From 1140aa187ecb82fc95375df2e70759270f594b69 Mon Sep 17 00:00:00 2001 From: akhumphrey Date: Thu, 28 Mar 2024 22:25:15 +1300 Subject: [PATCH] NTO-180 merged upstream changes (#10) * Add docker compose * Add apcu for PHP 5.5+ * Disable APC on PHP 7+ as APCu 5 is not supported * Add ability to use a custom test runtime Co-authored-by: Thomas * Use GitHub actions for Continuous Integration tests Remove TravisCI integration * Fix test for /bin/ls file mimetype guessing, using application/x-pie-executable * PHP 8.1 > internal_method_return_types https://wiki.php.net/rfc/internal_method_return_types PHP 8.0 added return type for abstract methods on Iterator, ArrayAccess, Countable, IteratorAggregate PHP 8.1 made non implementation as a Deprecated Warning PHP 9.0 (no release date at this moment) will drop the support. Temporary Fix : adding this Attribute Will drop the Deprecated warning. Adding return type will break compatibility before PHP 7.4, Return type has been added on PHP 7.0, but "mixed" special type is required, and it has been added on PHP 7.4. In order to be compatible with future PHP 9.0, once it will be release, we will have to drop the support to PHP Version before 7.4 Currently a lot of Unix distribution in LTS are running a PHP Version older than 7.4 so moving to the final solution of "add return type" should break a lot of setup for the moment. * PHP 8.1 > Serializable Phase Out https://wiki.php.net/rfc/phase_out_serializable PHP 7.4 add a new Serialize mecanism PHP 8.1 made old method, "Serializable implementation" deprecated PHP 9.0 (no release date at this moment) will drop the support. Temporary Fix: Adding both method serialize/unserialize and __serialize/__unserialize In order to be compatible with future PHP 9.0, once it will be release, we will have to drop the support to PHP Version before 7.4. Currently a lot of Unix distribution in LTS are running a PHP Version older than 7.4 so moving to the final solution of "add return type" should break a lot of setup for the moment. Each class has been serialized/unserialized and compared on PHP 8.1.2 and 5.6.30 * PHP 8.0 & 8.1 > Deprecated of null to non-nullable internal function parameters Mainly ensure use of string instead of null / false by casting the variable into (string) Also fix method/function arguments with default value must be at the end. Thanks to @teymour https://github.com/FriendsOfSymfony1/symfony1/pull/265/commits/cba71a47894ca8a89f2a88a5cd9dcb637129dbeb * PHP 8.1 > strftime deprecated. 2 possible workaround, use partial implementation with php date method or use IntlDateFormatter. As symfony1 is not intended to evolve, it should not rely on currently unused PHP-Extension (nor update composer.json). I propose a fix to replace "strftime" by "date", with a translation of format for PHP 8.1+ It will lose the ability of translating date of logs (does anybody use it ?) and it will deprecated a few strftime format (probably not used) Performances should remains OK I only tested it with a few formats (the default one and a few others) If you need some missing strftime formats, please add them. * PHP 8.1 > Unit Test sfException> fileExcerpt file can be null, and PHP 8.1 do not allow null on is_readable() sfBrowser> Move sf_test conf before getContext, because getContext can throw some sfException, which will raise some printStackTrace, hidden by another Exception "header already sent ..." lime.php> some trace can have no "file" (internal methods call) lime.php> handle_exception can handle Error/Throwable, not avaialble under php7.2: remove typing sfTestFunctionalBase> can throw exception Fix Select Unit test NewActivePendingExpired. DomDocument on recent php return a list of values, not concatened ones. Fix SessionStorage UnitTest. sfSessionStorage could not be restarted. Flag $sessionStarted as false when shutdown to avoid error during unit test which can start several sfSessionStorage Storage need to be shutdown to avoid: PHP Warning: session_name(): Session name cannot be changed when a session is active * Fix lime message: "An uncaught exception has been thrown" do not have "error" value uncaught exception does not populate error field * PHP 8.1 > uasort(): Returning bool from comparison function is deprecated, return an integer less than, equal to, or greater than zero * Fix ValueError: DOMDocument::loadHTML(): Argument #1 ($source) must not be empty * PHP 8.0 > fread()/count() behavior ValueError: fread(): Argument #2 ($length) must be greater than 0 TypeError: count(): Argument #1 ($value) must be of type Countable|array Foo Given Use Symfony Polyfill https://github.com/symfony/polyfill/commit/d330c0094a47d8edceeea1ed553d6e08215a9fc2 TypeError: count(): Argument #1 ($value) must be of type Countable|array, string given Do not use Symfony pollyfill, is_array is enought * Fix Declaration of sfPearRestTest::downloadHttp($url, $lastmodified = null, $accept = false) must be compatible with sfPearRest::downloadHttp($url, $lastmodified = null, $accept = false, $channel = false) * PHP 8.0 > mktime update 8.0.0 hour is no longer optional. 8.0.0 minute, second, month, day and year are nullable now. * Fix sfWebResponse->getContentType() return a string not an array * Fix sfDoctrineTester, string cannot be accessed as array * PHP 8.0 > Fix is_numeric behavior with trailing empty char Numeric strings ending with whitespace ("42 ") will now return true. Previously, false was return instead. Use same fix has main maintened Yaml lib : https://github.com/symfony/yaml/commit/4152e36b0f305c2a57aa0233dee56ec27bca4f06 + performance improvement https://github.com/symfony/yaml/commit/2b5f2ae892b489e51d81616fbc475c8238b533dc * PHP 8.0 > String to Number Comparison. When $previousIndent was equal to 0, and $matches['indent'] = " " PHP(before 8.0)> (0 != " ") ==> false PHP8.0+ > (0 != " ") ==> true In order to keep "false" value we avoid "0" as a valid value. More details here why here: https://www.php.net/manual/en/migration80.incompatible.php * PHP 8.1 > Change support to PHP 8.1 * Fix UnitTest application/x-sharedlib /bin/ls can be reported as: - application/x-sharedlib - application/x-executable - application/x-pie-executable * PHP 8.1 > mysqli_report revert to off https://php.watch/versions/8.1/mysqli-error-mode * Refactor code and apply Coding Style fixes * PHP 8.1 > Better MYSQLI_REPORT_OFF implementations for php8.1 compat Thanks @mentalstring * PHP 8.1 > remove full_path from uploads added on PHP v8.1 * Fix use of null on string parameter on multiple classes * Github Actions: enable testing on PHP v8.0 and v8.1 (for PRs too) * test environment for php 8.2 * PHP 8.2 > Using ${var} in strings is deprecated, use {$var} instead. * PHP 8.2 > Creation of dynamic property Class::$property is deprecated * PHP 8.0 > Uncaught ArgumentCountError: Too few arguments to function * PHP 8.0 > Trying to access array offset on value of type bool * PHP 8.0 > Passing null to parameter #1 ($haystack) of type string is deprecated * set symfony version to 1.5.15-dev * PHP 8.0 > Class name must be a valid object or a string in case the controller does not exist. * PHP 8.0 > Fix undefined array key * PHP 8.1 > Fix some more null on string parameter * Prepared release 1.5.15 * Add(changelog) Add v1.5.15 release date to Changelog file * Add(versioning) Add v1.5.16-dev as next release * Fix(deprecations) Fix deprecations in sfMessageSource_Aggregate (#277) * Fix(deprecations) Fix deprecations in sfMessageSource_Aggregate, add return types from implemented sfIMessageSource * Add(linting) Add code linting to GitHub workflow, use php-cs-fixer * Fix(php-cs) Fix php-cs styles according to configuration * Add(gitattributes) Add .gitattributes to repository * imported upstream php-cs-fixer configuration * initial pass of php-cs-fixer * updated config * updated config * updated config * updated config * imported routing fixes from `master` * removed `7.4` and `8.0` test targets * fixed `long_to_shorthand_operator` warnings * temporarily disabled testing * removed route caching * fixed coding standards issues * re-fixed more coding standards issues * Fix: avoid creating dynamic property $options in sfViewCacheManager (#290) Dynamic properties are deprecated since PHP8.2 * Update(github) Update github workflows, include cache for composer install * Fix(php-cs-fixer) Fix php-cs-fixer warnings, according to new checks * add php8.3 * Fix(php-cs-fix) fix php-cs-fix single_space_around_construct warning * Fix(php-cs-fixer) Fix php-cs-fixer to v3.45 and apply code fixes * Fix(deprecation) preg_match_all requires string parameter (#298) * Fix APC cache tests - Using negative TTLs to force the immediate expiration of keys, while convenient in tests, doesn't work consistently with APC and is an undocumented feature. Using a low TTL and sleep() is what guarantees that it works for APC. See https://github.com/krakjoe/apcu/issues/184 - The setting apc.use_request_time interferes with key expiration when running on the CLI. Making sure it always has a sensible value for running the tests. See https://github.com/krakjoe/apcu/pull/392 * Add APCu support Support for the APCu extension (through sfAPCuCache) as an alternative to APC, which no longer works with recent versions of PHP. * Fix sfCacheSessionStorageTest with PHP>=7.2 From PHP 7.2 onward, session functions are stricter and may not work if output/headers have already been sent out. Using output buffering prevents this issue. * Remove test dependency on APC Replace the use of sfAPCCache with sfFileCache in sfCacheSessionStorageTest so that it doesn't depend on APC being available. * Fix deprecation on stropos() usage on sfDebug::shortenFilePath (#299) Fix PHP v8.x deprecation on strpos() usage with `null` as first parameter * Fix strpos() deprecation on sfCacheSessionStorage check for cookie * Fix setrawcookie() deprecation on null parameter (#304) * Fix str_replace() deprecated null parameter on sfNumberFormat * Declare $params var * Replace default with 0 * removed some automated testing for old php versions * updated `php-cs-fixer` config * Update README Fix build badge, update supported PHP version and other minor tweaks. * Fix link to GitHub pipeline badge * fix(config) sfCacheConfigHandler: There is no fourth argument. Nice catch phpstan! * Fix PHP8.1 sfForm - Unsupported operand types: array + null on sfForm::updateValues() Avoid error: Fatal error: Uncaught TypeError: Unsupported operand types: array + null in lib\form\sfForm.class.php:319 Step to reproduce : $form = new sfForm(); $form->updateValues(array('foo' => 'value')); PHP 5.3 coding style May use sfForm::getValues(), but as sfForm::updateValues() is a hack, it could be used before bind ($this->isBound = true); * fix(phpdoc) remove html code from throws phpdoc. phpstan don't like this * fix(phpdoc) remove version tag * applied php-cs-fixer * added missing properties * PHP 8.3 deprecated errors fixed (#320) * Update min PHP requirement to v7.4 or v8.1 * Remove PHP v8.0 from CI workflow * Updated gh workflow to use latest actions * Backported display_errors-handling to sf1 * removed duplicate class properties * Set min versions of swiftmailer to 5.4.13 and 6.2.5 and updated swiftmailer submodule (#331) * Update min versions of swiftmailer to v5.4.13 or v6.2.5 * Update swiftmailer code on submodule to v5.4.13 * Sync changelog with latest releases (#337) * Sync changelog with latest releases * Remove(legacy): Remove unsupported PHP docker images * Remove(legacy): drop sfAPCCache cache as apc extension does not exist anymore Please use sfAPCUCache instead * Fix(docblock): fix typo in check_configuration.php docblock * Update(check-config): use PHP constant for version check on check_configuration.php file * Remove(legacy): delete checks for 'magic_quotes_gpc' and 'register_globals' ini settings, as removed on PHP v5.4 * Remove(legacy): delete EAccelerator cache, the extension is not existing for php v7.4 See: https://github.com/eaccelerator/eaccelerator, where the following message is shown: > This project is deprecated and does not work with anything newer than PHP 5.3. > Please use a recent version of PHP with OPcache instead! * Remove(legacy): drop XCache support, as the extension is not available for PHP >= 7.4 * Remove(legacy): delete check for PHP < 5.2 in tests for mime_content_type bug * Remove(legacy): drop PHP v5.3 check for SQLite version match * Remove(legacy): drop PHP v5.4 check and compatibility layer on sfWebRequest * Remove(legacy): drop PHP v5.3 check on sfRoute This removes a preliminary fix for a legacy PHP 5.3. issue with regexp excaping PHP bug reference: http://bugs.php.net/bug.php?id=47229 * Update: Update php-cs-fixer to v3.51 Apply rule fixes * Update: php-cs-fixer, enable short array syntax * Update: move php-cs-fixer cache under .cache folder * Update: run php-cs-fixer on PHP v7.4 as min supported version * Update: GitHub actions to run php-cs-fixer only on relevant changed files * Hotfix: Add type checking for deserialized data in sfParameterHolder and sfNamespacedParameterHolder (CVE-2024-28861) * Update php-cs-fixer to v3.52 * Remove(legacy): drop sf*Cache implementations for APC, XCache and EAccelerator extensions * Phpstan: fix warnings on sfAPCiCache implementation, add docblocks and returns * Phpstan: fix warnings on sfFileCache and sfMemcache implementation, add missing returns * Phpstan: fix missing sfTask* return statement * [widget] fix return statement missing (#349) * [validator] fix return statement missing (#352) * [view] fix return statement missing on ParamHolder and CacheManager (#350) * [task] Fix return statement missing on some tasks (#353) * [util] fix missing return statement and docblock on sfContext class (#351) * applied upstream php-cs-fixer configuration * corrected json format * use `php8.2` when linting * don't build php8.1 * reverted many changes back to upstream equivalents * removed upstream submodule * replaced submodule with our fork * updated tests to match custom functionality * only test php82 * corrected number of expected tests * only use php8.2 for github actions * explicitly apply `nullable_type_declaration_for_default_null_value` * attributes don't use `\` * corrected method signatures --------- Co-authored-by: Alexandre Quercia Co-authored-by: Thomas Co-authored-by: Emanuele Panzeri Co-authored-by: Tybaze Co-authored-by: Paulo Magalhaes Co-authored-by: Thomas A. Hirsch Co-authored-by: Karoly Gossler Co-authored-by: Vincent Mariani <541354+vimar@users.noreply.github.com> Co-authored-by: iricketson Co-authored-by: Ian Ricketson Co-authored-by: Sergei Miami Co-authored-by: darkpills <> --- .docker/Dockerfile | 68 + .editorconfig | 6 +- .env.dist | 5 + .gitattributes | 11 + .github/workflows/continuous-integration.yml | 59 + .github/workflows/lint.yml | 43 + .gitignore | 2 + .gitmodules | 10 +- .php-cs-fixer.dist.php | 38 + .travis.yml | 56 - CHANGELOG.md | 65 + README.md | 53 +- WHATS_NEW.md | 5 +- composer.json | 6 +- data/bin/changelog.php | 35 +- data/bin/check_configuration.php | 82 +- data/bin/release.php | 96 +- data/bin/sandbox_installer.php | 16 +- docker-compose.yml | 66 + lib/action/sfAction.class.php | 951 +++--- lib/action/sfActionStack.class.php | 169 +- lib/action/sfActionStackEntry.class.php | 134 +- lib/action/sfActions.class.php | 72 +- lib/action/sfComponent.class.php | 805 ++--- lib/action/sfComponents.class.php | 25 +- lib/addon/sfData.class.php | 180 +- lib/addon/sfPager.class.php | 1138 ++++--- lib/autoload/sfAutoload.class.php | 347 +-- lib/autoload/sfAutoloadAgain.class.php | 182 +- lib/autoload/sfCoreAutoload.class.php | 971 +++--- lib/autoload/sfSimpleAutoload.class.php | 497 ++- lib/cache/sfAPCCache.class.php | 220 -- lib/cache/sfAPCuCache.class.php | 204 ++ lib/cache/sfCache.class.php | 425 ++- lib/cache/sfEAcceleratorCache.class.php | 192 -- lib/cache/sfFileCache.class.php | 528 ++-- lib/cache/sfFunctionCache.class.php | 158 +- lib/cache/sfMemcacheCache.class.php | 463 ++- lib/cache/sfNoCache.class.php | 127 +- lib/cache/sfSQLiteCache.class.php | 501 ++-- lib/cache/sfXCacheCache.class.php | 229 -- lib/command/cli.php | 46 +- lib/command/sfAnsiColorFormatter.class.php | 179 +- lib/command/sfCommandApplication.class.php | 1168 ++++---- lib/command/sfCommandArgument.class.php | 192 +- lib/command/sfCommandArgumentSet.class.php | 265 +- .../sfCommandArgumentsException.class.php | 5 +- lib/command/sfCommandException.class.php | 5 +- lib/command/sfCommandLogger.class.php | 71 +- lib/command/sfCommandManager.class.php | 619 ++-- lib/command/sfCommandOption.class.php | 288 +- lib/command/sfCommandOptionSet.class.php | 285 +- lib/command/sfFormatter.class.php | 161 +- .../sfSymfonyCommandApplication.class.php | 216 +- .../sfApplicationConfiguration.class.php | 1146 ++++--- lib/config/sfAutoloadConfigHandler.class.php | 272 +- lib/config/sfCacheConfigHandler.class.php | 170 +- lib/config/sfCompileConfigHandler.class.php | 117 +- lib/config/sfConfig.class.php | 132 +- lib/config/sfConfigCache.class.php | 586 ++-- lib/config/sfConfigHandler.class.php | 189 +- lib/config/sfDatabaseConfigHandler.class.php | 208 +- ...sfDefineEnvironmentConfigHandler.class.php | 216 +- lib/config/sfFactoryConfigHandler.class.php | 463 +-- lib/config/sfFilterConfigHandler.class.php | 314 +- lib/config/sfGeneratorConfigHandler.class.php | 117 +- lib/config/sfPluginConfiguration.class.php | 356 ++- .../sfPluginConfigurationGeneric.class.php | 17 +- lib/config/sfProjectConfiguration.class.php | 1059 ++++--- lib/config/sfRootConfigHandler.class.php | 155 +- lib/config/sfRoutingConfigHandler.class.php | 168 +- lib/config/sfSecurityConfigHandler.class.php | 71 +- lib/config/sfServiceConfigHandler.class.php | 87 +- .../sfSimpleYamlConfigHandler.class.php | 52 +- lib/config/sfViewConfigHandler.class.php | 503 ++-- lib/config/sfYamlConfigHandler.class.php | 226 +- .../default/actions/actions.class.php | 83 +- .../default/templates/defaultLayout.php | 18 +- .../default/templates/disabledSuccess.php | 6 +- .../default/templates/error404Success.php | 10 +- .../default/templates/indexSuccess.php | 6 +- .../default/templates/loginSuccess.php | 6 +- .../default/templates/moduleSuccess.php | 10 +- .../default/templates/secureSuccess.php | 4 +- lib/controller/sfController.class.php | 844 +++--- lib/controller/sfFrontWebController.class.php | 57 +- lib/controller/sfWebController.class.php | 330 +- lib/database/sfDatabase.class.php | 287 +- lib/database/sfDatabaseManager.class.php | 183 +- lib/database/sfMySQLDatabase.class.php | 110 + lib/database/sfMySQLiDatabase.class.php | 88 +- lib/database/sfPDODatabase.class.php | 137 +- lib/database/sfPostgreSQLDatabase.class.php | 85 +- lib/debug/sfDebug.class.php | 418 ++- lib/debug/sfTimer.class.php | 111 +- lib/debug/sfTimerManager.class.php | 78 +- lib/debug/sfWebDebug.class.php | 421 ++- lib/debug/sfWebDebugPanel.class.php | 327 +- lib/debug/sfWebDebugPanelCache.class.php | 42 +- lib/debug/sfWebDebugPanelConfig.class.php | 100 +- lib/debug/sfWebDebugPanelLogs.class.php | 204 +- lib/debug/sfWebDebugPanelMailer.class.php | 131 +- lib/debug/sfWebDebugPanelMemory.class.php | 25 +- .../sfWebDebugPanelSymfonyVersion.class.php | 23 +- lib/debug/sfWebDebugPanelTimer.class.php | 108 +- lib/debug/sfWebDebugPanelView.class.php | 565 ++-- lib/escaper/sfOutputEscaper.class.php | 377 ++- .../sfOutputEscaperArrayDecorator.class.php | 334 ++- .../sfOutputEscaperGetterDecorator.class.php | 61 +- ...sfOutputEscaperIteratorDecorator.class.php | 254 +- .../sfOutputEscaperObjectDecorator.class.php | 183 +- lib/escaper/sfOutputEscaperSafe.class.php | 95 +- lib/event/sfEvent.class.php | 285 +- lib/event/sfEventDispatcher.class.php | 221 +- lib/exception/data/error.atom.php | 4 +- lib/exception/data/error.css.php | 2 +- lib/exception/data/error.html.php | 12 +- lib/exception/data/error.js.php | 2 +- lib/exception/data/error.json.php | 12 +- lib/exception/data/error.rdf.php | 4 +- lib/exception/data/error.txt.php | 2 +- lib/exception/data/error.xml.php | 4 +- lib/exception/data/exception.atom.php | 4 +- lib/exception/data/exception.css.php | 12 +- lib/exception/data/exception.html.php | 20 +- lib/exception/data/exception.js.php | 12 +- lib/exception/data/exception.json.php | 22 +- lib/exception/data/exception.rdf.php | 4 +- lib/exception/data/exception.txt.php | 18 +- lib/exception/data/exception.xml.php | 14 +- lib/exception/data/unavailable.php | 12 +- lib/exception/sfCacheException.class.php | 5 +- .../sfConfigurationException.class.php | 5 +- lib/exception/sfControllerException.class.php | 5 +- lib/exception/sfDatabaseException.class.php | 5 +- lib/exception/sfError404Exception.class.php | 52 +- lib/exception/sfException.class.php | 747 +++-- lib/exception/sfFactoryException.class.php | 5 +- lib/exception/sfFileException.class.php | 5 +- lib/exception/sfFilterException.class.php | 5 +- lib/exception/sfForwardException.class.php | 5 +- .../sfInitializationException.class.php | 5 +- lib/exception/sfParseException.class.php | 5 +- lib/exception/sfRenderException.class.php | 5 +- lib/exception/sfSecurityException.class.php | 5 +- lib/exception/sfStopException.class.php | 17 +- lib/exception/sfStorageException.class.php | 5 +- lib/exception/sfViewException.class.php | 5 +- lib/filter/sfBasicSecurityFilter.class.php | 145 +- lib/filter/sfCacheFilter.class.php | 317 +- lib/filter/sfCommonFilter.class.php | 67 +- lib/filter/sfExecutionFilter.class.php | 252 +- lib/filter/sfFilter.class.php | 256 +- lib/filter/sfFilterChain.class.php | 108 +- lib/filter/sfRenderingFilter.class.php | 56 +- lib/form/addon/sfFormFilter.class.php | 3 - lib/form/addon/sfFormObject.class.php | 449 ++- lib/form/addon/sfFormSymfony.class.php | 148 +- lib/form/sfForm.class.php | 2656 ++++++++--------- lib/form/sfFormField.class.php | 536 ++-- lib/form/sfFormFieldSchema.class.php | 389 ++- lib/generator/sfGenerator.class.php | 346 ++- lib/generator/sfGeneratorManager.class.php | 170 +- lib/generator/sfModelGenerator.class.php | 724 +++-- .../sfModelGeneratorConfiguration.class.php | 881 +++--- ...ModelGeneratorConfigurationField.class.php | 424 ++- .../sfModelGeneratorHelper.class.php | 85 +- lib/helper/AssetHelper.php | 470 ++- lib/helper/CacheHelper.php | 60 +- lib/helper/DateHelper.php | 208 +- lib/helper/DebugHelper.php | 7 +- lib/helper/EscapingHelper.php | 32 +- lib/helper/HelperHelper.php | 8 +- lib/helper/I18NHelper.php | 46 +- lib/helper/JavascriptBaseHelper.php | 131 +- lib/helper/NumberHelper.php | 30 +- lib/helper/PartialHelper.php | 327 +- lib/helper/TagHelper.php | 140 +- lib/helper/TextHelper.php | 324 +- lib/helper/UrlHelper.php | 615 ++-- lib/i18n/Gettext/MO.php | 167 +- lib/i18n/Gettext/PO.php | 70 +- lib/i18n/Gettext/TGettext.class.php | 162 +- .../sfI18nApplicationExtract.class.php | 100 +- lib/i18n/extract/sfI18nExtract.class.php | 343 ++- .../sfI18nExtractorInterface.class.php | 19 +- .../extract/sfI18nModuleExtract.class.php | 89 +- lib/i18n/extract/sfI18nPhpExtractor.class.php | 160 +- .../extract/sfI18nYamlExtractor.class.php | 3 - .../sfI18nYamlGeneratorExtractor.class.php | 142 +- .../sfI18nYamlValidateExtractor.class.php | 133 +- lib/i18n/sfChoiceFormat.class.php | 275 +- lib/i18n/sfCultureInfo.class.php | 1506 +++++----- lib/i18n/sfDateFormat.class.php | 1453 ++++----- lib/i18n/sfDateTimeFormatInfo.class.php | 983 +++--- lib/i18n/sfI18N.class.php | 716 +++-- lib/i18n/sfIMessageSource.class.php | 189 +- lib/i18n/sfMessageFormat.class.php | 372 ++- lib/i18n/sfMessageSource.class.php | 502 ++-- lib/i18n/sfMessageSource_Aggregate.class.php | 318 +- lib/i18n/sfMessageSource_Database.class.php | 302 +- lib/i18n/sfMessageSource_File.class.php | 313 +- lib/i18n/sfMessageSource_MySQL.class.php | 454 +++ lib/i18n/sfMessageSource_MySQLi.class.php | 627 ++-- lib/i18n/sfMessageSource_SQLite.class.php | 518 ++-- lib/i18n/sfMessageSource_SQLite3.class.php | 538 ++-- lib/i18n/sfMessageSource_XLIFF.class.php | 648 ++-- lib/i18n/sfMessageSource_gettext.class.php | 508 ++-- lib/i18n/sfNumberFormat.class.php | 452 ++- lib/i18n/sfNumberFormatInfo.class.php | 1315 ++++---- lib/log/sfAggregateLogger.class.php | 154 +- lib/log/sfConsoleLogger.class.php | 27 +- lib/log/sfEventLogger.class.php | 39 +- lib/log/sfFileLogger.class.php | 370 +-- lib/log/sfLogger.class.php | 506 ++-- lib/log/sfLoggerInterface.class.php | 17 +- lib/log/sfLoggerWrapper.class.php | 46 +- lib/log/sfNoLogger.class.php | 41 +- lib/log/sfPsrLoggerAdapter.class.php | 250 +- lib/log/sfStreamLogger.class.php | 100 +- lib/log/sfVarLogger.class.php | 283 +- lib/log/sfWebDebugLogger.class.php | 288 +- lib/mailer/sfMailer.class.php | 593 ++-- .../sfMailerMessageLoggerPlugin.class.php | 110 +- lib/mailer/sfNoMailer.class.php | 104 +- lib/plugin/sfPearConfig.class.php | 15 +- lib/plugin/sfPearDownloader.class.php | 22 +- lib/plugin/sfPearEnvironment.class.php | 403 ++- lib/plugin/sfPearFrontendPlugin.class.php | 72 +- lib/plugin/sfPearRest.class.php | 19 +- lib/plugin/sfPearRest10.class.php | 21 +- lib/plugin/sfPearRest11.class.php | 21 +- lib/plugin/sfPearRestPlugin.class.php | 338 +-- .../sfPluginDependencyException.class.php | 5 +- lib/plugin/sfPluginException.class.php | 5 +- lib/plugin/sfPluginManager.class.php | 785 +++-- ...uginRecursiveDependencyException.class.php | 5 +- lib/plugin/sfPluginRestException.class.php | 5 +- lib/plugin/sfSymfonyPluginManager.class.php | 369 ++- .../sfDoctrinePlugin/config/installer.php | 2 +- .../sfDoctrinePluginConfiguration.class.php | 143 +- .../template/sfDoctrineFormBaseTemplate.php | 1 - ...ctrineFormGeneratedInheritanceTemplate.php | 1 - .../sfDoctrineFormGeneratedTemplate.php | 1 - .../template/sfDoctrineFormPluginTemplate.php | 1 - .../template/sfDoctrineFormTemplate.php | 1 - .../template/sfDoctrinePluginFormTemplate.php | 1 - .../sfDoctrineFormFilterBaseTemplate.php | 1 - ...FormFilterGeneratedInheritanceTemplate.php | 1 - .../sfDoctrineFormFilterGeneratedTemplate.php | 1 - .../sfDoctrineFormFilterPluginTemplate.php | 1 - .../template/sfDoctrineFormFilterTemplate.php | 1 - .../sfDoctrinePluginFormFilterTemplate.php | 1 - .../admin/parts/configuration.php | 9 +- .../admin/skeleton/actions/actions.class.php | 5 +- .../admin/skeleton/lib/configuration.php | 1 - .../admin/skeleton/lib/helper.php | 1 - .../admin/template/actions/actions.class.php | 29 +- .../admin/template/lib/helper.php | 1 - .../skeleton/actions/actions.class.php | 1 - .../template/actions/actions.class.php | 17 +- .../lib/cli/sfDoctrineCli.class.php | 94 +- .../sfDoctrineConnectionListener.class.php | 30 +- .../sfDoctrineConnectionProfiler.class.php | 311 +- .../lib/database/sfDoctrineDatabase.class.php | 226 +- .../debug/sfWebDebugPanelDoctrine.class.php | 236 +- .../lib/form/sfFormDoctrine.class.php | 661 ++-- .../lib/form/sfFormFilterDoctrine.class.php | 490 ++- .../lib/generator/sfDoctrineColumn.class.php | 608 ++-- .../sfDoctrineFormFilterGenerator.class.php | 619 ++-- .../sfDoctrineFormGenerator.class.php | 1223 ++++---- .../generator/sfDoctrineGenerator.class.php | 433 ++- .../lib/mailer/Swift_DoctrineSpool.class.php | 189 +- .../lib/pager/sfDoctrinePager.class.php | 364 ++- .../lib/record/sfDoctrineRecord.class.php | 404 ++- .../sfDoctrineRecordI18nFilter.class.php | 72 +- .../lib/routing/sfDoctrineRoute.class.php | 186 +- .../sfDoctrineRouteCollection.class.php | 8 +- .../lib/sfDoctrineException.class.php | 7 +- .../lib/task/sfDoctrineBaseTask.class.php | 286 +- .../lib/task/sfDoctrineBuildDbTask.class.php | 78 +- .../task/sfDoctrineBuildFiltersTask.class.php | 85 +- .../task/sfDoctrineBuildFormsTask.class.php | 98 +- .../task/sfDoctrineBuildModelTask.class.php | 159 +- .../task/sfDoctrineBuildSchemaTask.class.php | 61 +- .../lib/task/sfDoctrineBuildSqlTask.class.php | 65 +- .../lib/task/sfDoctrineBuildTask.class.php | 413 ++- .../sfDoctrineCleanModelFilesTask.class.php | 161 +- .../lib/task/sfDoctrineCompileTask.class.php | 88 +- .../sfDoctrineConfigureDatabaseTask.class.php | 90 +- .../sfDoctrineCreateModelTablesTask.class.php | 115 +- .../lib/task/sfDoctrineDataDumpTask.class.php | 98 +- .../lib/task/sfDoctrineDataLoadTask.class.php | 93 +- .../sfDoctrineDeleteModelFilesTask.class.php | 204 +- .../lib/task/sfDoctrineDqlTask.class.php | 241 +- .../lib/task/sfDoctrineDropDbTask.class.php | 112 +- .../sfDoctrineGenerateAdminTask.class.php | 272 +- .../sfDoctrineGenerateMigrationTask.class.php | 106 +- ...DoctrineGenerateMigrationsDbTask.class.php | 68 +- ...ctrineGenerateMigrationsDiffTask.class.php | 66 +- ...rineGenerateMigrationsModelsTask.class.php | 60 +- ...ctrineGenerateModuleForRouteTask.class.php | 133 +- .../sfDoctrineGenerateModuleTask.class.php | 302 +- .../task/sfDoctrineInsertSqlTask.class.php | 61 +- .../lib/task/sfDoctrineMigrateTask.class.php | 182 +- .../lib/test/sfTesterDoctrine.class.php | 250 +- .../sfValidatorDoctrineChoice.class.php | 172 +- .../sfValidatorDoctrineUnique.class.php | 228 +- .../sfDoctrinePlugin/lib/vendor/doctrine | 2 +- .../sfWidgetFormDoctrineArrayChoice.class.php | 107 +- .../sfWidgetFormDoctrineChoice.class.php | 182 +- .../sfDoctrinePlugin/test/bin/coverage.php | 13 +- .../sfDoctrinePlugin/test/bin/prove.php | 23 +- .../test/bootstrap/functional.php | 42 +- .../sfDoctrinePlugin/test/bootstrap/unit.php | 10 +- .../test/functional/ActionRedirectTest.php | 15 +- .../test/functional/AdminGenBrowser.class.php | 482 ++- .../test/functional/AdminGenTest.php | 10 +- .../test/functional/EnvironmentSetupTest.php | 21 +- .../test/functional/FormGeneratorTest.php | 34 +- .../test/functional/FormTest.php | 101 +- .../test/functional/I18nTest.php | 316 +- .../test/functional/PagerTest.php | 19 +- .../test/functional/RouteTest.php | 98 +- .../test/functional/SchemaMergeTest.php | 27 +- .../test/functional/Ticket/5269Test.php | 24 +- .../test/functional/Ticket/7774Test.php | 10 +- .../test/functional/UniqueTest.php | 17 +- .../test/functional/UploadTest.php | 49 +- .../config/backendConfiguration.class.php | 6 +- .../actions/actions.class.php | 25 +- .../templates/indexSuccess.php | 4 +- .../my_articles/actions/actions.class.php | 8 +- ...y_articlesGeneratorConfiguration.class.php | 3 - .../lib/my_articlesGeneratorHelper.class.php | 3 - .../apps/backend/templates/layout.php | 12 +- .../config/frontendConfiguration.class.php | 6 +- .../articles/actions/actions.class.php | 121 +- .../articles/templates/editSuccess.php | 38 +- .../articles/templates/indexSuccess.php | 14 +- .../articles/templates/showSuccess.php | 2 +- .../attachment/actions/actions.class.php | 77 +- .../attachment/templates/editableInput.php | 4 +- .../attachment/templates/indexInput.php | 4 +- .../apps/frontend/templates/layout.php | 12 +- .../config/ProjectConfiguration.class.php | 97 +- .../doctrine/ArticleFormFilter.class.php | 12 +- .../ArticleTranslationFormFilter.class.php | 12 +- .../doctrine/AttachmentFormFilter.class.php | 9 +- .../doctrine/AuthorFormFilter.class.php | 12 +- ...horInheritanceConcreteFormFilter.class.php | 9 +- .../AuthorInheritanceFormFilter.class.php | 12 +- .../doctrine/BaseFormFilterDoctrine.class.php | 12 +- .../doctrine/BlogArticleFormFilter.class.php | 17 +- ...BlogArticleTranslationFormFilter.class.php | 9 +- .../doctrine/BlogAuthorFormFilter.class.php | 17 +- .../doctrine/CamelCaseFormFilter.class.php | 12 +- .../DefaultValueTestFormFilter.class.php | 9 +- .../FormGeneratorTest2FormFilter.class.php | 12 +- .../filter/doctrine/GroupFormFilter.class.php | 12 +- .../doctrine/PermissionFormFilter.class.php | 12 +- .../doctrine/ProfileFormFilter.class.php | 12 +- .../doctrine/ResourceTypeFormFilter.class.php | 9 +- .../SettingFormFilter.class.php | 9 +- .../doctrine/SubscriptionFormFilter.class.php | 12 +- .../doctrine/UniqueTestFormFilter.class.php | 12 +- .../filter/doctrine/UserFormFilter.class.php | 12 +- .../fixtures/lib/form/BaseForm.class.php | 5 +- .../lib/form/doctrine/ArticleForm.class.php | 14 +- .../doctrine/ArticleTranslationForm.class.php | 12 +- .../form/doctrine/AttachmentForm.class.php | 40 +- .../lib/form/doctrine/AuthorForm.class.php | 12 +- .../AuthorInheritanceConcreteForm.class.php | 17 +- .../doctrine/AuthorInheritanceForm.class.php | 12 +- .../form/doctrine/BaseFormDoctrine.class.php | 11 +- .../form/doctrine/BlogArticleForm.class.php | 17 +- .../BlogArticleTranslationForm.class.php | 9 +- .../form/doctrine/BlogAuthorForm.class.php | 17 +- .../lib/form/doctrine/CamelCaseForm.class.php | 12 +- .../doctrine/DefaultValueTestForm.class.php | 9 +- .../doctrine/FormGeneratorTestForm.class.php | 12 +- .../lib/form/doctrine/GroupForm.class.php | 12 +- .../form/doctrine/PermissionForm.class.php | 12 +- .../lib/form/doctrine/ProfileForm.class.php | 12 +- .../form/doctrine/ResourceTypeForm.class.php | 9 +- .../SettingsPlugin/SettingForm.class.php | 9 +- .../form/doctrine/SubscriptionForm.class.php | 12 +- .../form/doctrine/UniqueTestForm.class.php | 12 +- .../lib/form/doctrine/UserForm.class.php | 18 +- .../lib/model/doctrine/Article.class.php | 12 +- .../lib/model/doctrine/ArticleTable.class.php | 117 +- .../lib/model/doctrine/Attachment.class.php | 9 +- .../lib/model/doctrine/Author.class.php | 28 +- .../doctrine/AuthorInheritance.class.php | 12 +- .../AuthorInheritanceConcrete.class.php | 12 +- .../AuthorInheritanceConcreteTable.class.php | 6 +- .../doctrine/AuthorInheritanceTable.class.php | 6 +- .../lib/model/doctrine/AuthorTable.class.php | 46 +- .../lib/model/doctrine/BlogArticle.class.php | 9 +- .../lib/model/doctrine/BlogAuthor.class.php | 9 +- .../lib/model/doctrine/CamelCase.class.php | 12 +- .../model/doctrine/CamelCaseTable.class.php | 6 +- .../model/doctrine/DefaultValueTest.class.php | 16 +- .../doctrine/DefaultValueTestTable.class.php | 6 +- .../doctrine/FormGeneratorTest.class.php | 16 +- .../doctrine/FormGeneratorTest2.class.php | 12 +- .../FormGeneratorTest2Table.class.php | 6 +- .../doctrine/FormGeneratorTest3.class.php | 9 +- .../doctrine/FormGeneratorTestTable.class.php | 6 +- .../lib/model/doctrine/Group.class.php | 5 +- .../model/doctrine/GroupPermission.class.php | 5 +- .../doctrine/GroupPermissionTable.class.php | 5 +- .../lib/model/doctrine/GroupTable.class.php | 5 +- .../doctrine/ModelFromLinkedSchema.class.php | 9 +- .../ModelWithNumberInColumn.class.php | 9 +- .../lib/model/doctrine/Permission.class.php | 5 +- .../model/doctrine/PermissionTable.class.php | 5 +- .../lib/model/doctrine/Profile.class.php | 5 +- .../lib/model/doctrine/ProfileTable.class.php | 5 +- .../lib/model/doctrine/ResourceType.class.php | 9 +- .../doctrine/SettingsPlugin/Setting.class.php | 9 +- .../SettingsPlugin/SettingTable.class.php | 4 +- .../lib/model/doctrine/Subscription.class.php | 5 +- .../doctrine/SubscriptionTable.class.php | 5 +- .../lib/model/doctrine/UniqueTest.class.php | 9 +- .../model/doctrine/UniqueTestTable.class.php | 5 +- .../lib/model/doctrine/User.class.php | 12 +- .../lib/model/doctrine/UserGroup.class.php | 5 +- .../model/doctrine/UserGroupTable.class.php | 5 +- .../model/doctrine/UserPermission.class.php | 5 +- .../doctrine/UserPermissionTable.class.php | 5 +- .../lib/model/doctrine/UserTable.class.php | 47 +- .../fixtures/lib/myDoctrineRecord.class.php | 4 +- .../PluginSettingFormFilter.class.php | 3 - .../form/doctrine/PluginSettingForm.class.php | 3 - .../model/doctrine/PluginSetting.class.php | 12 +- .../doctrine/PluginSettingTable.class.php | 6 +- .../test/functional/fixtures/symfony | 4 +- .../test/functional/sfDoctrineRecordTest.php | 9 +- .../test/unit/form/sfFormDoctrineTest.php | 69 +- .../unit/form/sfFormFilterDoctrineTest.php | 151 +- .../test/unit/pager/sfDoctrinePagerTest.php | 13 +- .../test/unit/record/sfDoctrineRecordTest.php | 24 +- .../test/unit/sfDoctrineColumnTest.php | 47 +- .../test/unit/sfDoctrineDatabaseTest.php | 24 +- .../sfValidatorDoctrineChoiceTest.php | 5 +- .../sfWidgetFormDoctrineArrayChoiceTest.php | 11 +- .../widget/sfWidgetFormDoctrineChoiceTest.php | 17 +- lib/request/sfRequest.class.php | 618 ++-- lib/request/sfWebRequest.class.php | 1696 +++++------ lib/response/sfResponse.class.php | 326 +- lib/response/sfWebResponse.class.php | 1655 +++++----- lib/routing/sfObjectRoute.class.php | 338 +-- lib/routing/sfObjectRouteCollection.class.php | 354 ++- lib/routing/sfPatternRouting.class.php | 877 +++--- lib/routing/sfRequestRoute.class.php | 138 +- lib/routing/sfRoute.class.php | 1228 ++++---- lib/routing/sfRouteCollection.class.php | 94 +- lib/routing/sfRouting.class.php | 508 ++-- lib/service/sfServiceContainer.class.php | 311 +- .../sfServiceContainerBuilder.class.php | 526 ++-- .../sfServiceContainerDumper.class.php | 45 +- ...sfServiceContainerDumperGraphviz.class.php | 314 +- ...fServiceContainerDumperInterface.class.php | 5 +- .../sfServiceContainerDumperPhp.class.php | 504 ++-- .../sfServiceContainerInterface.class.php | 151 +- .../sfServiceContainerLoader.class.php | 158 +- .../sfServiceContainerLoaderArray.class.php | 175 +- ...fServiceContainerLoaderInterface.class.php | 5 +- lib/service/sfServiceDefinition.class.php | 443 ++- lib/service/sfServiceParameter.class.php | 42 +- lib/service/sfServiceReference.class.php | 42 +- lib/storage/sfCacheSessionStorage.class.php | 304 +- .../sfDatabaseSessionStorage.class.php | 325 +- lib/storage/sfMySQLSessionStorage.class.php | 210 ++ lib/storage/sfMySQLiSessionStorage.class.php | 228 +- lib/storage/sfNoStorage.class.php | 130 +- lib/storage/sfPDOSessionStorage.class.php | 266 +- .../sfPostgreSQLSessionStorage.class.php | 244 +- lib/storage/sfSessionStorage.class.php | 290 +- lib/storage/sfSessionTestStorage.class.php | 257 +- lib/storage/sfStorage.class.php | 189 +- lib/task/app/sfAppRoutesTask.class.php | 233 +- lib/task/cache/sfCacheClearTask.class.php | 339 +-- .../configure/sfConfigureAuthorTask.class.php | 76 +- .../generator/sfGenerateAppTask.class.php | 214 +- .../generator/sfGenerateModuleTask.class.php | 126 +- .../generator/sfGenerateProjectTask.class.php | 203 +- .../generator/sfGenerateTaskTask.class.php | 146 +- .../generator/sfGeneratorBaseTask.class.php | 5 +- .../module/module/actions/actions.class.php | 1 - .../config/ProjectConfiguration.class.php | 5 + .../project/lib/form/BaseForm.class.php | 3 +- lib/task/help/sfHelpTask.class.php | 177 +- lib/task/help/sfListTask.class.php | 254 +- lib/task/i18n/sfI18nExtractTask.class.php | 151 +- lib/task/i18n/sfI18nFindTask.class.php | 203 +- lib/task/log/sfLogClearTask.class.php | 43 +- lib/task/log/sfLogRotateTask.class.php | 247 +- .../plugin/sfPluginAddChannelTask.class.php | 51 +- lib/task/plugin/sfPluginBaseTask.class.php | 5 +- lib/task/plugin/sfPluginInstallTask.class.php | 113 +- lib/task/plugin/sfPluginListTask.class.php | 48 +- .../sfPluginPublishAssetsTask.class.php | 127 +- .../plugin/sfPluginUninstallTask.class.php | 67 +- lib/task/plugin/sfPluginUpgradeTask.class.php | 61 +- .../sfProjectClearControllersTask.class.php | 56 +- .../project/sfProjectDeployTask.class.php | 238 +- .../project/sfProjectDisableTask.class.php | 84 +- .../project/sfProjectEnableTask.class.php | 92 +- .../project/sfProjectOptimizeTask.class.php | 274 +- .../sfProjectPermissionsTask.class.php | 167 +- .../project/sfProjectSendEmailsTask.class.php | 55 +- .../project/sfProjectValidateTask.class.php | 115 +- .../sfDeprecatedClassesValidation.class.php | 127 +- ...atedConfigurationFilesValidation.class.php | 87 +- .../sfDeprecatedHelpersValidation.class.php | 119 +- .../sfDeprecatedMethodsValidation.class.php | 139 +- .../sfDeprecatedPluginsValidation.class.php | 73 +- .../sfDeprecatedSettingsValidation.class.php | 99 +- .../sfParameterHolderValidation.class.php | 79 +- .../project/validation/sfValidation.class.php | 172 +- lib/task/sfBaseTask.class.php | 866 +++--- lib/task/sfCommandApplicationTask.class.php | 379 ++- lib/task/sfFilesystem.class.php | 774 +++-- lib/task/sfTask.class.php | 1349 ++++----- lib/task/symfony/lime_symfony.php | 18 +- lib/task/symfony/sfSymfonyTestTask.class.php | 186 +- lib/task/test/sfLimeHarness.class.php | 38 +- lib/task/test/sfTestAllTask.class.php | 124 +- lib/task/test/sfTestBaseTask.class.php | 70 +- lib/task/test/sfTestCoverageTask.class.php | 128 +- lib/task/test/sfTestFunctionalTask.class.php | 140 +- lib/task/test/sfTestPluginTask.class.php | 71 +- lib/task/test/sfTestUnitTask.class.php | 134 +- lib/test/sfTestBrowser.class.php | 51 +- lib/test/sfTestFunctional.class.php | 88 +- lib/test/sfTestFunctionalBase.class.php | 842 +++--- lib/test/sfTester.class.php | 116 +- lib/test/sfTesterForm.class.php | 374 +-- lib/test/sfTesterMailer.class.php | 397 ++- lib/test/sfTesterRequest.class.php | 217 +- lib/test/sfTesterResponse.class.php | 762 +++-- lib/test/sfTesterUser.class.php | 160 +- lib/test/sfTesterViewCache.class.php | 173 +- lib/user/sfBasicSecurityUser.class.php | 439 ++- lib/user/sfSecurityUser.class.php | 77 +- lib/user/sfUser.class.php | 553 ++-- lib/util/sfBrowser.class.php | 259 +- lib/util/sfBrowserBase.class.php | 1732 +++++------ lib/util/sfCallable.class.php | 75 +- lib/util/sfClassManipulator.class.php | 497 ++- lib/util/sfContext.class.php | 1199 ++++---- lib/util/sfDomCssSelector.class.php | 980 +++--- lib/util/sfFinder.class.php | 1202 ++++---- lib/util/sfInflector.class.php | 180 +- .../sfNamespacedParameterHolder.class.php | 623 ++-- lib/util/sfParameterHolder.class.php | 338 +-- lib/util/sfToolkit.class.php | 958 +++--- .../sfValidatorI18nChoiceCountry.class.php | 59 +- .../sfValidatorI18nChoiceLanguage.class.php | 59 +- .../sfValidatorI18nChoiceTimezone.class.php | 33 +- lib/validator/sfValidatedFile.class.php | 1234 ++++---- lib/validator/sfValidatorAnd.class.php | 244 +- lib/validator/sfValidatorBase.class.php | 880 +++--- lib/validator/sfValidatorBoolean.class.php | 71 +- lib/validator/sfValidatorCSRFToken.class.php | 40 +- lib/validator/sfValidatorCallback.class.php | 55 +- lib/validator/sfValidatorChoice.class.php | 249 +- lib/validator/sfValidatorDate.class.php | 422 ++- lib/validator/sfValidatorDateRange.class.php | 80 +- lib/validator/sfValidatorDateTime.class.php | 19 +- lib/validator/sfValidatorDecorator.class.php | 277 +- lib/validator/sfValidatorEmail.class.php | 21 +- lib/validator/sfValidatorEqual.class.php | 79 +- lib/validator/sfValidatorError.class.php | 284 +- .../sfValidatorErrorSchema.class.php | 575 ++-- lib/validator/sfValidatorFile.class.php | 525 ++-- lib/validator/sfValidatorFileMulti.class.php | 22 +- .../sfValidatorFromDescription.class.php | 606 ++-- lib/validator/sfValidatorInteger.class.php | 92 +- lib/validator/sfValidatorIp.class.php | 151 +- lib/validator/sfValidatorNumber.class.php | 90 +- lib/validator/sfValidatorOr.class.php | 196 +- lib/validator/sfValidatorPass.class.php | 33 +- lib/validator/sfValidatorRegex.class.php | 91 +- lib/validator/sfValidatorSchema.class.php | 642 ++-- .../sfValidatorSchemaCompare.class.php | 273 +- .../sfValidatorSchemaFilter.class.php | 93 +- lib/validator/sfValidatorString.class.php | 87 +- lib/validator/sfValidatorTime.class.php | 214 +- lib/validator/sfValidatorUrl.class.php | 55 +- lib/vendor/lime/lime.php | 1 - lib/vendor/swiftmailer | 1 + lib/view/sfPHPView.class.php | 280 +- lib/view/sfPartialView.class.php | 229 +- lib/view/sfView.class.php | 1005 +++---- lib/view/sfViewCacheManager.class.php | 1741 +++++------ lib/view/sfViewParameterHolder.class.php | 340 +-- .../sfWidgetFormI18nChoiceCountry.class.php | 64 +- .../sfWidgetFormI18nChoiceCurrency.class.php | 64 +- .../sfWidgetFormI18nChoiceLanguage.class.php | 64 +- .../sfWidgetFormI18nChoiceTimezone.class.php | 60 +- .../i18n/sfWidgetFormI18nDate.class.php | 104 +- .../i18n/sfWidgetFormI18nDateTime.class.php | 71 +- .../i18n/sfWidgetFormI18nTime.class.php | 86 +- lib/widget/sfWidget.class.php | 739 +++-- lib/widget/sfWidgetForm.class.php | 599 ++-- lib/widget/sfWidgetFormChoice.class.php | 211 +- lib/widget/sfWidgetFormChoiceBase.class.php | 117 +- lib/widget/sfWidgetFormDate.class.php | 203 +- lib/widget/sfWidgetFormDateRange.class.php | 123 +- lib/widget/sfWidgetFormDateTime.class.php | 209 +- lib/widget/sfWidgetFormFilterDate.class.php | 95 +- lib/widget/sfWidgetFormFilterInput.class.php | 89 +- lib/widget/sfWidgetFormInput.class.php | 73 +- .../sfWidgetFormInputCheckbox.class.php | 110 +- lib/widget/sfWidgetFormInputFile.class.php | 31 +- .../sfWidgetFormInputFileEditable.class.php | 152 +- .../sfWidgetFormInputFileMulti.class.php | 68 +- lib/widget/sfWidgetFormInputHidden.class.php | 33 +- .../sfWidgetFormInputPassword.class.php | 73 +- lib/widget/sfWidgetFormInputRead.class.php | 89 +- lib/widget/sfWidgetFormInputText.class.php | 31 +- lib/widget/sfWidgetFormSchema.class.php | 1550 +++++----- .../sfWidgetFormSchemaDecorator.class.php | 715 +++-- .../sfWidgetFormSchemaFormatter.class.php | 526 ++-- .../sfWidgetFormSchemaFormatterList.class.php | 16 +- ...sfWidgetFormSchemaFormatterTable.class.php | 16 +- lib/widget/sfWidgetFormSelect.class.php | 158 +- .../sfWidgetFormSelectCheckbox.class.php | 178 +- lib/widget/sfWidgetFormSelectMany.class.php | 31 +- lib/widget/sfWidgetFormSelectRadio.class.php | 171 +- lib/widget/sfWidgetFormTextarea.class.php | 63 +- lib/widget/sfWidgetFormTime.class.php | 152 +- lib/yaml/sfYaml.class.php | 246 +- lib/yaml/sfYamlDumper.class.php | 66 +- lib/yaml/sfYamlInline.class.php | 753 ++--- lib/yaml/sfYamlParser.class.php | 974 +++--- test/bin/coverage.php | 12 +- test/bin/loc.php | 37 +- test/bin/test | 89 + test/bootstrap/functional.php | 59 +- test/bootstrap/task.php | 15 +- test/bootstrap/unit.php | 47 +- test/functional/authTest.php | 74 +- test/functional/autoloadTest.php | 8 +- test/functional/cacheTest.php | 644 ++-- test/functional/escapingTest.php | 27 +- test/functional/filterTest.php | 13 +- .../cache/config/cacheConfiguration.class.php | 6 +- .../modules/cache/actions/actions.class.php | 185 +- .../cache/actions/components.class.php | 43 +- .../templates/_anotherCacheablePartial.php | 14 +- .../cache/templates/_cacheableComponent.php | 8 +- .../cache/templates/_cacheablePartial.php | 10 +- .../modules/cache/templates/_component.php | 2 +- .../_contextualCacheableComponent.php | 2 +- .../templates/_contextualCacheablePartial.php | 2 +- .../cache/templates/_contextualComponent.php | 2 +- .../cache/templates/anotherPartialSuccess.php | 2 +- .../cache/templates/componentSuccess.php | 4 +- .../modules/cache/templates/imageSuccess.php | 4 +- .../modules/cache/templates/listSuccess.php | 2 +- .../cache/templates/multiBisSuccess.php | 12 +- .../modules/cache/templates/multiSuccess.php | 28 +- .../cache/templates/partialSuccess.php | 2 +- .../templates/specificCacheKeySuccess.php | 8 +- .../httpcache/actions/actions.class.php | 36 +- .../modules/nocache/actions/actions.class.php | 16 +- .../fixtures/apps/cache/templates/image.php | 4 +- .../fixtures/apps/cache/templates/layout.php | 18 +- .../config/frontendConfiguration.class.php | 51 +- .../lib/myAppsFrontendLibClass.class.php | 8 +- .../apps/frontend/lib/myAutoload.class.php | 15 +- .../frontend/lib/myAutoloadedClass.class.php | 8 +- .../apps/frontend/lib/myFilter.class.php | 24 +- .../assetInclusion/actions/actions.class.php | 9 +- .../modules/auth/actions/actions.class.php | 34 +- .../modules/auth/templates/basicSuccess.php | 6 +- .../autoload/actions/actions.class.php | 25 +- ...myAppsFrontendModulesAutoloadLib.class.php | 8 +- .../autoload/templates/indexSuccess.php | 8 +- .../autoload/templates/myAutoloadSuccess.php | 2 +- .../modules/browser/actions/actions.class.php | 76 +- .../actions/actions.class.php | 9 +- .../configFiltersSimpleFilterFilter.class.php | 12 +- .../templates/indexSuccess.php | 4 +- .../actions/actions.class.php | 9 +- .../actions/actions.class.php | 9 +- .../actions/actions.class.php | 9 +- .../actions/actions.class.php | 11 +- .../actions/actions.class.php | 9 +- .../modules/cookie/actions/actions.class.php | 31 +- .../escaping/actions/actions.class.php | 31 +- .../modules/escaping/templates/_partial1.php | 8 +- .../modules/escaping/templates/_partial2.php | 6 +- .../escaping/templates/indexSuccess.php | 6 +- .../exception/actions/actions.class.php | 27 +- .../modules/filter/actions/actions.class.php | 19 +- .../modules/format/actions/actions.class.php | 55 +- .../format/templates/indexSuccess.js.php | 2 +- .../notfound/actions/actions.class.php | 13 +- .../presentation/actions/actions.class.php | 19 +- .../presentation/templates/indexSuccess.php | 4 +- .../renderText/actions/actions.class.php | 11 +- .../modules/view/actions/actions.class.php | 23 +- .../apps/frontend/templates/layout.iphone.php | 12 +- .../apps/frontend/templates/layout.php | 12 +- .../apps/frontend/templates/layout.xml.php | 2 +- .../i18n/config/i18nConfiguration.class.php | 10 +- .../modules/i18n/actions/actions.class.php | 60 +- .../lib/I18nCustomCatalogueForm.class.php | 11 +- .../i18n/modules/i18n/lib/I18nForm.class.php | 43 +- .../i18n/templates/i18nFormSuccess.php | 4 +- .../modules/i18n/templates/indexSuccess.php | 18 +- .../fixtures/apps/i18n/templates/layout.php | 12 +- .../config/ProjectConfiguration.class.php | 15 +- .../fixtures/lib/form/BaseForm.class.php | 5 +- .../fixtures/lib/myLibClass.class.php | 8 +- .../autoloadPlugin/actions/actions.class.php | 12 +- ...adPluginModulesAutoloadPluginLib.class.php | 8 +- .../autoloadPlugin/templates/indexSuccess.php | 6 +- .../sfI18NPlugin/actions/actions.class.php | 21 +- .../sfI18NPlugin/templates/indexSuccess.php | 22 +- test/functional/formatTest.php | 31 +- test/functional/genericTest.php | 62 +- test/functional/httpcacheTest.php | 19 +- test/functional/i18nFormTest.php | 46 +- test/functional/i18nTest.php | 56 +- test/functional/prodTest.php | 22 +- test/functional/sfTestBrowserTest.php | 79 +- .../fixtures/task/myPluginTask.class.php | 22 +- test/other/fixtures/test/unit/testTest.php | 2 +- test/other/tasksTest.php | 110 +- test/unit/action/sfComponentTest.php | 28 +- test/unit/addon/sfPagerTest.php | 89 +- test/unit/autoload/sfCoreAutoloadTest.php | 2 +- test/unit/autoload/sfSimpleAutoloadTest.php | 2 +- test/unit/cache/sfAPCCacheTest.php | 42 - test/unit/cache/sfAPCuCacheTest.php | 57 + test/unit/cache/sfCacheDriverTests.class.php | 337 +-- test/unit/cache/sfCacheTest.php | 45 +- test/unit/cache/sfEAcceleratorCacheTest.php | 36 - test/unit/cache/sfFileCacheTest.php | 23 +- test/unit/cache/sfFunctionCacheTest.php | 119 +- test/unit/cache/sfMemcacheCacheTest.php | 53 +- test/unit/cache/sfNoCacheTest.php | 2 +- test/unit/cache/sfSQLiteCacheTest.php | 47 +- test/unit/cache/sfXCacheCacheTest.php | 36 - .../unit/command/sfCommandArgumentSetTest.php | 111 +- test/unit/command/sfCommandArgumentTest.php | 53 +- test/unit/command/sfCommandManagerTest.php | 116 +- test/unit/command/sfCommandOptionSetTest.php | 144 +- test/unit/command/sfCommandOptionTest.php | 57 +- .../config/sfCompileConfigHandlerTest.php | 10 +- test/unit/config/sfConfigHandlerTest.php | 22 +- test/unit/config/sfConfigTest.php | 8 +- .../sfDefineEnvironmentConfigHandlerTest.php | 14 +- .../unit/config/sfFilterConfigHandlerTest.php | 92 +- .../config/sfGeneratorConfigHandlerTest.php | 111 +- .../unit/config/sfPluginConfigurationTest.php | 38 +- .../config/sfProjectConfigurationTest.php | 63 +- .../config/sfSimpleYamlConfigHandlerTest.php | 16 +- test/unit/config/sfViewConfigHandlerTest.php | 468 +-- test/unit/config/sfYamlConfigHandlerTest.php | 86 +- test/unit/controller/sfControllerTest.php | 13 +- test/unit/controller/sfWebControllerTest.php | 318 +- test/unit/database/sfDatabaseTest.php | 18 +- test/unit/debug/sfDebugTest.php | 13 +- test/unit/debug/sfTimerTest.php | 4 +- test/unit/debug/sfWebDebugTest.php | 19 +- .../sfOutputEscaperArrayDecoratorTest.php | 94 +- .../sfOutputEscaperObjectDecoratorTest.php | 75 +- test/unit/escaper/sfOutputEscaperSafeTest.php | 34 +- test/unit/escaper/sfOutputEscaperTest.php | 107 +- test/unit/event/sfEventDispatcherTest.php | 107 +- test/unit/event/sfEventTest.php | 17 +- test/unit/exception/sfExceptionsTest.php | 39 +- test/unit/filter/sfFilterTest.php | 19 +- test/unit/form/addon/sfFormSymfonyTest.php | 60 +- test/unit/form/sfFormFieldSchemaTest.php | 88 +- test/unit/form/sfFormFieldTest.php | 106 +- test/unit/form/sfFormTest.php | 1102 +++---- test/unit/generator/sfGeneratorTest.php | 8 +- ...sfModelGeneratorConfigurationFieldTest.php | 10 +- test/unit/helper/AssetHelperTest.php | 309 +- test/unit/helper/DateHelperTest.php | 45 +- test/unit/helper/EscapingHelperTest.php | 8 +- test/unit/helper/JavascriptBaseHelperTest.php | 26 +- test/unit/helper/NumberHelperTest.php | 13 +- test/unit/helper/PartialHelperTest.php | 34 +- test/unit/helper/TagHelperTest.php | 23 +- test/unit/helper/TestObject.php | 66 +- test/unit/helper/TextHelperTest.php | 85 +- test/unit/helper/UrlHelperTest.php | 133 +- test/unit/i18n/dataTest.php | 48 +- test/unit/i18n/extract/sfI18nExtractTest.php | 33 +- .../i18n/extract/sfI18nPhpExtractorTest.php | 32 +- .../sfI18nYamlGeneratorExtractorTest.php | 36 +- .../sfI18nYamlValidateExtractorTest.php | 18 +- test/unit/i18n/sfChoiceFormatTest.php | 168 +- test/unit/i18n/sfCultureInfoTest.php | 140 +- test/unit/i18n/sfI18NTest.php | 75 +- test/unit/i18n/sfMessageSourceTest.php | 33 +- .../i18n/sfMessageSource_AggregateTest.php | 10 +- test/unit/i18n/sfMessageSource_FileTest.php | 32 +- test/unit/i18n/sfMessageSource_SQLiteTest.php | 59 +- test/unit/i18n/sfMessageSource_XLIFFTest.php | 4 +- test/unit/i18n/sfNumberFormatInfoTest.php | 142 +- test/unit/log/sfAggregateLoggerTest.php | 29 +- test/unit/log/sfConsoleLoggerTest.php | 4 +- test/unit/log/sfFileLoggerTest.php | 51 +- test/unit/log/sfLoggerTest.php | 76 +- test/unit/log/sfLoggerWrapperTest.php | 22 +- test/unit/log/sfStreamLoggerTest.php | 6 +- test/unit/log/sfVarLoggerTest.php | 4 +- test/unit/log/sfWebDebugLoggerTest.php | 5 +- .../mailer/fixtures/TestMailMessage.class.php | 12 +- .../fixtures/TestMailerTransport.class.php | 108 +- test/unit/mailer/fixtures/TestSpool.class.php | 76 +- test/unit/mailer/sfMailerTest.php | 140 +- .../plugin/sfPearDownloaderTest.class.php | 44 +- test/unit/plugin/sfPearEnvironmentTest.php | 52 +- test/unit/plugin/sfPearRestPluginTest.php | 34 +- test/unit/plugin/sfPearRestTest.class.php | 50 +- test/unit/plugin/sfPluginManagerTest.php | 202 +- test/unit/plugin/sfPluginTestHelper.class.php | 34 +- test/unit/request/sfRequestTest.php | 39 +- test/unit/request/sfWebRequestTest.php | 232 +- test/unit/response/sfResponseTest.php | 25 +- test/unit/response/sfWebResponseTest.php | 113 +- .../routing/fixtures/config_routing.yml.php | 1 + .../routing/sfObjectRouteCollectionTest.php | 124 +- test/unit/routing/sfObjectRouteTest.php | 34 +- test/unit/routing/sfPatternRoutingTest.php | 489 +-- test/unit/routing/sfRequestRouteTest.php | 34 +- test/unit/routing/sfRouteTest.php | 236 +- .../fixtures/containers/container10.php | 3 +- .../fixtures/containers/container8.php | 10 +- .../fixtures/containers/container9.php | 25 +- .../service/fixtures/includes/classes.php | 32 +- test/unit/service/fixtures/includes/foo.php | 50 +- .../service/sfServiceContainerBuilderTest.php | 127 +- .../sfServiceContainerDumperGraphvizTest.php | 19 +- .../sfServiceContainerDumperPhpTest.php | 19 +- .../service/sfServiceContainerDumperTest.php | 16 +- .../sfServiceContainerLoaderArrayTest.php | 54 +- .../service/sfServiceContainerLoaderTest.php | 62 +- test/unit/service/sfServiceContainerTest.php | 114 +- test/unit/service/sfServiceDefinitionTest.php | 20 +- test/unit/service/sfServiceParameterTest.php | 2 +- test/unit/service/sfServiceReferenceTest.php | 2 +- test/unit/sfContextMock.class.php | 211 +- test/unit/sfEventDispatcherTest.class.php | 48 +- test/unit/sfNoRouting.class.php | 154 +- test/unit/sfParameterHolderTest.class.php | 79 +- .../storage/sfCacheSessionStorageTest.php | 40 +- test/unit/storage/sfMySQLStorageTest.php | 139 + test/unit/storage/sfMySQLiStorageTest.php | 99 +- test/unit/storage/sfNoStorageTest.php | 4 +- test/unit/storage/sfPDOSessionStorageTest.php | 71 +- test/unit/storage/sfSessionStorageTest.php | 21 +- test/unit/storage/sfStorageTest.php | 28 +- test/unit/task/cache/sfCacheClearTaskTest.php | 8 +- test/unit/task/sfBaseTaskTest.php | 111 +- test/unit/task/sfFilesystemTest.php | 24 +- test/unit/task/sfTaskTest.php | 137 +- test/unit/test/limeTestTest.php | 6 +- test/unit/test/sfTestFunctionalTest.php | 51 +- test/unit/user/sfBasicSecurityUserTest.php | 46 +- test/unit/user/sfUserTest.php | 34 +- test/unit/util/sfBrowserTest.php | 186 +- test/unit/util/sfCallableTest.php | 38 +- test/unit/util/sfClassManipulatorTest.php | 123 +- test/unit/util/sfContextTest.php | 35 +- test/unit/util/sfDomCssSelectorTest.php | 172 +- test/unit/util/sfFinderTest.php | 176 +- test/unit/util/sfInflectorTest.php | 10 +- .../util/sfNamespacedParameterHolderTest.php | 20 +- test/unit/util/sfParameterHolderTest.php | 20 +- test/unit/util/sfToolkitTest.php | 182 +- .../i18n/sfValidatorI18nChoiceCountryTest.php | 21 +- .../sfValidatorI18nChoiceLanguageTest.php | 21 +- .../sfValidatorI18nChoiceTimezoneTest.php | 2 +- test/unit/validator/sfValidatorAndTest.php | 154 +- test/unit/validator/sfValidatorBaseTest.php | 180 +- .../unit/validator/sfValidatorBooleanTest.php | 41 +- .../validator/sfValidatorCSRFTokenTest.php | 35 +- .../validator/sfValidatorCallbackTest.php | 49 +- test/unit/validator/sfValidatorChoiceTest.php | 108 +- .../validator/sfValidatorDateRangeTest.php | 77 +- test/unit/validator/sfValidatorDateTest.php | 252 +- .../validator/sfValidatorDateTimeTest.php | 4 +- .../validator/sfValidatorDecoratorTest.php | 100 +- test/unit/validator/sfValidatorEmailTest.php | 47 +- test/unit/validator/sfValidatorEqualTest.php | 82 +- .../validator/sfValidatorErrorSchemaTest.php | 101 +- test/unit/validator/sfValidatorErrorTest.php | 63 +- .../validator/sfValidatorFileMultiTest.php | 10 +- test/unit/validator/sfValidatorFileTest.php | 268 +- .../sfValidatorFromDescriptionTest.php | 133 +- .../unit/validator/sfValidatorIntegerTest.php | 102 +- test/unit/validator/sfValidatorIpTest.php | 396 ++- test/unit/validator/sfValidatorNumberTest.php | 77 +- test/unit/validator/sfValidatorOrTest.php | 110 +- test/unit/validator/sfValidatorPassTest.php | 2 +- test/unit/validator/sfValidatorRegexTest.php | 77 +- .../sfValidatorSchemaCompareTest.php | 160 +- .../validator/sfValidatorSchemaFilterTest.php | 53 +- test/unit/validator/sfValidatorSchemaTest.php | 486 ++- test/unit/validator/sfValidatorStringTest.php | 83 +- test/unit/validator/sfValidatorTimeTest.php | 145 +- test/unit/validator/sfValidatorUrlTest.php | 70 +- test/unit/view/sfViewCacheManagerTest.php | 239 +- test/unit/view/sfViewParameterHolderTest.php | 63 +- test/unit/view/sfViewTest.php | 54 +- .../sfWidgetFormI18nChoiceCountryTest.php | 28 +- .../sfWidgetFormI18nChoiceCurrencyTest.php | 28 +- .../sfWidgetFormI18nChoiceLanguageTest.php | 28 +- .../sfWidgetFormI18nChoiceTimezoneTest.php | 8 +- .../widget/i18n/sfWidgetFormI18nDateTest.php | 29 +- .../i18n/sfWidgetFormI18nDateTimeTest.php | 6 +- .../widget/i18n/sfWidgetFormI18nTimeTest.php | 8 +- test/unit/widget/sfWidgetFormChoiceTest.php | 66 +- .../unit/widget/sfWidgetFormDateRangeTest.php | 38 +- test/unit/widget/sfWidgetFormDateTest.php | 47 +- test/unit/widget/sfWidgetFormDateTimeTest.php | 73 +- .../widget/sfWidgetFormFilterDateTest.php | 35 +- .../widget/sfWidgetFormFilterInputTest.php | 19 +- .../widget/sfWidgetFormInputCheckboxTest.php | 12 +- .../sfWidgetFormInputFileEditableTest.php | 71 +- .../widget/sfWidgetFormInputFileMultiTest.php | 4 +- .../unit/widget/sfWidgetFormInputFileTest.php | 2 +- .../widget/sfWidgetFormInputHiddenTest.php | 2 +- .../widget/sfWidgetFormInputPasswordTest.php | 2 +- .../unit/widget/sfWidgetFormInputReadTest.php | 10 +- .../unit/widget/sfWidgetFormInputTextTest.php | 8 +- .../sfWidgetFormSchemaDecoratorTest.php | 28 +- .../sfWidgetFormSchemaFormatterListTest.php | 10 +- .../sfWidgetFormSchemaFormatterTableTest.php | 10 +- .../sfWidgetFormSchemaFormatterTest.php | 134 +- test/unit/widget/sfWidgetFormSchemaTest.php | 392 ++- .../widget/sfWidgetFormSelectCheckboxTest.php | 77 +- .../widget/sfWidgetFormSelectManyTest.php | 6 +- .../widget/sfWidgetFormSelectRadioTest.php | 63 +- test/unit/widget/sfWidgetFormSelectTest.php | 67 +- test/unit/widget/sfWidgetFormTest.php | 46 +- test/unit/widget/sfWidgetFormTextareaTest.php | 2 +- test/unit/widget/sfWidgetFormTimeTest.php | 45 +- test/unit/widget/sfWidgetTest.php | 120 +- test/unit/yaml/sfYamlDumperTest.php | 97 +- test/unit/yaml/sfYamlInlineTest.php | 208 +- test/unit/yaml/sfYamlParserTest.php | 77 +- 954 files changed, 69293 insertions(+), 75641 deletions(-) create mode 100644 .docker/Dockerfile create mode 100644 .env.dist create mode 100644 .gitattributes create mode 100644 .github/workflows/continuous-integration.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .php-cs-fixer.dist.php delete mode 100644 .travis.yml create mode 100644 docker-compose.yml delete mode 100644 lib/cache/sfAPCCache.class.php create mode 100644 lib/cache/sfAPCuCache.class.php delete mode 100644 lib/cache/sfEAcceleratorCache.class.php delete mode 100644 lib/cache/sfXCacheCache.class.php create mode 100644 lib/database/sfMySQLDatabase.class.php create mode 100644 lib/i18n/sfMessageSource_MySQL.class.php create mode 100644 lib/storage/sfMySQLSessionStorage.class.php create mode 160000 lib/vendor/swiftmailer create mode 100755 test/bin/test delete mode 100644 test/unit/cache/sfAPCCacheTest.php create mode 100644 test/unit/cache/sfAPCuCacheTest.php delete mode 100644 test/unit/cache/sfEAcceleratorCacheTest.php delete mode 100644 test/unit/cache/sfXCacheCacheTest.php create mode 100644 test/unit/storage/sfMySQLStorageTest.php diff --git a/.docker/Dockerfile b/.docker/Dockerfile new file mode 100644 index 000000000..a9d410dbf --- /dev/null +++ b/.docker/Dockerfile @@ -0,0 +1,68 @@ +ARG PHP_VERSION +FROM php:${PHP_VERSION}-cli + +RUN docker-php-ext-install pdo +RUN docker-php-ext-install pdo_mysql + +# Install mbstring PHP extension +# +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-upgrade --no-install-recommends \ + libonig-dev \ + ; \ + \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/*; \ + \ + docker-php-ext-install mbstring + +# Install APCu PHP extension +# +ARG APCU_VERSION +RUN set -eux; \ + \ + test x"" = x"${APCU_VERSION}" || { \ + pecl install apcu-${APCU_VERSION}; \ + docker-php-ext-enable apcu; \ + \ + rm -r /tmp/pear; \ + } + +# Install memcache PHP extension +# +ARG MEMCACHE_VERSION +RUN set -eux; \ + buildDeps=' \ + libzip-dev \ + '; \ + apt-get update; \ + apt-get install -y --no-upgrade --no-install-recommends \ + $buildDeps \ + ; \ + \ + pecl install memcache-${MEMCACHE_VERSION}; \ + docker-php-ext-enable memcache; \ + \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=true \ + $buildDeps \ + ; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/*; \ + rm -r /tmp/pear + +# For consistent mime type file guesser +RUN set -eux; \ + distFilePath=`which file`; \ + \ + mv ${distFilePath} ${distFilePath}.dist; \ + { \ + echo '#! /bin/sh -eu'; \ + echo ''; \ + echo "${distFilePath}"'.dist "$@" | sed -e s,application/x-pie-executable,application/x-executable,g'; \ + } | tee ${distFilePath}; \ + \ + chmod +x ${distFilePath}; \ + \ + file /bin/ls --mime | grep application/x-executable; \ + :; diff --git a/.editorconfig b/.editorconfig index 4a7ea3036..92af3f94c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,7 +2,7 @@ root = true [*] indent_style = space -indent_size = 2 +indent_size = 4 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true @@ -10,3 +10,7 @@ insert_final_newline = true [*.md] trim_trailing_whitespace = false + +[.github/**.yml] +indent_size = 2 +indent_style = space diff --git a/.env.dist b/.env.dist new file mode 100644 index 000000000..c4d23d59a --- /dev/null +++ b/.env.dist @@ -0,0 +1,5 @@ +# +# Environment variables used by docker-compose for test. +# +# Copy to `.env` in order to use it. +# diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..9645b77e9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +.docker/ export-ignore +.editorconfig export-ignore +.env.dist export-ignore +.gitattributes export-ignore +.github/ export-ignore +.gitignore export-ignore +.php-cs-fixer.dist.php export-ignore +docker-compose.yml export-ignore +phpstan.neon export-ignore +phpunit.xml export-ignore +tests/ export-ignore diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 000000000..2a9dc32c8 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,59 @@ +name: "Continuous Integration" + +on: + push: + branches: + - master + pull_request: + +env: + fail-fast: true + +jobs: + tests: + name: "Symfony1 Tests" + runs-on: "ubuntu-latest" + + strategy: + matrix: + php-version: + - "8.2" + memcached-version: + - "1.6" + + services: + memcached: + image: "memcached:${{ matrix.memcached-version }}" + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: "true" + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ matrix.php-version }}" + extensions: apcu + ini-values: apc.enable_cli=1 + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --prefer-dist + + - name: Run Check configuration + run: php data/bin/check_configuration.php + + - name: Run Tests + run: php data/bin/symfony symfony:test --trace diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 000000000..fddeefeeb --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,43 @@ +name: "Code Linting" +on: + push: + paths: + - .php-cs-fixer.dist.php + - autoload.php + - lib/** + - data/** + - tests/** + branches: + - master + pull_request: + paths: + - .php-cs-fixer.dist.php + - autoload.php + - lib/** + - data/** + - tests/** + +jobs: + php-cs-fixer: + name: 'PHP-CS-Fixer' + runs-on: 'ubuntu-latest' + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.2 + tools: php-cs-fixer:3.52, cs2pr + + - uses: actions/cache@v4 + with: + path: '.php-cs-fixer.cache' + key: ${{ github.repository }}-8.2-phpcsfixer-${{ github.ref_name }} + restore-keys: | + ${{ github.repository }}-8.2-phpcsfixer-master + ${{ github.repository }}-8.2-phpcsfixer- + + - name: Run PHP-CS-Fixer + # Using cs2pr settings, see: https://github.com/shivammathur/setup-php#tools-with-checkstyle-support + run: 'php-cs-fixer fix --dry-run --format=checkstyle | cs2pr' diff --git a/.gitignore b/.gitignore index ebc31dcea..1c5624fa2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.cache/ + /test/functional/fixtures/cache /test/functional/fixtures/log /lib/plugins/sfDoctrinePlugin/test/functional/fixtures/lib/*/doctrine/base/ diff --git a/.gitmodules b/.gitmodules index 3ee8d0c7d..5307c7137 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,7 @@ [submodule "lib/vendor/swiftmailer"] - path = lib/vendor/swiftmailer - url = https://github.com/swiftmailer/swiftmailer.git - branch = 5.x + path = lib/vendor/swiftmailer + url = https://github.com/FriendsOfSymfony1/swiftmailer.git + branch = 5.x [submodule "lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine"] - path = lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine - url = https://github.com/FriendsOfSymfony1/doctrine1.git + path = lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine + url = https://github.com/JamesAndJamesFulfilment/doctrine1.git diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 000000000..7199fd535 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,38 @@ +ignoreVCSIgnored(true) + ->in(__DIR__.'/lib') + ->in(__DIR__.'/data/bin') + ->in(__DIR__.'/test') + ->append([__FILE__]) + // Exclude PHP classes templates/generators, which are not valid PHP files + ->exclude('task/generator/skeleton/') + ->exclude('plugins/sfDoctrinePlugin/data/generator/') + ->exclude('plugins/sfDoctrinePlugin/test/functional/fixtures/') + + // Exclude sub-modules folders + ->exclude('plugins/sfDoctrinePlugin/lib/vendor/doctrine') + + // Exclude generated files (whole directories) + ->exclude('functional/fixtures/cache') + ->exclude('functional/fixtures/log') + + // Exclude generated files (single files) + ->notPath('unit/config/fixtures/sfDefineEnvironmentConfigHandler/prefix_result.php') + ->notPath('unit/config/fixtures/sfFilterConfigHandler/result.php') +; + +$config = new PhpCsFixer\Config(); +$config + ->setRules([ + '@PhpCsFixer' => true, + '@Symfony' => true, + 'array_syntax' => ['syntax' => 'short'], + 'nullable_type_declaration_for_default_null_value' => true, + ]) + ->setCacheFile('.cache/php-cs-fixer.cache') + ->setFinder($finder) +; + +return $config; diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3c97ddbec..000000000 --- a/.travis.yml +++ /dev/null @@ -1,56 +0,0 @@ -os: linux -dist: focal -language: php - -php: - - 7.4 - - 8.0 - - 8.1 - - nightly - -# run build against nightly but allow them to fail -jobs: - fast_finish: true - allow_failures: - - php: nightly - - php: 5.3 - - php: 5.4 - include: - - php: 5.3 - dist: precise - - php: 5.4 - dist: trusty - - php: 5.5 - dist: trusty - - php: 5.6 - dist: trusty - - php: 7.0 - dist: xenial - - php: 7.1 - dist: xenial - - php: 7.2 - dist: xenial - - php: 7.3 - dist: xenial - -services: - - memcached - -cache: - directories: - - $HOME/.composer/cache - -before_install: - - sh -c 'if [ $(php -r "echo PHP_MINOR_VERSION;") -le 4 ] && [ $(php -r "echo PHP_MAJOR_VERSION;") -le 5 ]; then echo "extension = apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;' - - sh -c 'if [ $(php -r "echo PHP_RELEASE_VERSION;") -le 98 ] && [ $(php -r "echo PHP_MAJOR_VERSION;") -le 5 ]; then echo "extension = memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;' - -install: - # by default, --remote is not used on travis - - git submodule update --remote --force - - composer install --prefer-dist --no-progress --no-suggest -o - # Temporary, while Doctrine is not merged, it will avoid one error tasksTest - - echo 'error_reporting = E_ALL & ~E_DEPRECATED' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini - -script: - - php data/bin/check_configuration.php - - php data/bin/symfony symfony:test --trace diff --git a/CHANGELOG.md b/CHANGELOG.md index 33855aef2..7f5430169 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,71 @@ CHANGELOG ========= +======= + +xx/xx/xxxx: Version 1.5.xx +-------------------------- + +* Remove sfXCacheCache as the extension is not available on PHP v7.4 anymore. +* Remove sfEAcceleratorCache as the extension is not available on PHP v7.4 anymore. +* Remove sfAPCCache as it uses the `apc` extension, which is not available on PHP v7.4 anymore. + **[BC-Break]** Use `sfAPCuCache` class instead, available from Symfony1 v1.5.16 + +28/02/2024: Version 1.5.18 +-------------------------- + +* Set min versions of swiftmailer to 5.4.13 and 6.2.5 and updated swiftmailer submodule by @thirsch in #331 + +23/02/2024: Version 1.5.17 +-------------------------- + +* Update min PHP requirement to v7.4 or v8.1 by @thePanz in #325 +* Updated gh workflow to use latest actions by @thirsch in #330 +* Backported display_errors-handling to sf1 by @thirsch in #328 + +15/02/2024: Version 1.5.16 +-------------------------- + +* Fix(deprecations) Fix deprecations in sfMessageSource_Aggregate, by @thePanz in #277 +* Add(linting) Add code linting to GitHub workflow, use php-cs-fixer by @thePanz in #283 +* Add(gitattributes) Add .gitattributes to repository by @thePanz in #287 +* fix: avoid creating dynamic property $options by @vimar in #290 +* Update(github) Update github workflows by @thePanz in #292 +* php8.3 in the party by @connorhu in #294 +* Fix(php-cs-fixer) Fix php-cs-fixer to v3.45 and apply code fixes by @thePanz in #300 +* 8.3 compat/string to array by @iricketson in #298 +* Fix APC tests and add APCu support by @mentalstring in #267 +* [8.x Compatiblity] sfDebug::shortenFilePath by @iricketson in #299 +* Fix strpos() deprecation on sfCacheSessionStorage check for cookie by @thePanz in #303 +* Fix setrawcookie() deprecation on null parameter by @thePanz in #304 +* Fix str_replace() deprecated null parameter on sfNumberFormat by @thePanz in #305 +* [PHP] Replace default $flags variable with 0 by @iricketson in #307 +* [PHP8] Declare sfDoctrineFormGenerator $params property by @iricketson in #306 +* Update README by @mentalstring in #310 +* minor fix: remove fourth argument by @connorhu in #308 +* Fix PHP8.1 sfForm - Unsupported operand types: array + null on sfForm by @Tybaze in #281 +* Fix link to GitHub pipeline badge by @thePanz in #311 +* fix(phpdoc) remove html code from throws phpdoc. phpstan don't like this by @connorhu in #309 +* fix(phpdoc) remove version tag by @connorhu in #313 + +12/01/2023: Version 1.5.15 +-------------------------- + +* Add support for PHP 8.2 by @thirsch in #274 +* More adjustments for PHP 8.0 & 8.1 by @thirsch in #272 + +25/11/2022: Version 1.5.14 +-------------------------- + +* Update composer.json to automatically remove lexpress/symfony1 package by @spirit-q2 in #241 +* Updated lexpress to fos1 in the submodules. by @thirsch in #238 +* Compat for Swiftmailer 6 but preserve compatibility with Swiftmailer 5. by @thirsch in #240 +* Update PHPDoc for `sfWebController::redirect()` func by @cmdeviant in #246 +* Fixing Issue #234 by @pathumhdes in #235 +* Add consistent local environment for testing with docker and docker-compose by @alquerci in #262 +* Use GitHub actions for Continuous Integration tests by @thePanz in #268 +* Add support for PHP 8.0 & 8.1 by @Tybaze in #266 + 08/06/2020: Version 1.5.13 -------------------------- diff --git a/README.md b/README.md index 28c30702a..9cf3d95cc 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ -[![Build Status](https://secure.travis-ci.org/FriendsOfSymfony1/symfony1.png?branch=master)](http://travis-ci.org/FriendsOfSymfony1/symfony1) +![Build Status](https://github.com/FriendsOfSymfony1/symfony1/actions/workflows/continuous-integration.yml/badge.svg) About this version ------------------ -This is a community driven fork of symfony 1, as official support has been [interrupted in November 2012](http://symfony.com/blog/symfony-1-4-end-of-maintenance-what-does-it-mean). +This is a community driven fork of symfony 1, as official support has been [interrupted in November 2012](https://symfony.com/blog/symfony-1-4-end-of-maintenance-what-does-it-mean). -**Do not use it for new projects: this version is great to improve existing symfony1 applications, but [Symfony5](http://symfony.com/) is the way to go today.** +**Do not use it for new projects: this version is great to improve existing symfony1 applications, but [newer Symfony](https://symfony.com/) versions is the way to go today.** All the enhancements and BC breaks are listed in the [WHATS_NEW](https://github.com/FriendsOfSymfony1/symfony1/blob/master/WHATS_NEW.md) file, this include: - [DIC](https://github.com/FriendsOfSymfony1/symfony1/wiki/ServiceContainer) - Composer support -- PHP 8.1 support +- PHP 8.3 support - performance boost - new widgets & validators - some tickets fixed from the symfony trac @@ -34,30 +34,61 @@ It runs on *nix and Windows platforms*. Requirements ------------ -PHP 5.3.4 and up. See prerequisites on http://symfony.com/legacy/doc/getting-started/1_4/en/02-Prerequisites +PHP 5.3.4 and up. See prerequisites on https://symfony.com/legacy/doc/getting-started/1_4/en/02-Prerequisites Installation ------------ -See http://symfony.com/legacy/doc/getting-started/1_4/en/03-Symfony-Installation +See https://symfony.com/legacy/doc/getting-started/1_4/en/03-Symfony-Installation -Option 1: Using [Composer](http://getcomposer.org/doc/00-intro.md) as dependency management: +Option 1: Using [Composer](https://getcomposer.org/doc/00-intro.md) as dependency management: composer require friendsofsymfony1/symfony1 "1.5.*" composer install - -Note: On windows, if your project is a few directories down from the drive root, composer can throw an error relating to ZipArchive::extractTo(), this can be because pathnames are too long. There currently appears to be no proper solution but a workaround is to move your project to the drive root, run the commands from there, where they will run happily, and then move your project back. + +Note: On windows, if your project is a few directories down from the drive root, composer can throw an error relating to ZipArchive::extractTo(), this can be because pathnames are too long. There currently appears to be no proper solution but a workaround is to move your project to the drive root, run the commands from there, where they will run happily, and then move your project back. Option 2: Using Git submodules: - + git init # your project git submodule add https://github.com/FriendsOfSymfony1/symfony1.git lib/vendor/symfony git submodule update --init --recursive + +Tests +----- + +### Prerequisites + + * docker-engine version 17.12.0+ + * docker-compose version 1.20.0+ + +### How to execute all tests on all supported PHP versions and dependencies? + + test/bin/test + +### For PHP 7.3 and for lowest dependencies versions? + + test/bin/test php73 lowest + +### For PHP 7.3 and for highest dependencies versions? + + test/bin/test php73 highest + +### For executing a dedicated test file? + + test/bin/test php73 highest test/unit/cache/sfAPCCacheTest.php + + +### When you finish your work day, do not forget to clean up your desk + + docker-compose down + + Documentation ------------- -Read the official [symfony1 documentation](http://symfony.com/legacy) +Read the official [symfony1 documentation](https://symfony.com/legacy) Contributing ------------ diff --git a/WHATS_NEW.md b/WHATS_NEW.md index c6692e8eb..02bbb92ed 100644 --- a/WHATS_NEW.md +++ b/WHATS_NEW.md @@ -165,8 +165,7 @@ This allow you to remove all stylesheets and/or all javascripts added into the g Configuration ------------- -* A new configuration `sf_upload_dir_name` contains 'uploads' has been added. -* A new settings `sf_display_errors` has been added to change display_errors from stdout to stderr for example. +A new configuration `sf_upload_dir_name` contains 'uploads' has been added. Performance ----------- @@ -245,4 +244,4 @@ all: monolog.handler.file: class: Monolog\Handler\StreamHandler arguments: [/the/file/path/of/your/file.log] -``` +``` \ No newline at end of file diff --git a/composer.json b/composer.json index a3afe9aa5..490d0d508 100644 --- a/composer.json +++ b/composer.json @@ -5,8 +5,8 @@ "keywords": ["framework", "symfony1", "doctrine1"], "license": "MIT", "require": { - "swiftmailer/swiftmailer": "~6.2", - "php" : ">=8.1.0" + "php" : "^7.4 || ^8.1", + "friendsofsymfony1/swiftmailer": "^6.2.5" }, "require-dev": { "psr/log": "*" @@ -24,7 +24,7 @@ }, "extra": { "branch-alias": { - "dev-php81": "1.6-dev" + "dev-php82": "1.6-dev" } }, "bin": ["data/bin/symfony"] diff --git a/data/bin/changelog.php b/data/bin/changelog.php index 55d3c1c6f..6a3218a4b 100644 --- a/data/bin/changelog.php +++ b/data/bin/changelog.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -13,22 +13,22 @@ * * Usage: php data/bin/changelog.php -r12345:67890 /branches/1.3 * - * @package symfony * @author Fabien Potencier + * * @version SVN: $Id$ */ require_once __DIR__.'/../../lib/task/sfFilesystem.class.php'; -if (!isset($argv[1])) -{ - echo "You must provide a revision range (-r123:456)\n"; - exit(1); +if (!isset($argv[1])) { + echo "You must provide a revision range (-r123:456)\n"; + + exit(1); } -if (!isset($argv[2])) -{ - echo "You must provide a repository path (/branches/1.4)\n"; - exit(1); +if (!isset($argv[2])) { + echo "You must provide a repository path (/branches/1.4)\n"; + + exit(1); } $filesystem = new sfFilesystem(); @@ -36,14 +36,13 @@ list($out, $err) = $filesystem->execute('svn info --xml'); $info = new SimpleXMLElement($out); -list($out, $err) = $filesystem->execute(vsprintf('svn log %s --xml %s', array_map('escapeshellarg', array( - $argv[1], - (string) $info->entry->repository->root.$argv[2], -)))); +list($out, $err) = $filesystem->execute(vsprintf('svn log %s --xml %s', array_map('escapeshellarg', [ + $argv[1], + (string) $info->entry->repository->root.$argv[2], +]))); $log = new SimpleXMLElement($out); -foreach ($log->logentry as $logentry) -{ - echo sprintf(' * [%d] %s', $logentry['revision'], trim(preg_replace('/\s*\[[\d\., ]+\]\s*/', '', (string) $logentry->msg))); - echo PHP_EOL; +foreach ($log->logentry as $logentry) { + echo sprintf(' * [%d] %s', $logentry['revision'], trim(preg_replace('/\s*\[[\d\., ]+\]\s*/', '', (string) $logentry->msg))); + echo PHP_EOL; } diff --git a/data/bin/check_configuration.php b/data/bin/check_configuration.php index 0315489ba..ad542be16 100644 --- a/data/bin/check_configuration.php +++ b/data/bin/check_configuration.php @@ -2,7 +2,7 @@ function is_cli() { - return !isset($_SERVER['HTTP_HOST']); + return !isset($_SERVER['HTTP_HOST']); } /** @@ -10,37 +10,33 @@ function is_cli() */ function check($boolean, $message, $help = '', $fatal = false) { - echo $boolean ? " OK " : sprintf("[[%s]] ", $fatal ? ' ERROR ' : 'WARNING'); - echo sprintf("$message%s\n", $boolean ? '' : ': FAILED'); + echo $boolean ? ' OK ' : sprintf('[[%s]] ', $fatal ? ' ERROR ' : 'WARNING'); + echo sprintf("{$message}%s\n", $boolean ? '' : ': FAILED'); - if (!$boolean) - { - echo " *** $help ***\n"; - if ($fatal) - { - die("You must fix this problem before resuming the check.\n"); + if (!$boolean) { + echo " *** {$help} ***\n"; + if ($fatal) { + exit("You must fix this problem before resuming the check.\n"); + } } - } } /** - * Gets the php.ini path used by the current PHP interpretor. + * Gets the php.ini path used by the current PHP interpreter. * * @return string the php.ini path */ function get_ini_path() { - if ($path = get_cfg_var('cfg_file_path')) - { - return $path; - } + if ($path = get_cfg_var('cfg_file_path')) { + return $path; + } - return 'WARNING: not using a php.ini file'; + return 'WARNING: not using a php.ini file'; } -if (!is_cli()) -{ - echo '
';
+if (!is_cli()) {
+    echo '
';
 }
 
 echo "********************************\n";
@@ -51,31 +47,28 @@ function get_ini_path()
 
 echo sprintf("php.ini used by PHP: %s\n\n", get_ini_path());
 
-if (is_cli())
-{
-  echo "** WARNING **\n";
-  echo "*  The PHP CLI can use a different php.ini file\n";
-  echo "*  than the one used with your web server.\n";
-  if ('\\' == DIRECTORY_SEPARATOR)
-  {
-    echo "*  (especially on the Windows platform)\n";
-  }
-  echo "*  If this is the case, please launch this\n";
-  echo "*  utility from your web server.\n";
-  echo "** WARNING **\n";
+if (is_cli()) {
+    echo "** WARNING **\n";
+    echo "*  The PHP CLI can use a different php.ini file\n";
+    echo "*  than the one used with your web server.\n";
+    if ('\\' == DIRECTORY_SEPARATOR) {
+        echo "*  (especially on the Windows platform)\n";
+    }
+    echo "*  If this is the case, please launch this\n";
+    echo "*  utility from your web server.\n";
+    echo "** WARNING **\n";
 }
 
 // mandatory
 echo "\n** Mandatory requirements **\n\n";
-check(version_compare(phpversion(), '5.3.1', '>='), sprintf('PHP version is at least 5.3.1 (%s)', phpversion()), 'Current version is '.phpversion(), true);
+check(PHP_VERSION_ID >= 70400, sprintf('PHP version is at least 7.4.0 (%s)', PHP_VERSION), 'Current version is '.PHP_VERSION, true);
 
 // warnings
 echo "\n** Optional checks **\n\n";
 check(class_exists('PDO'), 'PDO is installed', 'Install PDO (mandatory for Doctrine)', false);
-if (class_exists('PDO'))
-{
-  $drivers = PDO::getAvailableDrivers();
-  check(count($drivers), 'PDO has some drivers installed: '.implode(', ', $drivers), 'Install PDO drivers (mandatory for Doctrine)');
+if (class_exists('PDO')) {
+    $drivers = PDO::getAvailableDrivers();
+    check(count($drivers), 'PDO has some drivers installed: '.implode(', ', $drivers), 'Install PDO drivers (mandatory for Doctrine)');
 }
 check(function_exists('token_get_all'), 'The token_get_all() function is available', 'Install and enable the Tokenizer extension (highly recommended)', false);
 check(function_exists('mb_strlen'), 'The mb_strlen() function is available', 'Install and enable the mbstring extension', false);
@@ -83,23 +76,14 @@ function get_ini_path()
 check(function_exists('utf8_decode'), 'The utf8_decode() is available', 'Install and enable the XML extension', false);
 check(function_exists('posix_isatty'), 'The posix_isatty() is available', 'Install and enable the php_posix extension (used to colorized the CLI output)', false);
 
-$accelerator =
-  (function_exists('apc_store') && ini_get('apc.enabled'))
-  ||
-  function_exists('eaccelerator_put') && ini_get('eaccelerator.enable')
-  ||
-  function_exists('xcache_set')
-;
-check($accelerator, 'A PHP accelerator is installed', 'Install a PHP accelerator like APC (highly recommended)', false);
+$apcu = (function_exists('apc_store') || function_exists('apcu_store')) && ini_get('apc.enabled');
+check($apcu, 'A PHP accelerator is installed', 'Install a PHP accelerator like APCu (highly recommended)', false);
 
 check(!ini_get('short_open_tag'), 'php.ini has short_open_tag set to off', 'Set it to off in php.ini', false);
-check(!ini_get('magic_quotes_gpc'), 'php.ini has magic_quotes_gpc set to off', 'Set it to off in php.ini', false);
-check(!ini_get('register_globals'), 'php.ini has register_globals set to off', 'Set it to off in php.ini', false);
 check(!ini_get('session.auto_start'), 'php.ini has session.auto_start set to off', 'Set it to off in php.ini', false);
 
 check(class_exists('Memcache'), 'Memcache is available', 'You must have memcache installed and enabled to use sfMemcacheCache class.', false);
 
-if (!is_cli())
-{
-  echo '
'; +if (!is_cli()) { + echo '
'; } diff --git a/data/bin/release.php b/data/bin/release.php index 366510b48..ad652a3bf 100644 --- a/data/bin/release.php +++ b/data/bin/release.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) 2004-2007 Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -13,65 +13,59 @@ * * Usage: php data/bin/release.php 1.3.0 stable * - * @package symfony * @author Fabien Potencier + * * @version SVN: $Id$ */ -require_once(__DIR__.'/../../lib/exception/sfException.class.php'); -require_once(__DIR__.'/../../lib/task/sfFilesystem.class.php'); -require_once(__DIR__.'/../../lib/util/sfFinder.class.php'); -require_once(__DIR__.'/../../lib/vendor/lime/lime.php'); - -if (!isset($argv[1])) -{ - throw new Exception('You must provide version prefix.'); +require_once __DIR__.'/../../lib/exception/sfException.class.php'; + +require_once __DIR__.'/../../lib/task/sfFilesystem.class.php'; + +require_once __DIR__.'/../../lib/util/sfFinder.class.php'; + +require_once __DIR__.'/../../lib/vendor/lime/lime.php'; + +if (!isset($argv[1])) { + throw new Exception('You must provide version prefix.'); } -if (!isset($argv[2])) -{ - throw new Exception('You must provide stability status (alpha/beta/stable).'); +if (!isset($argv[2])) { + throw new Exception('You must provide stability status (alpha/beta/stable).'); } $stability = $argv[2]; $filesystem = new sfFilesystem(); -if (($stability == 'beta' || $stability == 'alpha') && count(explode('.', $argv[1])) < 2) -{ - $version_prefix = $argv[1]; +if (('beta' == $stability || 'alpha' == $stability) && count(explode('.', $argv[1])) < 2) { + $version_prefix = $argv[1]; - list($result) = $filesystem->execute('svn status -u '.getcwd()); - if (preg_match('/Status against revision\:\s+(\d+)\s*$/im', $result, $match)) - { - $version = $match[1]; - } + list($result) = $filesystem->execute('svn status -u '.getcwd()); + if (preg_match('/Status against revision\:\s+(\d+)\s*$/im', $result, $match)) { + $version = $match[1]; + } - if (!isset($version)) - { - throw new Exception('Unable to find last SVN revision.'); - } + if (!isset($version)) { + throw new Exception('Unable to find last SVN revision.'); + } - // make a PEAR compatible version - $version = $version_prefix.'.'.$version; -} -else -{ - $version = $argv[1]; + // make a PEAR compatible version + $version = $version_prefix.'.'.$version; +} else { + $version = $argv[1]; } -print sprintf("Releasing symfony version \"%s\".\n", $version); +echo sprintf("Releasing symfony version \"%s\".\n", $version); // tests list($result) = $filesystem->execute('php data/bin/symfony symfony:test'); -if (0 != $result) -{ - throw new Exception('Some tests failed. Release process aborted!'); +if (0 != $result) { + throw new Exception('Some tests failed. Release process aborted!'); } -if (is_file('package.xml')) -{ - $filesystem->remove(getcwd().DIRECTORY_SEPARATOR.'package.xml'); +if (is_file('package.xml')) { + $filesystem->remove(getcwd().DIRECTORY_SEPARATOR.'package.xml'); } $filesystem->copy(getcwd().'/package.xml.tmpl', getcwd().'/package.xml'); @@ -79,23 +73,21 @@ // add class files $finder = sfFinder::type('file')->relative(); $xml_classes = ''; -$dirs = array('lib' => 'php', 'data' => 'data'); -foreach ($dirs as $dir => $role) -{ - $class_files = $finder->in($dir); - foreach ($class_files as $file) - { - $xml_classes .= ''."\n"; - } +$dirs = ['lib' => 'php', 'data' => 'data']; +foreach ($dirs as $dir => $role) { + $class_files = $finder->in($dir); + foreach ($class_files as $file) { + $xml_classes .= ''."\n"; + } } // replace tokens -$filesystem->replaceTokens(getcwd().DIRECTORY_SEPARATOR.'package.xml', '##', '##', array( - 'SYMFONY_VERSION' => $version, - 'CURRENT_DATE' => date('Y-m-d'), - 'CLASS_FILES' => $xml_classes, - 'STABILITY' => $stability, -)); +$filesystem->replaceTokens(getcwd().DIRECTORY_SEPARATOR.'package.xml', '##', '##', [ + 'SYMFONY_VERSION' => $version, + 'CURRENT_DATE' => date('Y-m-d'), + 'CLASS_FILES' => $xml_classes, + 'STABILITY' => $stability, +]); list($results) = $filesystem->execute('pear package'); echo $results; diff --git a/data/bin/sandbox_installer.php b/data/bin/sandbox_installer.php index c45891174..3f35604aa 100644 --- a/data/bin/sandbox_installer.php +++ b/data/bin/sandbox_installer.php @@ -23,13 +23,11 @@ chmod(sfConfig::get('sf_data_dir').'/sandbox.db', 0777); $this->logSection('install', 'add an empty file in empty directories'); -$seen = array(); -foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(sfConfig::get('sf_root_dir')), RecursiveIteratorIterator::CHILD_FIRST) as $path => $item) -{ - if (!isset($seen[$path]) && $item->isDir() && !$item->isLink()) - { - touch($item->getRealPath().'/.sf'); - } - - $seen[$item->getPath()] = true; +$seen = []; +foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(sfConfig::get('sf_root_dir')), RecursiveIteratorIterator::CHILD_FIRST) as $path => $item) { + if (!isset($seen[$path]) && $item->isDir() && !$item->isLink()) { + touch($item->getRealPath().'/.sf'); + } + + $seen[$item->getPath()] = true; } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..c9177dc32 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,66 @@ +volumes: + db_socket: + +services: + composer: + image: composer + working_dir: /app + volumes: + - .:/app + entrypoint: + - sh + - -c + - | + exec tail -f /dev/null + + php82: &services_php82 + build: + context: .docker + args: + PHP_VERSION: '8.2' + MEMCACHE_VERSION: '8.2' + APCU_VERSION: '5.1.23' + environment: + MEMCACHED_HOST: memcached + working_dir: /app + volumes: + - .:/app + - db_socket:/var/run/mysqld + entrypoint: + - sh + - -c + - | + { + echo 'pdo_mysql.default_socket = /var/run/mysqld/mysql.sock' + echo 'memory_limit = -1' + echo 'short_open_tag = off' + echo 'magic_quotes_gpc = off' + echo 'date.timezone = "UTC"' + echo 'apc.enable_cli = on' + echo 'apc.use_request_time = 0' + } | tee -a /usr/local/etc/php/php.ini + + exec tail -f /dev/null + depends_on: + - db + - memcached + + + db: + image: mysql:5.5.62 + environment: + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + volumes: + - db_socket:/tmp + entrypoint: + - bash + - -c + - | + { + echo "CREATE DATABASE IF NOT EXISTS test;" + } | tee /docker-entrypoint-initdb.d/init.sql + + exec /usr/local/bin/docker-entrypoint.sh mysqld + + memcached: + image: memcached:1.6.13-alpine3.15 diff --git a/lib/action/sfAction.class.php b/lib/action/sfAction.class.php index f796cd30d..cabab27f0 100644 --- a/lib/action/sfAction.class.php +++ b/lib/action/sfAction.class.php @@ -12,533 +12,510 @@ /** * sfAction executes all the logic for the current request. * - * @package symfony - * @subpackage action * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ * * @method sfWebController getController() - * @method sfWebResponse getResponse() + * @method sfWebResponse getResponse() */ abstract class sfAction extends sfComponent { - protected - $security = array(); - - /** - * Initializes this action. - * - * @param sfContext $context The current application context. - * @param string $moduleName The module name. - * @param string $actionName The action name. - * - * @return void - */ - public function initialize($context, $moduleName, $actionName) - { - parent::initialize($context, $moduleName, $actionName); - - // include security configuration - if ($file = $context->getConfigCache()->checkConfig('modules/'.$this->getModuleName().'/config/security.yml', true)) + protected $security = []; + + /** + * Initializes this action. + * + * @param sfContext $context the current application context + * @param string $moduleName the module name + * @param string $actionName the action name + */ + public function initialize($context, $moduleName, $actionName) { - require($file); + parent::initialize($context, $moduleName, $actionName); + + // include security configuration + if ($file = $context->getConfigCache()->checkConfig('modules/'.$this->getModuleName().'/config/security.yml', true)) { + require $file; + } + } + + /** + * Executes an application defined process prior to execution of this sfAction object. + * + * By default, this method is empty. + */ + public function preExecute() + { + } + + /** + * Execute an application defined process immediately after execution of this sfAction object. + * + * By default, this method is empty. + */ + public function postExecute() + { + } + + /** + * Forwards current action to the default 404 error action. + * + * @param string $message Message of the generated exception + * + * @throws sfError404Exception + */ + public function forward404($message = null) + { + throw new sfError404Exception($this->get404Message($message)); + } + + /** + * Forwards current action to the default 404 error action unless the specified condition is true. + * + * @param bool $condition A condition that evaluates to true or false + * @param string $message Message of the generated exception + * + * @throws sfError404Exception + */ + public function forward404Unless($condition, $message = null) + { + if (!$condition) { + throw new sfError404Exception($this->get404Message($message)); + } + } + + /** + * Forwards current action to the default 404 error action if the specified condition is true. + * + * @param bool $condition A condition that evaluates to true or false + * @param string $message Message of the generated exception + * + * @throws sfError404Exception + */ + public function forward404If($condition, $message = null) + { + if ($condition) { + throw new sfError404Exception($this->get404Message($message)); + } + } + + /** + * Redirects current action to the default 404 error action (with browser redirection). + * + * This method stops the current code flow. + */ + public function redirect404() + { + return $this->redirect('/'.sfConfig::get('sf_error_404_module').'/'.sfConfig::get('sf_error_404_action')); + } + + /** + * Forwards current action to a new one (without browser redirection). + * + * This method stops the action. So, no code is executed after a call to this method. + * + * @param string $module A module name + * @param string $action An action name + * + * @throws sfStopException + */ + public function forward($module, $action) + { + if (sfConfig::get('sf_logging_enabled')) { + $this->dispatcher->notify(new sfEvent($this, 'application.log', [sprintf('Forward to action "%s/%s"', $module, $action)])); + } + + $this->getController()->forward($module, $action); + + throw new sfStopException(); + } + + /** + * If the condition is true, forwards current action to a new one (without browser redirection). + * + * This method stops the action. So, no code is executed after a call to this method. + * + * @param bool $condition A condition that evaluates to true or false + * @param string $module A module name + * @param string $action An action name + * + * @throws sfStopException + */ + public function forwardIf($condition, $module, $action) + { + if ($condition) { + $this->forward($module, $action); + } + } + + /** + * Unless the condition is true, forwards current action to a new one (without browser redirection). + * + * This method stops the action. So, no code is executed after a call to this method. + * + * @param bool $condition A condition that evaluates to true or false + * @param string $module A module name + * @param string $action An action name + * + * @throws sfStopException + */ + public function forwardUnless($condition, $module, $action) + { + if (!$condition) { + $this->forward($module, $action); + } + } + + /** + * Redirects current request to a new URL. + * + * 2 URL formats are accepted : + * - a full URL: http://www.google.com/ + * - an internal URL (url_for() format): module/action + * + * This method stops the action. So, no code is executed after a call to this method. + * + * @param string $url Url + * @param int $statusCode Status code (default to 302) + * + * @throws sfStopException + */ + public function redirect($url, $statusCode = 302) + { + // compatibility with url_for2() style signature + if (is_object($statusCode) || is_array($statusCode)) { + $url = array_merge(['sf_route' => $url], is_object($statusCode) ? ['sf_subject' => $statusCode] : $statusCode); + $statusCode = func_num_args() >= 3 ? func_get_arg(2) : 302; + } + + $this->getController()->redirect($url, 0, $statusCode); + + throw new sfStopException(); + } + + /** + * Redirects current request to a new URL, only if specified condition is true. + * + * This method stops the action. So, no code is executed after a call to this method. + * + * @param bool $condition A condition that evaluates to true or false + * @param string $url Url + * @param int $statusCode Status code (default to 302) + * + * @throws sfStopException + * + * @see redirect + */ + public function redirectIf($condition, $url, $statusCode = 302) + { + if ($condition) { + // compatibility with url_for2() style signature + $arguments = func_get_args(); + call_user_func_array([$this, 'redirect'], array_slice($arguments, 1)); + } } - } - - /** - * Executes an application defined process prior to execution of this sfAction object. - * - * By default, this method is empty. - */ - public function preExecute() - { - } - - /** - * Execute an application defined process immediately after execution of this sfAction object. - * - * By default, this method is empty. - */ - public function postExecute() - { - } - - /** - * Forwards current action to the default 404 error action. - * - * @param string $message Message of the generated exception - * - * @throws sfError404Exception - * - */ - public function forward404($message = null) - { - throw new sfError404Exception($this->get404Message($message)); - } - - /** - * Forwards current action to the default 404 error action unless the specified condition is true. - * - * @param bool $condition A condition that evaluates to true or false - * @param string $message Message of the generated exception - * - * @throws sfError404Exception - */ - public function forward404Unless($condition, $message = null) - { - if (!$condition) + + /** + * Redirects current request to a new URL, unless specified condition is true. + * + * This method stops the action. So, no code is executed after a call to this method. + * + * @param bool $condition A condition that evaluates to true or false + * @param string $url Url + * @param int $statusCode Status code (default to 302) + * + * @throws sfStopException + * + * @see redirect + */ + public function redirectUnless($condition, $url, $statusCode = 302) { - throw new sfError404Exception($this->get404Message($message)); + if (!$condition) { + // compatibility with url_for2() style signature + $arguments = func_get_args(); + call_user_func_array([$this, 'redirect'], array_slice($arguments, 1)); + } } - } - - /** - * Forwards current action to the default 404 error action if the specified condition is true. - * - * @param bool $condition A condition that evaluates to true or false - * @param string $message Message of the generated exception - * - * @throws sfError404Exception - */ - public function forward404If($condition, $message = null) - { - if ($condition) + + /** + * Appends the given text to the response content and bypasses the built-in view system. + * + * This method must be called as with a return: + * + * return $this->renderText('some text') + * + * @param string $text Text to append to the response + * + * @return string sfView::NONE + */ + public function renderText($text) { - throw new sfError404Exception($this->get404Message($message)); + $this->getResponse()->setContent($this->getResponse()->getContent().$text); + + return sfView::NONE; } - } - - /** - * Redirects current action to the default 404 error action (with browser redirection). - * - * This method stops the current code flow. - */ - public function redirect404() - { - return $this->redirect('/'.sfConfig::get('sf_error_404_module').'/'.sfConfig::get('sf_error_404_action')); - } - - /** - * Forwards current action to a new one (without browser redirection). - * - * This method stops the action. So, no code is executed after a call to this method. - * - * @param string $module A module name - * @param string $action An action name - * - * @throws sfStopException - */ - public function forward($module, $action) - { - if (sfConfig::get('sf_logging_enabled')) + + /** + * Convert the given data into a JSON response. + * + * return $this->renderJson(array('username' => 'john')) + * + * @param mixed $data Data to encode as JSON + * + * @return string sfView::NONE + */ + public function renderJson($data) { - $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Forward to action "%s/%s"', $module, $action)))); + $this->getResponse()->setContentType('application/json'); + $this->getResponse()->setContent(json_encode($data)); + + return sfView::NONE; } - $this->getController()->forward($module, $action); - - throw new sfStopException(); - } - - /** - * If the condition is true, forwards current action to a new one (without browser redirection). - * - * This method stops the action. So, no code is executed after a call to this method. - * - * @param bool $condition A condition that evaluates to true or false - * @param string $module A module name - * @param string $action An action name - * - * @throws sfStopException - */ - public function forwardIf($condition, $module, $action) - { - if ($condition) + /** + * Returns the partial rendered content. + * + * If the vars parameter is omitted, the action's internal variables + * will be passed, just as it would to a normal template. + * + * If the vars parameter is set then only those values are + * available in the partial. + * + * @param string $templateName partial name + * @param array $vars vars + * + * @return string The partial content + */ + public function getPartial($templateName, $vars = null) { - $this->forward($module, $action); + $this->getContext()->getConfiguration()->loadHelpers('Partial'); + + $vars = null !== $vars ? $vars : $this->varHolder->getAll(); + + return get_partial($templateName, $vars); } - } - - /** - * Unless the condition is true, forwards current action to a new one (without browser redirection). - * - * This method stops the action. So, no code is executed after a call to this method. - * - * @param bool $condition A condition that evaluates to true or false - * @param string $module A module name - * @param string $action An action name - * - * @throws sfStopException - */ - public function forwardUnless($condition, $module, $action) - { - if (!$condition) + + /** + * Appends the result of the given partial execution to the response content. + * + * This method must be called as with a return: + * + * return $this->renderPartial('foo/bar') + * + * @param string $templateName partial name + * @param array $vars vars + * + * @return string sfView::NONE + * + * @see getPartial + */ + public function renderPartial($templateName, $vars = null) { - $this->forward($module, $action); + return $this->renderText($this->getPartial($templateName, $vars)); } - } - - /** - * Redirects current request to a new URL. - * - * 2 URL formats are accepted : - * - a full URL: http://www.google.com/ - * - an internal URL (url_for() format): module/action - * - * This method stops the action. So, no code is executed after a call to this method. - * - * @param string $url Url - * @param int $statusCode Status code (default to 302) - * - * @throws sfStopException - */ - public function redirect($url, $statusCode = 302) - { - // compatibility with url_for2() style signature - if (is_object($statusCode) || is_array($statusCode)) + + /** + * Returns the component rendered content. + * + * If the vars parameter is omitted, the action's internal variables + * will be passed, just as it would to a normal template. + * + * If the vars parameter is set then only those values are + * available in the component. + * + * @param string $moduleName module name + * @param string $componentName component name + * @param array $vars vars + * + * @return string The component rendered content + */ + public function getComponent($moduleName, $componentName, $vars = null) { - $url = array_merge(array('sf_route' => $url), is_object($statusCode) ? array('sf_subject' => $statusCode) : $statusCode); - $statusCode = func_num_args() >= 3 ? func_get_arg(2) : 302; + $this->getContext()->getConfiguration()->loadHelpers('Partial'); + + $vars = null !== $vars ? $vars : $this->varHolder->getAll(); + + return get_component($moduleName, $componentName, $vars); } - $this->getController()->redirect($url, 0, $statusCode); - - throw new sfStopException(); - } - - /** - * Redirects current request to a new URL, only if specified condition is true. - * - * This method stops the action. So, no code is executed after a call to this method. - * - * @param bool $condition A condition that evaluates to true or false - * @param string $url Url - * @param int $statusCode Status code (default to 302) - * - * @throws sfStopException - * - * @see redirect - */ - public function redirectIf($condition, $url, $statusCode = 302) - { - if ($condition) + /** + * Appends the result of the given component execution to the response content. + * + * This method must be called as with a return: + * + * return $this->renderComponent('foo', 'bar') + * + * @param string $moduleName module name + * @param string $componentName component name + * @param array $vars vars + * + * @return string sfView::NONE + * + * @see getComponent + */ + public function renderComponent($moduleName, $componentName, $vars = null) { - // compatibility with url_for2() style signature - $arguments = func_get_args(); - call_user_func_array(array($this, 'redirect'), array_slice($arguments, 1)); + return $this->renderText($this->getComponent($moduleName, $componentName, $vars)); } - } - - /** - * Redirects current request to a new URL, unless specified condition is true. - * - * This method stops the action. So, no code is executed after a call to this method. - * - * @param bool $condition A condition that evaluates to true or false - * @param string $url Url - * @param int $statusCode Status code (default to 302) - * - * @throws sfStopException - * - * @see redirect - */ - public function redirectUnless($condition, $url, $statusCode = 302) - { - if (!$condition) + + /** + * Returns the security configuration for this module. + * + * @return string Current security configuration as an array + */ + public function getSecurityConfiguration() { - // compatibility with url_for2() style signature - $arguments = func_get_args(); - call_user_func_array(array($this, 'redirect'), array_slice($arguments, 1)); + return $this->security; } - } - - /** - * Appends the given text to the response content and bypasses the built-in view system. - * - * This method must be called as with a return: - * - * return $this->renderText('some text') - * - * @param string $text Text to append to the response - * - * @return string sfView::NONE - */ - public function renderText($text) - { - $this->getResponse()->setContent($this->getResponse()->getContent().$text); - - return sfView::NONE; - } - - /** - * Convert the given data into a JSON response. - * - * return $this->renderJson(array('username' => 'john')) - * - * @param mixed $data Data to encode as JSON - * - * @return string sfView::NONE - */ - public function renderJson($data) - { - $this->getResponse()->setContentType('application/json'); - $this->getResponse()->setContent(json_encode($data)); - - return sfView::NONE; - } - - /** - * Returns the partial rendered content. - * - * If the vars parameter is omitted, the action's internal variables - * will be passed, just as it would to a normal template. - * - * If the vars parameter is set then only those values are - * available in the partial. - * - * @param string $templateName partial name - * @param array $vars vars - * - * @return string The partial content - */ - public function getPartial($templateName, $vars = null) - { - $this->getContext()->getConfiguration()->loadHelpers('Partial'); - - $vars = null !== $vars ? $vars : $this->varHolder->getAll(); - - return get_partial($templateName, $vars); - } - - /** - * Appends the result of the given partial execution to the response content. - * - * This method must be called as with a return: - * - * return $this->renderPartial('foo/bar') - * - * @param string $templateName partial name - * @param array $vars vars - * - * @return string sfView::NONE - * - * @see getPartial - */ - public function renderPartial($templateName, $vars = null) - { - return $this->renderText($this->getPartial($templateName, $vars)); - } - - /** - * Returns the component rendered content. - * - * If the vars parameter is omitted, the action's internal variables - * will be passed, just as it would to a normal template. - * - * If the vars parameter is set then only those values are - * available in the component. - * - * @param string $moduleName module name - * @param string $componentName component name - * @param array $vars vars - * - * @return string The component rendered content - */ - public function getComponent($moduleName, $componentName, $vars = null) - { - $this->getContext()->getConfiguration()->loadHelpers('Partial'); - - $vars = null !== $vars ? $vars : $this->varHolder->getAll(); - - return get_component($moduleName, $componentName, $vars); - } - - /** - * Appends the result of the given component execution to the response content. - * - * This method must be called as with a return: - * - * return $this->renderComponent('foo', 'bar') - * - * @param string $moduleName module name - * @param string $componentName component name - * @param array $vars vars - * - * @return string sfView::NONE - * - * @see getComponent - */ - public function renderComponent($moduleName, $componentName, $vars = null) - { - return $this->renderText($this->getComponent($moduleName, $componentName, $vars)); - } - - /** - * Returns the security configuration for this module. - * - * @return string Current security configuration as an array - */ - public function getSecurityConfiguration() - { - return $this->security; - } - - /** - * Overrides the current security configuration for this module. - * - * @param array $security The new security configuration - */ - public function setSecurityConfiguration($security) - { - $this->security = $security; - } - - /** - * Returns a value from security.yml. - * - * @param string $name The name of the value to pull from security.yml - * @param mixed $default The default value to return if none is found in security.yml - * - * @return mixed - */ - public function getSecurityValue($name, $default = null) - { - $actionName = strtolower($this->getActionName()); - - if (isset($this->security[$actionName][$name])) + + /** + * Overrides the current security configuration for this module. + * + * @param array $security The new security configuration + */ + public function setSecurityConfiguration($security) { - return $this->security[$actionName][$name]; + $this->security = $security; } - if (isset($this->security['all'][$name])) + /** + * Returns a value from security.yml. + * + * @param string $name The name of the value to pull from security.yml + * @param mixed $default The default value to return if none is found in security.yml + */ + public function getSecurityValue($name, $default = null) { - return $this->security['all'][$name]; + $actionName = strtolower($this->getActionName()); + + if (isset($this->security[$actionName][$name])) { + return $this->security[$actionName][$name]; + } + + if (isset($this->security['all'][$name])) { + return $this->security['all'][$name]; + } + + return $default; } - return $default; - } - - /** - * Indicates that this action requires security. - * - * @return bool true, if this action requires security, otherwise false. - */ - public function isSecure() - { - return $this->getSecurityValue('is_secure', false); - } - - /** - * Gets credentials the user must have to access this action. - * - * @return mixed An array or a string describing the credentials the user must have to access this action - */ - public function getCredential() - { - return $this->getSecurityValue('credentials'); - } - - /** - * Sets an alternate template for this sfAction. - * - * See 'Naming Conventions' in the 'Symfony View' documentation. - * - * @param string $name Template name - * @param string $module The module (current if null) - */ - public function setTemplate($name, $module = null) - { - if (sfConfig::get('sf_logging_enabled')) + /** + * Indicates that this action requires security. + * + * @return bool true, if this action requires security, otherwise false + */ + public function isSecure() { - $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Change template to "%s/%s"', null === $module ? 'CURRENT' : $module, $name)))); + return $this->getSecurityValue('is_secure', false); } - if (null !== $module) + /** + * Gets credentials the user must have to access this action. + * + * @return mixed An array or a string describing the credentials the user must have to access this action + */ + public function getCredential() { - $dir = $this->context->getConfiguration()->getTemplateDir($module, $name.sfView::SUCCESS.'.php'); - $name = $dir.'/'.$name; + return $this->getSecurityValue('credentials'); } - sfConfig::set('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_template', $name); - } - - /** - * Gets the name of the alternate template for this sfAction. - * - * WARNING: It only returns the template you set with the setTemplate() method, - * and does not return the template that you configured in your view.yml. - * - * See 'Naming Conventions' in the 'Symfony View' documentation. - * - * @return string Template name. Returns null if no template has been set within the action - */ - public function getTemplate() - { - return sfConfig::get('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_template'); - } - - /** - * Sets an alternate layout for this sfAction. - * - * To de-activate the layout, set the layout name to false. - * - * To revert the layout to the one configured in the view.yml, set the template name to null. - * - * @param mixed $name Layout name or false to de-activate the layout - */ - public function setLayout($name) - { - if (sfConfig::get('sf_logging_enabled')) + /** + * Sets an alternate template for this sfAction. + * + * See 'Naming Conventions' in the 'Symfony View' documentation. + * + * @param string $name Template name + * @param string $module The module (current if null) + */ + public function setTemplate($name, $module = null) { - $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Change layout to "%s"', $name)))); + if (sfConfig::get('sf_logging_enabled')) { + $this->dispatcher->notify(new sfEvent($this, 'application.log', [sprintf('Change template to "%s/%s"', null === $module ? 'CURRENT' : $module, $name)])); + } + + if (null !== $module) { + $dir = $this->context->getConfiguration()->getTemplateDir($module, $name.sfView::SUCCESS.'.php'); + $name = $dir.'/'.$name; + } + + sfConfig::set('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_template', $name); } - sfConfig::set('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_layout', $name); - } - - /** - * Gets the name of the alternate layout for this sfAction. - * - * WARNING: It only returns the layout you set with the setLayout() method, - * and does not return the layout that you configured in your view.yml. - * - * @return mixed Layout name. Returns null if no layout has been set within the action - */ - public function getLayout() - { - return sfConfig::get('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_layout'); - } - - /** - * Changes the default view class used for rendering the template associated with the current action. - * - * @param string $class View class name - */ - public function setViewClass($class) - { - sfConfig::set('mod_'.strtolower($this->getModuleName()).'_view_class', $class); - } - - /** - * Returns the current route for this request - * - * @return sfRoute The route for the request - */ - public function getRoute() - { - return $this->getRequest()->getAttribute('sf_route'); - } - - /** - * Returns a formatted message for a 404 error. - * - * @param string $message An error message (null by default) - * - * @return string The error message or a default one if null - */ - protected function get404Message($message = null) - { - return null === $message ? sprintf('This request has been forwarded to a 404 error page by the action "%s/%s".', $this->getModuleName(), $this->getActionName()) : $message; - } + /** + * Gets the name of the alternate template for this sfAction. + * + * WARNING: It only returns the template you set with the setTemplate() method, + * and does not return the template that you configured in your view.yml. + * + * See 'Naming Conventions' in the 'Symfony View' documentation. + * + * @return string Template name. Returns null if no template has been set within the action + */ + public function getTemplate() + { + return sfConfig::get('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_template'); + } + + /** + * Sets an alternate layout for this sfAction. + * + * To de-activate the layout, set the layout name to false. + * + * To revert the layout to the one configured in the view.yml, set the template name to null. + * + * @param mixed $name Layout name or false to de-activate the layout + */ + public function setLayout($name) + { + if (sfConfig::get('sf_logging_enabled')) { + $this->dispatcher->notify(new sfEvent($this, 'application.log', [sprintf('Change layout to "%s"', $name)])); + } + + sfConfig::set('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_layout', $name); + } + + /** + * Gets the name of the alternate layout for this sfAction. + * + * WARNING: It only returns the layout you set with the setLayout() method, + * and does not return the layout that you configured in your view.yml. + * + * @return mixed Layout name. Returns null if no layout has been set within the action + */ + public function getLayout() + { + return sfConfig::get('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_layout'); + } + + /** + * Changes the default view class used for rendering the template associated with the current action. + * + * @param string $class View class name + */ + public function setViewClass($class) + { + sfConfig::set('mod_'.strtolower($this->getModuleName()).'_view_class', $class); + } + + /** + * Returns the current route for this request. + * + * @return sfRoute The route for the request + */ + public function getRoute() + { + return $this->getRequest()->getAttribute('sf_route'); + } + + /** + * Returns a formatted message for a 404 error. + * + * @param string $message An error message (null by default) + * + * @return string The error message or a default one if null + */ + protected function get404Message($message = null) + { + return null === $message ? sprintf('This request has been forwarded to a 404 error page by the action "%s/%s".', $this->getModuleName(), $this->getActionName()) : $message; + } } diff --git a/lib/action/sfActionStack.class.php b/lib/action/sfActionStack.class.php index 351117588..09242f6ef 100644 --- a/lib/action/sfActionStack.class.php +++ b/lib/action/sfActionStack.class.php @@ -13,108 +13,101 @@ * sfActionStack keeps a list of all requested actions and provides accessor * methods for retrieving individual entries. * - * @package symfony - * @subpackage action * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ class sfActionStack { - /** @var sfActionStackEntry[] */ - protected - $stack = array(); - - /** - * Adds an entry to the action stack. - * - * @param string $moduleName A module name - * @param string $actionName An action name - * @param sfAction $actionInstance An sfAction implementation instance - * - * @return sfActionStackEntry sfActionStackEntry instance - */ - public function addEntry($moduleName, $actionName, $actionInstance) - { - // create our action stack entry and add it to our stack - $actionEntry = new sfActionStackEntry($moduleName, $actionName, $actionInstance); - - $this->stack[] = $actionEntry; - - return $actionEntry; - } - - /** - * Retrieves the entry at a specific index. - * - * @param int $index An entry index - * - * @return sfActionStackEntry An action stack entry implementation. - */ - public function getEntry($index) - { - $retval = null; - - if ($index > -1 && $index < count($this->stack)) + /** @var sfActionStackEntry[] */ + protected $stack = []; + + /** + * Adds an entry to the action stack. + * + * @param string $moduleName A module name + * @param string $actionName An action name + * @param sfAction $actionInstance An sfAction implementation instance + * + * @return sfActionStackEntry sfActionStackEntry instance + */ + public function addEntry($moduleName, $actionName, $actionInstance) { - $retval = $this->stack[$index]; + // create our action stack entry and add it to our stack + $actionEntry = new sfActionStackEntry($moduleName, $actionName, $actionInstance); + + $this->stack[] = $actionEntry; + + return $actionEntry; + } + + /** + * Retrieves the entry at a specific index. + * + * @param int $index An entry index + * + * @return sfActionStackEntry an action stack entry implementation + */ + public function getEntry($index) + { + $retval = null; + + if ($index > -1 && $index < count($this->stack)) { + $retval = $this->stack[$index]; + } + + return $retval; } - return $retval; - } - - /** - * Removes the entry at a specific index. - * - * @return sfActionStackEntry An action stack entry implementation. - */ - public function popEntry() - { - return array_pop($this->stack); - } - - /** - * Retrieves the first entry. - * - * @return mixed An action stack entry implementation or null if there is no sfAction instance in the stack - */ - public function getFirstEntry() - { - $retval = null; - - if (isset($this->stack[0])) + /** + * Removes the entry at a specific index. + * + * @return sfActionStackEntry an action stack entry implementation + */ + public function popEntry() { - $retval = $this->stack[0]; + return array_pop($this->stack); } - return $retval; - } + /** + * Retrieves the first entry. + * + * @return mixed An action stack entry implementation or null if there is no sfAction instance in the stack + */ + public function getFirstEntry() + { + $retval = null; + + if (isset($this->stack[0])) { + $retval = $this->stack[0]; + } - /** - * Retrieves the last entry. - * - * @return mixed An action stack entry implementation or null if there is no sfAction instance in the stack - */ - public function getLastEntry() - { - $count = count($this->stack); - $retval = null; + return $retval; + } - if (isset($this->stack[0])) + /** + * Retrieves the last entry. + * + * @return mixed An action stack entry implementation or null if there is no sfAction instance in the stack + */ + public function getLastEntry() { - $retval = $this->stack[$count - 1]; + $count = count($this->stack); + $retval = null; + + if (isset($this->stack[0])) { + $retval = $this->stack[$count - 1]; + } + + return $retval; } - return $retval; - } - - /** - * Retrieves the size of this stack. - * - * @return int The size of this stack. - */ - public function getSize() - { - return count($this->stack); - } + /** + * Retrieves the size of this stack. + * + * @return int the size of this stack + */ + public function getSize() + { + return count($this->stack); + } } diff --git a/lib/action/sfActionStackEntry.class.php b/lib/action/sfActionStackEntry.class.php index 32f691126..2d65536e3 100644 --- a/lib/action/sfActionStackEntry.class.php +++ b/lib/action/sfActionStackEntry.class.php @@ -4,7 +4,7 @@ * This file is part of the symfony package. * (c) 2004-2006 Fabien Potencier * (c) 2004-2006 Sean Kerr - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -12,83 +12,79 @@ /** * sfActionStackEntry represents information relating to a single sfAction request during a single HTTP request. * - * @package symfony - * @subpackage action * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ class sfActionStackEntry { - protected - $actionInstance = null, - $actionName = null, - $moduleName = null, - $presentation = null; + protected $actionInstance; + protected $actionName; + protected $moduleName; + protected $presentation; - /** - * Class constructor. - * - * @param string $moduleName A module name - * @param string $actionName An action name - * @param sfAction $actionInstance An sfAction implementation instance - */ - public function __construct($moduleName, $actionName, $actionInstance) - { - $this->actionName = $actionName; - $this->actionInstance = $actionInstance; - $this->moduleName = $moduleName; - } + /** + * Class constructor. + * + * @param string $moduleName A module name + * @param string $actionName An action name + * @param sfAction $actionInstance An sfAction implementation instance + */ + public function __construct($moduleName, $actionName, $actionInstance) + { + $this->actionName = $actionName; + $this->actionInstance = $actionInstance; + $this->moduleName = $moduleName; + } - /** - * Retrieves this entry's action name. - * - * @return string An action name - */ - public function getActionName() - { - return $this->actionName; - } + /** + * Retrieves this entry's action name. + * + * @return string An action name + */ + public function getActionName() + { + return $this->actionName; + } - /** - * Retrieves this entry's action instance. - * - * @return sfAction An sfAction implementation instance - */ - public function getActionInstance() - { - return $this->actionInstance; - } + /** + * Retrieves this entry's action instance. + * + * @return sfAction An sfAction implementation instance + */ + public function getActionInstance() + { + return $this->actionInstance; + } - /** - * Retrieves this entry's module name. - * - * @return string A module name - */ - public function getModuleName() - { - return $this->moduleName; - } + /** + * Retrieves this entry's module name. + * + * @return string A module name + */ + public function getModuleName() + { + return $this->moduleName; + } - /** - * Retrieves this entry's rendered view presentation. - * - * This will only exist if the view has processed and the render mode is set to sfView::RENDER_VAR. - * - * @return string Rendered view presentation - */ - public function & getPresentation() - { - return $this->presentation; - } + /** + * Retrieves this entry's rendered view presentation. + * + * This will only exist if the view has processed and the render mode is set to sfView::RENDER_VAR. + * + * @return string Rendered view presentation + */ + public function &getPresentation() + { + return $this->presentation; + } - /** - * Sets the rendered presentation for this action. - * - * @param string $presentation A rendered presentation. - */ - public function setPresentation(&$presentation) - { - $this->presentation =& $presentation; - } + /** + * Sets the rendered presentation for this action. + * + * @param string $presentation a rendered presentation + */ + public function setPresentation(&$presentation) + { + $this->presentation = &$presentation; + } } diff --git a/lib/action/sfActions.class.php b/lib/action/sfActions.class.php index fcc84b47c..2950780fc 100644 --- a/lib/action/sfActions.class.php +++ b/lib/action/sfActions.class.php @@ -4,7 +4,7 @@ * This file is part of the symfony package. * (c) 2004-2006 Fabien Potencier * (c) 2004-2006 Sean Kerr - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -12,51 +12,45 @@ /** * sfActions executes all the logic for the current request. * - * @package symfony - * @subpackage action * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ abstract class sfActions extends sfAction { - /** - * Dispatches to the action defined by the 'action' parameter of the sfRequest object. - * - * This method try to execute the executeXXX() method of the current object where XXX is the - * defined action name. - * - * @param sfRequest $request The current sfRequest object - * - * @return string A string containing the view name associated with this action - * - * @throws sfInitializationException - * - * @see sfAction - */ - public function execute($request) - { - // dispatch action - $actionToRun = 'execute'.ucfirst($this->getActionName()); - - if ($actionToRun === 'execute') + /** + * Dispatches to the action defined by the 'action' parameter of the sfRequest object. + * + * This method try to execute the executeXXX() method of the current object where XXX is the + * defined action name. + * + * @param sfRequest $request The current sfRequest object + * + * @return string A string containing the view name associated with this action + * + * @throws sfInitializationException + * + * @see sfAction + */ + public function execute($request) { - // no action given - throw new sfInitializationException(sprintf('sfAction initialization failed for module "%s". There was no action given.', $this->getModuleName())); - } + // dispatch action + $actionToRun = 'execute'.ucfirst($this->getActionName()); - if (!is_callable(array($this, $actionToRun))) - { - // action not found - throw new sfInitializationException(sprintf('sfAction initialization failed for module "%s", action "%s". You must create a "%s" method.', $this->getModuleName(), $this->getActionName(), $actionToRun)); - } + if ('execute' === $actionToRun) { + // no action given + throw new sfInitializationException(sprintf('sfAction initialization failed for module "%s". There was no action given.', $this->getModuleName())); + } - if (sfConfig::get('sf_logging_enabled')) - { - $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Call "%s->%s()"', get_class($this), $actionToRun)))); - } + if (!is_callable([$this, $actionToRun])) { + // action not found + throw new sfInitializationException(sprintf('sfAction initialization failed for module "%s", action "%s". You must create a "%s" method.', $this->getModuleName(), $this->getActionName(), $actionToRun)); + } - // run action - return $this->$actionToRun($request); - } + if (sfConfig::get('sf_logging_enabled')) { + $this->dispatcher->notify(new sfEvent($this, 'application.log', [sprintf('Call "%s->%s()"', get_class($this), $actionToRun)])); + } + + // run action + return $this->{$actionToRun}($request); + } } diff --git a/lib/action/sfComponent.class.php b/lib/action/sfComponent.class.php index e76d8d689..fb7ee72ed 100644 --- a/lib/action/sfComponent.class.php +++ b/lib/action/sfComponent.class.php @@ -11,415 +11,416 @@ /** * sfComponent. * - * @package symfony - * @subpackage action * @author Fabien Potencier - * @version SVN: $Id$ */ abstract class sfComponent { - /** @var string */ - protected $moduleName = ''; - /** @var string */ - protected $actionName = ''; - /** @var sfContext */ - protected $context = null; - /** @var sfEventDispatcher */ - protected $dispatcher = null; - /** @var sfRequest */ - protected $request = null; - /** @var sfResponse */ - protected $response = null; - /** @var sfParameterHolder */ - protected $varHolder = null; - /** @var sfParameterHolder */ - protected $requestParameterHolder = null; - - /** - * Class constructor. - * - * @see initialize() - * - * @param sfContext $context - * @param string $moduleName - * @param string $actionName - */ - public function __construct($context, $moduleName, $actionName) - { - $this->initialize($context, $moduleName, $actionName); - } - - /** - * Initializes this component. - * - * @param sfContext $context The current application context. - * @param string $moduleName The module name. - * @param string $actionName The action name. - * - * @return void - */ - public function initialize($context, $moduleName, $actionName) - { - $this->moduleName = $moduleName; - $this->actionName = $actionName; - $this->context = $context; - $this->dispatcher = $context->getEventDispatcher(); - $this->varHolder = new sfParameterHolder(); - $this->request = $context->getRequest(); - $this->response = $context->getResponse(); - $this->requestParameterHolder = $this->request->getParameterHolder(); - } - - /** - * Execute any application/business logic for this component. - * - * In a typical database-driven application, execute() handles application - * logic itself and then proceeds to create a model instance. Once the model - * instance is initialized it handles all business logic for the action. - * - * A model should represent an entity in your application. This could be a - * user account, a shopping cart, or even a something as simple as a - * single product. - * - * @param sfRequest $request The current sfRequest object - * - * @return mixed A string containing the view name associated with this action - */ - abstract function execute($request); - - /** - * Gets the module name associated with this component. - * - * @return string A module name - */ - public function getModuleName() - { - return $this->moduleName; - } - - /** - * Gets the action name associated with this component. - * - * @return string An action name - */ - public function getActionName() - { - return $this->actionName; - } - - /** - * Retrieves the current application context. - * - * @return sfContext The current sfContext instance - */ - public final function getContext() - { - return $this->context; - } - - /** - * Retrieves the current service container instance. - * - * @return sfServiceContainer The current sfServiceContainer instance - */ - public final function getServiceContainer() - { - return $this->context->getServiceContainer(); - } - - /** - * Retrieves a service from the service container. - * - * @param string $id The service identifier - * - * @return object The service instance - */ - public function getService($id) - { - return $this->getServiceContainer()->getService($id); - } - - /** - * Retrieves the current logger instance. - * - * @return sfLogger The current sfLogger instance - */ - public final function getLogger() - { - return $this->context->getLogger(); - } - - /** - * Logs a message using the sfLogger object. - * - * @param mixed $message String or object containing the message to log - * @param string $priority The priority of the message - * (available priorities: emerg, alert, crit, err, - * warning, notice, info, debug) - * - * @see sfLogger - */ - public function logMessage($message, $priority = 'info') - { - if (sfConfig::get('sf_logging_enabled')) + /** @var string */ + protected $moduleName = ''; + + /** @var string */ + protected $actionName = ''; + + /** @var sfContext */ + protected $context; + + /** @var sfEventDispatcher */ + protected $dispatcher; + + /** @var sfRequest */ + protected $request; + + /** @var sfResponse */ + protected $response; + + /** @var sfParameterHolder */ + protected $varHolder; + + /** @var sfParameterHolder */ + protected $requestParameterHolder; + + /** + * Class constructor. + * + * @see initialize() + * + * @param sfContext $context + * @param string $moduleName + * @param string $actionName + */ + public function __construct($context, $moduleName, $actionName) + { + $this->initialize($context, $moduleName, $actionName); + } + + /** + * Gets the translation for the given string. + * + * @param string $string The string to translate + * @param array $args An array of arguments for the translation + * @param string $catalogue The catalogue name + * + * @return string The translated string + */ + public function __($string, $args = [], $catalogue = 'messages') + { + return $this->context->getI18N()->__($string, $args, $catalogue); + } + + /** + * Sets a variable for the template. + * + * This is a shortcut for: + * + * $this->setVar('name', 'value') + * + * @param string $key The variable name + * @param string $value The variable value + * + * @return bool always true + * + * @see setVar() + */ + public function __set($key, $value) + { + return $this->varHolder->setByRef($key, $value); + } + + /** + * Returns true if a variable for the template is set. + * + * This is a shortcut for: + * + * $this->getVarHolder()->has('name') + * + * @param string $name The variable name + * + * @return bool true if the variable is set + */ + public function __isset($name) + { + return $this->varHolder->has($name); + } + + /** + * Removes a variable for the template. + * + * This is just really a shortcut for: + * + * $this->getVarHolder()->remove('name') + * + * @param string $name The variable Name + */ + public function __unset($name) + { + $this->varHolder->remove($name); + } + + /** + * Calls methods defined via sfEventDispatcher. + * + * @param string $method The method name + * @param array $arguments The method arguments + * + * @return mixed The returned value of the called method + * + * @throws sfException If called method is undefined + */ + public function __call($method, $arguments) + { + $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'component.method_not_found', ['method' => $method, 'arguments' => $arguments])); + if (!$event->isProcessed()) { + throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method)); + } + + return $event->getReturnValue(); + } + + /** + * Initializes this component. + * + * @param sfContext $context the current application context + * @param string $moduleName the module name + * @param string $actionName the action name + */ + public function initialize($context, $moduleName, $actionName) + { + $this->moduleName = $moduleName; + $this->actionName = $actionName; + $this->context = $context; + $this->dispatcher = $context->getEventDispatcher(); + $this->varHolder = new sfParameterHolder(); + $this->request = $context->getRequest(); + $this->response = $context->getResponse(); + $this->requestParameterHolder = $this->request->getParameterHolder(); + } + + /** + * Execute any application/business logic for this component. + * + * In a typical database-driven application, execute() handles application + * logic itself and then proceeds to create a model instance. Once the model + * instance is initialized it handles all business logic for the action. + * + * A model should represent an entity in your application. This could be a + * user account, a shopping cart, or even a something as simple as a + * single product. + * + * @param sfRequest $request The current sfRequest object + * + * @return mixed A string containing the view name associated with this action + */ + abstract public function execute($request); + + /** + * Gets the module name associated with this component. + * + * @return string A module name + */ + public function getModuleName() + { + return $this->moduleName; + } + + /** + * Gets the action name associated with this component. + * + * @return string An action name + */ + public function getActionName() + { + return $this->actionName; + } + + /** + * Retrieves the current application context. + * + * @return sfContext The current sfContext instance + */ + final public function getContext() + { + return $this->context; + } + + /** + * Retrieves the current service container instance. + * + * @return sfServiceContainer The current sfServiceContainer instance + */ + final public function getServiceContainer() + { + return $this->context->getServiceContainer(); + } + + /** + * Retrieves a service from the service container. + * + * @param string $id The service identifier + * + * @return object The service instance + */ + public function getService($id) + { + return $this->getServiceContainer()->getService($id); + } + + /** + * Retrieves the current logger instance. + * + * @return sfLogger The current sfLogger instance + */ + final public function getLogger() + { + return $this->context->getLogger(); + } + + /** + * Logs a message using the sfLogger object. + * + * @param mixed $message String or object containing the message to log + * @param string $priority The priority of the message + * (available priorities: emerg, alert, crit, err, + * warning, notice, info, debug) + * + * @see sfLogger + */ + public function logMessage($message, $priority = 'info') + { + if (sfConfig::get('sf_logging_enabled')) { + $this->dispatcher->notify(new sfEvent($this, 'application.log', [$message, 'priority' => constant('sfLogger::'.strtoupper($priority))])); + } + } + + /** + * Returns the value of a request parameter. + * + * This is a proxy method equivalent to: + * + * $this->getRequest()->getParameterHolder()->get($name) + * + * @param string $name The parameter name + * @param mixed $default The default value if parameter does not exist + * + * @return string The request parameter value + */ + public function getRequestParameter($name, $default = null) { - $this->dispatcher->notify(new sfEvent($this, 'application.log', array($message, 'priority' => constant('sfLogger::'.strtoupper($priority))))); + return $this->requestParameterHolder->get($name, $default); } - } - - /** - * Gets the translation for the given string - * - * @param string $string The string to translate - * @param array $args An array of arguments for the translation - * @param string $catalogue The catalogue name - * - * @return string The translated string - */ - public function __($string, $args = array(), $catalogue = 'messages') - { - return $this->context->getI18N()->__($string, $args, $catalogue); - } - - /** - * Returns the value of a request parameter. - * - * This is a proxy method equivalent to: - * - * $this->getRequest()->getParameterHolder()->get($name) - * - * @param string $name The parameter name - * @param mixed $default The default value if parameter does not exist - * - * @return string The request parameter value - */ - public function getRequestParameter($name, $default = null) - { - return $this->requestParameterHolder->get($name, $default); - } - - /** - * Returns true if a request parameter exists. - * - * This is a proxy method equivalent to: - * - * $this->getRequest()->getParameterHolder()->has($name) - * - * @param string $name The parameter name - * @return boolean true if the request parameter exists, false otherwise - */ - public function hasRequestParameter($name) - { - return $this->requestParameterHolder->has($name); - } - - /** - * Retrieves the current sfRequest object. - * - * This is a proxy method equivalent to: - * - * $this->getContext()->getRequest() - * - * @return sfRequest The current sfRequest implementation instance - */ - public function getRequest() - { - return $this->request; - } - - /** - * Retrieves the current sfResponse object. - * - * This is a proxy method equivalent to: - * - * $this->getContext()->getResponse() - * - * @return sfResponse The current sfResponse implementation instance - */ - public function getResponse() - { - return $this->response; - } - - /** - * Retrieves the current sfController object. - * - * This is a proxy method equivalent to: - * - * $this->getContext()->getController() - * - * @return sfController The current sfController implementation instance - */ - public function getController() - { - return $this->context->getController(); - } - - /** - * Generates a URL for the given route and arguments. - * - * This is a proxy method equivalent to: - * - * $this->getContext()->getRouting()->generate(...) - * - * @param string $route The route name - * @param array $params An array of parameters for the route - * @param Boolean $absolute Whether to generate an absolute URL or not - * - * @return string The URL - */ - public function generateUrl($route, $params = array(), $absolute = false) - { - return $this->context->getRouting()->generate($route, $params, $absolute); - } - - /** - * Retrieves the current sfUser object. - * - * This is a proxy method equivalent to: - * - * $this->getContext()->getUser() - * - * @return sfUser The current sfUser implementation instance - */ - public function getUser() - { - return $this->context->getUser(); - } - - /** - * Gets the current mailer instance. - * - * @return sfMailer A sfMailer instance - */ - public function getMailer() - { - return $this->getContext()->getMailer(); - } - - /** - * Sets a variable for the template. - * - * If you add a safe value, the variable won't be output escaped - * by symfony, so this is your responsability to ensure that the - * value is escaped properly. - * - * @param string $name The variable name - * @param mixed $value The variable value - * @param Boolean $safe true if the value is safe for output (false by default) - */ - public function setVar($name, $value, $safe = false) - { - $this->varHolder->set($name, $safe ? new sfOutputEscaperSafe($value) : $value); - } - - /** - * Gets a variable set for the template. - * - * @param string $name The variable name - * - * @return mixed The variable value - */ - public function getVar($name) - { - return $this->varHolder->get($name); - } - - /** - * Gets the sfParameterHolder object that stores the template variables. - * - * @return sfParameterHolder The variable holder. - */ - public function getVarHolder() - { - return $this->varHolder; - } - - /** - * Sets a variable for the template. - * - * This is a shortcut for: - * - * $this->setVar('name', 'value') - * - * @param string $key The variable name - * @param string $value The variable value - * - * @return boolean always true - * - * @see setVar() - */ - public function __set($key, $value) - { - return $this->varHolder->setByRef($key, $value); - } - - /** - * Gets a variable for the template. - * - * This is a shortcut for: - * - * $this->getVar('name') - * - * @param string $key The variable name - * - * @return mixed The variable value - * - * @see getVar() - */ - public function & __get($key) - { - return $this->varHolder->get($key); - } - - /** - * Returns true if a variable for the template is set. - * - * This is a shortcut for: - * - * $this->getVarHolder()->has('name') - * - * @param string $name The variable name - * - * @return boolean true if the variable is set - */ - public function __isset($name) - { - return $this->varHolder->has($name); - } - - /** - * Removes a variable for the template. - * - * This is just really a shortcut for: - * - * $this->getVarHolder()->remove('name') - * - * @param string $name The variable Name - */ - public function __unset($name) - { - $this->varHolder->remove($name); - } - - /** - * Calls methods defined via sfEventDispatcher. - * - * @param string $method The method name - * @param array $arguments The method arguments - * - * @return mixed The returned value of the called method - * - * @throws sfException If called method is undefined - */ - public function __call($method, $arguments) - { - $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'component.method_not_found', array('method' => $method, 'arguments' => $arguments))); - if (!$event->isProcessed()) + + /** + * Returns true if a request parameter exists. + * + * This is a proxy method equivalent to: + * + * $this->getRequest()->getParameterHolder()->has($name) + * + * @param string $name The parameter name + * + * @return bool true if the request parameter exists, false otherwise + */ + public function hasRequestParameter($name) + { + return $this->requestParameterHolder->has($name); + } + + /** + * Retrieves the current sfRequest object. + * + * This is a proxy method equivalent to: + * + * $this->getContext()->getRequest() + * + * @return sfRequest The current sfRequest implementation instance + */ + public function getRequest() + { + return $this->request; + } + + /** + * Retrieves the current sfResponse object. + * + * This is a proxy method equivalent to: + * + * $this->getContext()->getResponse() + * + * @return sfResponse The current sfResponse implementation instance + */ + public function getResponse() + { + return $this->response; + } + + /** + * Retrieves the current sfController object. + * + * This is a proxy method equivalent to: + * + * $this->getContext()->getController() + * + * @return sfController The current sfController implementation instance + */ + public function getController() { - throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method)); + return $this->context->getController(); } - return $event->getReturnValue(); - } + /** + * Generates a URL for the given route and arguments. + * + * This is a proxy method equivalent to: + * + * $this->getContext()->getRouting()->generate(...) + * + * @param string $route The route name + * @param array $params An array of parameters for the route + * @param bool $absolute Whether to generate an absolute URL or not + * + * @return string The URL + */ + public function generateUrl($route, $params = [], $absolute = false) + { + return $this->context->getRouting()->generate($route, $params, $absolute); + } + + /** + * Retrieves the current sfUser object. + * + * This is a proxy method equivalent to: + * + * $this->getContext()->getUser() + * + * @return sfUser The current sfUser implementation instance + */ + public function getUser() + { + return $this->context->getUser(); + } + + /** + * Gets the current mailer instance. + * + * @return sfMailer A sfMailer instance + */ + public function getMailer() + { + return $this->getContext()->getMailer(); + } + + /** + * Sets a variable for the template. + * + * If you add a safe value, the variable won't be output escaped + * by symfony, so this is your responsability to ensure that the + * value is escaped properly. + * + * @param string $name The variable name + * @param mixed $value The variable value + * @param bool $safe true if the value is safe for output (false by default) + */ + public function setVar($name, $value, $safe = false) + { + $this->varHolder->set($name, $safe ? new sfOutputEscaperSafe($value) : $value); + } + + /** + * Gets a variable set for the template. + * + * @param string $name The variable name + * + * @return mixed The variable value + */ + public function getVar($name) + { + return $this->varHolder->get($name); + } + + /** + * Gets the sfParameterHolder object that stores the template variables. + * + * @return sfParameterHolder the variable holder + */ + public function getVarHolder() + { + return $this->varHolder; + } + + /** + * Gets a variable for the template. + * + * This is a shortcut for: + * + * $this->getVar('name') + * + * @param string $key The variable name + * + * @return mixed The variable value + * + * @see getVar() + */ + public function &__get($key) + { + return $this->varHolder->get($key); + } } diff --git a/lib/action/sfComponents.class.php b/lib/action/sfComponents.class.php index 2b6179955..10028b7c8 100644 --- a/lib/action/sfComponents.class.php +++ b/lib/action/sfComponents.class.php @@ -11,22 +11,19 @@ /** * sfComponents. * - * @package symfony - * @subpackage action * @author Fabien Potencier - * @version SVN: $Id$ */ abstract class sfComponents extends sfComponent { - /** - * @param sfRequest $request - * @return mixed - * @throws sfInitializationException - * - * @see sfComponent - */ - public function execute($request) - { - throw new sfInitializationException('sfComponents initialization failed.'); - } + /** + * @param sfRequest $request + * + * @throws sfInitializationException + * + * @see sfComponent + */ + public function execute($request) + { + throw new sfInitializationException('sfComponents initialization failed.'); + } } diff --git a/lib/addon/sfData.class.php b/lib/addon/sfData.class.php index 9741246cb..4d5e4e448 100644 --- a/lib/addon/sfData.class.php +++ b/lib/addon/sfData.class.php @@ -12,119 +12,105 @@ * This class defines the interface for interacting with data, as well * as default implementations. * - * @package symfony - * @subpackage addon * @author Fabien Potencier - * @version SVN: $Id$ */ abstract class sfData { - protected - $deleteCurrentData = true, - $object_references = array(); + protected $deleteCurrentData = true; + protected $object_references = []; - /** - * Sets a flag to indicate if the current data in the database - * should be deleted before new data is loaded. - * - * @param boolean $boolean The flag value - */ - public function setDeleteCurrentData($boolean) - { - $this->deleteCurrentData = $boolean; - } + /** + * Sets a flag to indicate if the current data in the database + * should be deleted before new data is loaded. + * + * @param bool $boolean The flag value + */ + public function setDeleteCurrentData($boolean) + { + $this->deleteCurrentData = $boolean; + } - /** - * Gets the current value of the flag that indicates whether - * current data is to be deleted or not. - * - * @return boolean - */ - public function getDeleteCurrentData() - { - return $this->deleteCurrentData; - } + /** + * Gets the current value of the flag that indicates whether + * current data is to be deleted or not. + * + * @return bool + */ + public function getDeleteCurrentData() + { + return $this->deleteCurrentData; + } - /** - * Loads data for the database from a YAML file - * - * @param string $file The path to the YAML file. - */ - protected function doLoadDataFromFile($file) - { - // import new datas - $data = sfYaml::load($file, sfConfig::get('sf_charset', 'UTF-8')); + /** + * Manages the insertion of data into the data source. + * + * @param array $data The data to be inserted into the data source + */ + abstract public function loadDataFromArray($data); - $this->loadDataFromArray($data); - } + /** + * Gets a list of one or more *.yml files and returns the list in an array. + * + * The returned array of files is sorted by alphabetical order. + * + * @param array|string $element A directory or file name or an array of directories and/or file names + * If null, then defaults to 'sf_data_dir'/fixtures + * + * @return array A list of *.yml files + * + * @throws sfInitializationException if the directory or file does not exist + */ + public function getFiles($element = null) + { + if (null === $element) { + $element = sfConfig::get('sf_data_dir').'/fixtures'; + } - /** - * Manages the insertion of data into the data source - * - * @param array $data The data to be inserted into the data source - */ - abstract public function loadDataFromArray($data); + $files = []; + if (is_array($element)) { + foreach ($element as $e) { + $files = array_merge($files, $this->getFiles($e)); + } + } elseif (is_file($element)) { + $files[] = $element; + } elseif (is_dir($element)) { + $files = sfFinder::type('file')->name('*.yml')->sort_by_name()->in($element); + } else { + throw new sfInitializationException(sprintf('You must give an array, a directory or a file to sfData::getFiles() (%s given).', $element)); + } - /** - * Manages reading all of the fixture data files and - * loading them into the data source - * - * @param array $files The path names of the YAML data files - */ - protected function doLoadData(array $files) - { - $this->object_references = array(); - $this->maps = array(); + $files = array_unique($files); + sort($files); - foreach ($files as $file) - { - $this->doLoadDataFromFile($file); + return $files; } - } - /** - * Gets a list of one or more *.yml files and returns the list in an array. - * - * The returned array of files is sorted by alphabetical order. - * - * @param string|array $element A directory or file name or an array of directories and/or file names - * If null, then defaults to 'sf_data_dir'/fixtures - * - * @return array A list of *.yml files - * - * @throws sfInitializationException If the directory or file does not exist. - */ - public function getFiles($element = null) - { - if (null === $element) + /** + * Loads data for the database from a YAML file. + * + * @param string $file the path to the YAML file + */ + protected function doLoadDataFromFile($file) { - $element = sfConfig::get('sf_data_dir').'/fixtures'; - } + // import new datas + $data = sfYaml::load($file, sfConfig::get('sf_charset', 'UTF-8')); - $files = array(); - if (is_array($element)) - { - foreach ($element as $e) - { - $files = array_merge($files, $this->getFiles($e)); - } - } - else if (is_file($element)) - { - $files[] = $element; - } - else if (is_dir($element)) - { - $files = sfFinder::type('file')->name('*.yml')->sort_by_name()->in($element); - } - else - { - throw new sfInitializationException(sprintf('You must give an array, a directory or a file to sfData::getFiles() (%s given).', $element)); + $this->loadDataFromArray($data); } - $files = array_unique($files); - sort($files); + /** + * Manages reading all of the fixture data files and + * loading them into the data source. + * + * @param array $files The path names of the YAML data files + */ + protected function doLoadData(array $files) + { + $this->object_references = []; + $this->maps = []; - return $files; - } + foreach ($files as $file) { + $this->doLoadDataFromFile($file); + } + } } diff --git a/lib/addon/sfPager.class.php b/lib/addon/sfPager.class.php index 84a4cc5f1..a1f988747 100644 --- a/lib/addon/sfPager.class.php +++ b/lib/addon/sfPager.class.php @@ -11,611 +11,563 @@ /** * sfPager class. * - * @package symfony - * @subpackage addon * @author Fabien Potencier - * @version SVN: $Id$ */ abstract class sfPager implements Iterator, Countable { - protected - $page = 1, - $maxPerPage = 0, - $lastPage = 1, - $nbResults = 0, - $class = '', - $tableName = '', - $objects = null, - $cursor = 1, - $parameters = array(), - $currentMaxLink = 1, - $parameterHolder = null, - $maxRecordLimit = false, - + protected $page = 1; + protected $maxPerPage = 0; + protected $lastPage = 1; + protected $nbResults = 0; + protected $class = ''; + protected $tableName = ''; + protected $objects; + protected $cursor = 1; + protected $parameters = []; + protected $currentMaxLink = 1; + protected $parameterHolder; + protected $maxRecordLimit = false; // used by iterator interface - $results = null, - $resultsCounter = 0; - - /** - * Constructor. - * - * @param string $class The model class - * @param integer $maxPerPage Number of records to display per page - */ - public function __construct($class, $maxPerPage = 10) - { - $this->setClass($class); - $this->setMaxPerPage($maxPerPage); - $this->parameterHolder = new sfParameterHolder(); - } - - /** - * Initialize the pager. - * - * Function to be called after parameters have been set. - */ - abstract public function init(); - - /** - * Returns an array of results on the given page. - * - * @return array - */ - abstract public function getResults(); - - /** - * Returns an object at a certain offset. - * - * Used internally by {@link getCurrent()}. - * - * @param int $offset - * @return mixed - */ - abstract protected function retrieveObject($offset); - - /** - * Returns the current pager's max link. - * - * @return integer - */ - public function getCurrentMaxLink() - { - return $this->currentMaxLink; - } - - /** - * Returns the current pager's max record limit. - * - * @return integer - */ - public function getMaxRecordLimit() - { - return $this->maxRecordLimit; - } - - /** - * Sets the current pager's max record limit. - * - * @param integer $limit - */ - public function setMaxRecordLimit($limit) - { - $this->maxRecordLimit = $limit; - } - - /** - * Returns an array of page numbers to use in pagination links. - * - * @param integer $nb_links The maximum number of page numbers to return - * - * @return array - */ - public function getLinks($nb_links = 5) - { - $links = array(); - $tmp = $this->page - floor($nb_links / 2); - $check = $this->lastPage - $nb_links + 1; - $limit = $check > 0 ? $check : 1; - $begin = $tmp > 0 ? ($tmp > $limit ? $limit : $tmp) : 1; - - $i = (int) $begin; - while ($i < $begin + $nb_links && $i <= $this->lastPage) - { - $links[] = $i++; - } - - $this->currentMaxLink = count($links) ? $links[count($links) - 1] : 1; - - return $links; - } - - /** - * Returns true if the current query requires pagination. - * - * @return boolean - */ - public function haveToPaginate() - { - return $this->getMaxPerPage() && $this->getNbResults() > $this->getMaxPerPage(); - } - - /** - * Returns the current cursor. - * - * @return integer - */ - public function getCursor() - { - return $this->cursor; - } - - /** - * Sets the current cursor. - * - * @param integer $pos - */ - public function setCursor($pos) - { - if ($pos < 1) - { - $this->cursor = 1; - } - else if ($pos > $this->nbResults) - { - $this->cursor = $this->nbResults; - } - else - { - $this->cursor = $pos; - } - } - - /** - * Returns an object by cursor position. - * - * @param integer $pos - * - * @return mixed - */ - public function getObjectByCursor($pos) - { - $this->setCursor($pos); - - return $this->getCurrent(); - } - - /** - * Returns the current object. - * - * @return mixed - */ - public function getCurrent() - { - return $this->retrieveObject($this->cursor); - } - - /** - * Returns the next object. - * - * @return mixed|null - */ - public function getNext() - { - if ($this->cursor + 1 > $this->nbResults) - { - return null; - } - else - { - return $this->retrieveObject($this->cursor + 1); - } - } - - /** - * Returns the previous object. - * - * @return mixed|null - */ - public function getPrevious() - { - if ($this->cursor - 1 < 1) + protected $results; + protected $resultsCounter = 0; + + /** + * Constructor. + * + * @param string $class The model class + * @param int $maxPerPage Number of records to display per page + */ + public function __construct($class, $maxPerPage = 10) { - return null; + $this->setClass($class); + $this->setMaxPerPage($maxPerPage); + $this->parameterHolder = new sfParameterHolder(); } - else - { - return $this->retrieveObject($this->cursor - 1); - } - } - - /** - * Returns the first index on the current page. - * - * @return integer - */ - public function getFirstIndice() - { - if ($this->page == 0) - { - return 1; + + /** + * Initialize the pager. + * + * Function to be called after parameters have been set. + */ + abstract public function init(); + + /** + * Returns an array of results on the given page. + * + * @return array + */ + abstract public function getResults(); + + /** + * Returns the current pager's max link. + * + * @return int + */ + public function getCurrentMaxLink() + { + return $this->currentMaxLink; } - else - { - return ($this->page - 1) * $this->maxPerPage + 1; + + /** + * Returns the current pager's max record limit. + * + * @return int + */ + public function getMaxRecordLimit() + { + return $this->maxRecordLimit; } - } - /** - * Returns the last index on the current page. - * - * @return integer - */ - public function getLastIndice() - { - if ($this->page == 0) + /** + * Sets the current pager's max record limit. + * + * @param int $limit + */ + public function setMaxRecordLimit($limit) { - return $this->nbResults; + $this->maxRecordLimit = $limit; } - else + + /** + * Returns an array of page numbers to use in pagination links. + * + * @param int $nb_links The maximum number of page numbers to return + * + * @return array + */ + public function getLinks($nb_links = 5) { - if ($this->page * $this->maxPerPage >= $this->nbResults) - { - return $this->nbResults; - } - else - { + $links = []; + $tmp = $this->page - floor($nb_links / 2); + $check = $this->lastPage - $nb_links + 1; + $limit = $check > 0 ? $check : 1; + $begin = $tmp > 0 ? ($tmp > $limit ? $limit : $tmp) : 1; + + $i = (int) $begin; + while ($i < $begin + $nb_links && $i <= $this->lastPage) { + $links[] = $i++; + } + + $this->currentMaxLink = count($links) ? $links[count($links) - 1] : 1; + + return $links; + } + + /** + * Returns true if the current query requires pagination. + * + * @return bool + */ + public function haveToPaginate() + { + return $this->getMaxPerPage() && $this->getNbResults() > $this->getMaxPerPage(); + } + + /** + * Returns the current cursor. + * + * @return int + */ + public function getCursor() + { + return $this->cursor; + } + + /** + * Sets the current cursor. + * + * @param int $pos + */ + public function setCursor($pos) + { + if ($pos < 1) { + $this->cursor = 1; + } elseif ($pos > $this->nbResults) { + $this->cursor = $this->nbResults; + } else { + $this->cursor = $pos; + } + } + + /** + * Returns an object by cursor position. + * + * @param int $pos + */ + public function getObjectByCursor($pos) + { + $this->setCursor($pos); + + return $this->getCurrent(); + } + + /** + * Returns the current object. + */ + public function getCurrent() + { + return $this->retrieveObject($this->cursor); + } + + /** + * Returns the next object. + * + * @return mixed|null + */ + public function getNext() + { + if ($this->cursor + 1 > $this->nbResults) { + return null; + } + + return $this->retrieveObject($this->cursor + 1); + } + + /** + * Returns the previous object. + * + * @return mixed|null + */ + public function getPrevious() + { + if ($this->cursor - 1 < 1) { + return null; + } + + return $this->retrieveObject($this->cursor - 1); + } + + /** + * Returns the first index on the current page. + * + * @return int + */ + public function getFirstIndice() + { + if (0 == $this->page) { + return 1; + } + + return ($this->page - 1) * $this->maxPerPage + 1; + } + + /** + * Returns the last index on the current page. + * + * @return int + */ + public function getLastIndice() + { + if (0 == $this->page) { + return $this->nbResults; + } + + if ($this->page * $this->maxPerPage >= $this->nbResults) { + return $this->nbResults; + } + return $this->page * $this->maxPerPage; - } - } - } - - /** - * Returns the current class. - * - * @return string - */ - public function getClass() - { - return $this->class; - } - - /** - * Sets the current class. - * - * @param string $class - */ - public function setClass($class) - { - $this->class = $class; - } - - /** - * Returns the number of results. - * - * @return integer - */ - public function getNbResults() - { - return $this->nbResults; - } - - /** - * Sets the number of results. - * - * @param integer $nb - */ - protected function setNbResults($nb) - { - $this->nbResults = $nb; - } - - /** - * Returns the first page number. - * - * @return integer - */ - public function getFirstPage() - { - return 1; - } - - /** - * Returns the last page number. - * - * @return integer - */ - public function getLastPage() - { - return $this->lastPage; - } - - /** - * Sets the last page number. - * - * @param integer $page - */ - protected function setLastPage($page) - { - $this->lastPage = $page; - - if ($this->getPage() > $page) - { - $this->setPage($page); - } - } - - /** - * Returns the current page. - * - * @return integer - */ - public function getPage() - { - return $this->page; - } - - /** - * Returns the next page. - * - * @return integer - */ - public function getNextPage() - { - return min($this->getPage() + 1, $this->getLastPage()); - } - - /** - * Returns the previous page. - * - * @return integer - */ - public function getPreviousPage() - { - return max($this->getPage() - 1, $this->getFirstPage()); - } - - /** - * Sets the current page. - * - * @param integer $page - */ - public function setPage($page) - { - $this->page = (int) $page; - - if ($this->page <= 0) - { - // set first page, which depends on a maximum set - $this->page = $this->getMaxPerPage() ? 1 : 0; - } - } - - /** - * Returns the maximum number of results per page. - * - * @return integer - */ - public function getMaxPerPage() - { - return $this->maxPerPage; - } - - /** - * Sets the maximum number of results per page. - * - * @param integer $max - */ - public function setMaxPerPage($max) - { - if ($max > 0) - { - $this->maxPerPage = $max; - if ($this->page == 0) - { - $this->page = 1; - } - } - else if ($max == 0) - { - $this->maxPerPage = 0; - $this->page = 0; - } - else - { - $this->maxPerPage = 1; - if ($this->page == 0) - { - $this->page = 1; - } - } - } - - /** - * Returns true if on the first page. - * - * @return boolean - */ - public function isFirstPage() - { - return 1 == $this->page; - } - - /** - * Returns true if on the last page. - * - * @return boolean - */ - public function isLastPage() - { - return $this->page == $this->lastPage; - } - - /** - * Returns the current pager's parameter holder. - * - * @return sfParameterHolder - */ - public function getParameterHolder() - { - return $this->parameterHolder; - } - - /** - * Returns a parameter. - * - * @param string $name - * @param mixed $default - * - * @return mixed - */ - public function getParameter($name, $default = null) - { - return $this->parameterHolder->get($name, $default); - } - - /** - * Checks whether a parameter has been set. - * - * @param string $name - * - * @return boolean - */ - public function hasParameter($name) - { - return $this->parameterHolder->has($name); - } - - /** - * Sets a parameter. - * - * @param string $name - * @param mixed $value - */ - public function setParameter($name, $value) - { - $this->parameterHolder->set($name, $value); - } - - /** - * Returns true if the properties used for iteration have been initialized. - * - * @return boolean - */ - protected function isIteratorInitialized() - { - return null !== $this->results; - } - - /** - * Loads data into properties used for iteration. - */ - protected function initializeIterator() - { - $this->results = $this->getResults(); - $this->resultsCounter = count($this->results); - } - - /** - * Empties properties used for iteration. - */ - protected function resetIterator() - { - $this->results = null; - $this->resultsCounter = 0; - } - - /** - * Returns the current result. - * - * @see Iterator - */ - #[\ReturnTypeWillChange] - public function current() - { - if (!$this->isIteratorInitialized()) - { - $this->initializeIterator(); - } - - return current($this->results); - } - - /** - * Returns the current key. - * - * @see Iterator - */ - #[\ReturnTypeWillChange] - public function key() - { - if (!$this->isIteratorInitialized()) - { - $this->initializeIterator(); - } - - return key($this->results); - } - - /** - * Advances the internal pointer and returns the current result. - * - * @see Iterator - */ - #[\ReturnTypeWillChange] - public function next() - { - if (!$this->isIteratorInitialized()) - { - $this->initializeIterator(); - } - - --$this->resultsCounter; - - return next($this->results); - } - - /** - * Resets the internal pointer and returns the current result. - * - * @see Iterator - */ - #[\ReturnTypeWillChange] - public function rewind() - { - if (!$this->isIteratorInitialized()) - { - $this->initializeIterator(); - } - - $this->resultsCounter = count($this->results); - - return reset($this->results); - } - - /** - * Returns true if pointer is within bounds. - * - * @see Iterator - */ - #[\ReturnTypeWillChange] - public function valid() - { - if (!$this->isIteratorInitialized()) - { - $this->initializeIterator(); - } - - return $this->resultsCounter > 0; - } - - /** - * Returns the total number of results. - * - * @see Countable - */ - #[\ReturnTypeWillChange] - public function count() - { - return $this->getNbResults(); - } + } + + /** + * Returns the current class. + * + * @return string + */ + public function getClass() + { + return $this->class; + } + + /** + * Sets the current class. + * + * @param string $class + */ + public function setClass($class) + { + $this->class = $class; + } + + /** + * Returns the number of results. + * + * @return int + */ + public function getNbResults() + { + return $this->nbResults; + } + + /** + * Returns the first page number. + * + * @return int + */ + public function getFirstPage() + { + return 1; + } + + /** + * Returns the last page number. + * + * @return int + */ + public function getLastPage() + { + return $this->lastPage; + } + + /** + * Returns the current page. + * + * @return int + */ + public function getPage() + { + return $this->page; + } + + /** + * Returns the next page. + * + * @return int + */ + public function getNextPage() + { + return min($this->getPage() + 1, $this->getLastPage()); + } + + /** + * Returns the previous page. + * + * @return int + */ + public function getPreviousPage() + { + return max($this->getPage() - 1, $this->getFirstPage()); + } + + /** + * Sets the current page. + * + * @param int $page + */ + public function setPage($page) + { + $this->page = (int) $page; + + if ($this->page <= 0) { + // set first page, which depends on a maximum set + $this->page = $this->getMaxPerPage() ? 1 : 0; + } + } + + /** + * Returns the maximum number of results per page. + * + * @return int + */ + public function getMaxPerPage() + { + return $this->maxPerPage; + } + + /** + * Sets the maximum number of results per page. + * + * @param int $max + */ + public function setMaxPerPage($max) + { + if ($max > 0) { + $this->maxPerPage = $max; + if (0 == $this->page) { + $this->page = 1; + } + } elseif (0 == $max) { + $this->maxPerPage = 0; + $this->page = 0; + } else { + $this->maxPerPage = 1; + if (0 == $this->page) { + $this->page = 1; + } + } + } + + /** + * Returns true if on the first page. + * + * @return bool + */ + public function isFirstPage() + { + return 1 == $this->page; + } + + /** + * Returns true if on the last page. + * + * @return bool + */ + public function isLastPage() + { + return $this->page == $this->lastPage; + } + + /** + * Returns the current pager's parameter holder. + * + * @return sfParameterHolder + */ + public function getParameterHolder() + { + return $this->parameterHolder; + } + + /** + * Returns a parameter. + * + * @param string $name + * @param mixed|null $default + */ + public function getParameter($name, $default = null) + { + return $this->parameterHolder->get($name, $default); + } + + /** + * Checks whether a parameter has been set. + * + * @param string $name + * + * @return bool + */ + public function hasParameter($name) + { + return $this->parameterHolder->has($name); + } + + /** + * Sets a parameter. + * + * @param string $name + */ + public function setParameter($name, $value) + { + $this->parameterHolder->set($name, $value); + } + + /** + * Returns the current result. + * + * @see Iterator + */ + #[ReturnTypeWillChange] + public function current() + { + if (!$this->isIteratorInitialized()) { + $this->initializeIterator(); + } + + return current($this->results); + } + + /** + * Returns the current key. + * + * @see Iterator + */ + #[ReturnTypeWillChange] + public function key() + { + if (!$this->isIteratorInitialized()) { + $this->initializeIterator(); + } + + return key($this->results); + } + + /** + * Advances the internal pointer and returns the current result. + * + * @see Iterator + */ + #[ReturnTypeWillChange] + public function next() + { + if (!$this->isIteratorInitialized()) { + $this->initializeIterator(); + } + + --$this->resultsCounter; + + return next($this->results); + } + + /** + * Resets the internal pointer and returns the current result. + * + * @see Iterator + */ + #[ReturnTypeWillChange] + public function rewind() + { + if (!$this->isIteratorInitialized()) { + $this->initializeIterator(); + } + + $this->resultsCounter = count($this->results); + + return reset($this->results); + } + + /** + * Returns true if pointer is within bounds. + * + * @see Iterator + */ + #[ReturnTypeWillChange] + public function valid() + { + if (!$this->isIteratorInitialized()) { + $this->initializeIterator(); + } + + return $this->resultsCounter > 0; + } + + /** + * Returns the total number of results. + * + * @see Countable + */ + #[ReturnTypeWillChange] + public function count() + { + return $this->getNbResults(); + } + + /** + * Returns an object at a certain offset. + * + * Used internally by {@link getCurrent()}. + * + * @param int $offset + */ + abstract protected function retrieveObject($offset); + + /** + * Sets the number of results. + * + * @param int $nb + */ + protected function setNbResults($nb) + { + $this->nbResults = $nb; + } + + /** + * Sets the last page number. + * + * @param int $page + */ + protected function setLastPage($page) + { + $this->lastPage = $page; + + if ($this->getPage() > $page) { + $this->setPage($page); + } + } + + /** + * Returns true if the properties used for iteration have been initialized. + * + * @return bool + */ + protected function isIteratorInitialized() + { + return null !== $this->results; + } + + /** + * Loads data into properties used for iteration. + */ + protected function initializeIterator() + { + $this->results = $this->getResults(); + $this->resultsCounter = count($this->results); + } + + /** + * Empties properties used for iteration. + */ + protected function resetIterator() + { + $this->results = null; + $this->resultsCounter = 0; + } } diff --git a/lib/autoload/sfAutoload.class.php b/lib/autoload/sfAutoload.class.php index 035ac5d92..89543724c 100644 --- a/lib/autoload/sfAutoload.class.php +++ b/lib/autoload/sfAutoload.class.php @@ -14,227 +14,192 @@ * This class is a singleton as PHP seems to be unable to register 2 autoloaders that are instances * of the same class (why?). * - * @package symfony - * @subpackage autoload * @author Fabien Potencier - * @version SVN: $Id$ */ class sfAutoload { - static protected - $freshCache = false, - $instance = null; - - protected - $overriden = array(), - $classes = array(); - - protected function __construct() - { - } - - /** - * Retrieves the singleton instance of this class. - * - * @return sfAutoload A sfAutoload implementation instance. - */ - static public function getInstance() - { - if (!isset(self::$instance)) + protected static $freshCache = false; + protected static $instance; + + protected $overriden = []; + protected $classes = []; + + protected function __construct() { - self::$instance = new sfAutoload(); } - return self::$instance; - } - - /** - * Register sfAutoload in spl autoloader. - * - * @return void - * - * @throws sfException - */ - static public function register() - { - ini_set('unserialize_callback_func', 'spl_autoload_call'); - - if (false === spl_autoload_register(array(self::getInstance(), 'autoload'))) + /** + * Retrieves the singleton instance of this class. + * + * @return sfAutoload a sfAutoload implementation instance + */ + public static function getInstance() { - throw new sfException(sprintf('Unable to register %s::autoload as an autoloading method.', get_class(self::getInstance()))); + if (!isset(self::$instance)) { + self::$instance = new sfAutoload(); + } + + return self::$instance; } - } - - /** - * Unregister sfAutoload from spl autoloader. - * - * @return void - */ - static public function unregister() - { - spl_autoload_unregister(array(self::getInstance(), 'autoload')); - } - - /** - * Sets the path for a particular class. - * - * @param string $class A PHP class name - * @param string $path An absolute path - */ - public function setClassPath($class, $path) - { - $class = strtolower($class); - - $this->overriden[$class] = $path; - - $this->classes[$class] = $path; - } - - /** - * Returns the path where a particular class can be found. - * - * @param string $class A PHP class name - * - * @return string|null An absolute path - */ - public function getClassPath($class) - { - $class = strtolower($class); - - return isset($this->classes[$class]) ? $this->classes[$class] : null; - } - - /** - * Reloads the autoloader. - * - * @param boolean $force Whether to force a reload - * - * @return boolean True if the reload was successful, otherwise false - */ - public function reloadClasses($force = false) - { - // only (re)load the autoloading cache once per request - if (self::$freshCache && !$force) + + /** + * Register sfAutoload in spl autoloader. + * + * @throws sfException + */ + public static function register() { - return false; + ini_set('unserialize_callback_func', 'spl_autoload_call'); + + if (false === spl_autoload_register([self::getInstance(), 'autoload'])) { + throw new sfException(sprintf('Unable to register %s::autoload as an autoloading method.', get_class(self::getInstance()))); + } } - $configuration = sfProjectConfiguration::getActive(); - if (!$configuration || !$configuration instanceof sfApplicationConfiguration) + /** + * Unregister sfAutoload from spl autoloader. + */ + public static function unregister() { - return false; + spl_autoload_unregister([self::getInstance(), 'autoload']); } - self::$freshCache = true; - $path = $configuration->getConfigCache()->getCacheName('config/autoload.yml'); - if (is_file($path)) + /** + * Sets the path for a particular class. + * + * @param string $class A PHP class name + * @param string $path An absolute path + */ + public function setClassPath($class, $path) { - self::$freshCache = false; - if ($force && file_exists($path) && is_writeable($path)) - { - unlink($path); - } - } + $class = strtolower($class); - $file = $configuration->getConfigCache()->checkConfig('config/autoload.yml'); + $this->overriden[$class] = $path; - if ($force && defined('HHVM_VERSION')) - { - // workaround for https://github.com/facebook/hhvm/issues/1447 - $this->classes = eval(str_replace('classes = include $file; + $this->classes[$class] = $path; } - foreach ($this->overriden as $class => $path) + /** + * Returns the path where a particular class can be found. + * + * @param string $class A PHP class name + * + * @return string|null An absolute path + */ + public function getClassPath($class) { - $this->classes[$class] = $path; - } + $class = strtolower($class); - return true; - } - - /** - * Handles autoloading of classes that have been specified in autoload.yml. - * - * @param string $class A class name. - * - * @return boolean Returns true if the class has been loaded - */ - public function autoload($class) - { - // load the list of autoload classes - if (!$this->classes) - { - self::reloadClasses(); + return isset($this->classes[$class]) ? $this->classes[$class] : null; } - return self::loadClass($class); - } - - /** - * Tries to load a class that has been specified in autoload.yml. - * - * @param string $class A class name. - * - * @return boolean Returns true if the class has been loaded - */ - public function loadClass($class) - { - $class = strtolower($class); - - // class already exists - if (class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false))) + /** + * Reloads the autoloader. + * + * @param bool $force Whether to force a reload + * + * @return bool True if the reload was successful, otherwise false + */ + public function reloadClasses($force = false) { - return true; + // only (re)load the autoloading cache once per request + if (self::$freshCache && !$force) { + return false; + } + + $configuration = sfProjectConfiguration::getActive(); + if (!$configuration || !$configuration instanceof sfApplicationConfiguration) { + return false; + } + + self::$freshCache = true; + $path = $configuration->getConfigCache()->getCacheName('config/autoload.yml'); + if (is_file($path)) { + self::$freshCache = false; + if ($force && file_exists($path) && is_writeable($path)) { + unlink($path); + } + } + + $file = $configuration->getConfigCache()->checkConfig('config/autoload.yml'); + + if ($force && defined('HHVM_VERSION')) { + // workaround for https://github.com/facebook/hhvm/issues/1447 + $this->classes = eval(str_replace('classes = include $file; + } + + foreach ($this->overriden as $class => $path) { + $this->classes[$class] = $path; + } + + return true; } - // we have a class path, let's include it - if (isset($this->classes[$class])) + /** + * Handles autoloading of classes that have been specified in autoload.yml. + * + * @param string $class a class name + * + * @return bool Returns true if the class has been loaded + */ + public function autoload($class) { - try - { - require $this->classes[$class]; - } - catch (sfException $e) - { - $e->printStackTrace(); - } - catch (Exception $e) - { - sfException::createFromException($e)->printStackTrace(); - } - - return true; + // load the list of autoload classes + if (!$this->classes) { + self::reloadClasses(); + } + + return self::loadClass($class); } - // see if the file exists in the current module lib directory - if ( - sfContext::hasInstance() - && - ($module = sfContext::getInstance()->getModuleName()) - && - isset($this->classes[$module.'/'.$class]) - ) + /** + * Tries to load a class that has been specified in autoload.yml. + * + * @param string $class a class name + * + * @return bool Returns true if the class has been loaded + */ + public function loadClass($class) { - try - { - require $this->classes[$module.'/'.$class]; - } - catch (sfException $e) - { - $e->printStackTrace(); - } - catch (Exception $e) - { - sfException::createFromException($e)->printStackTrace(); - } - - return true; + $class = strtolower($class); + + // class already exists + if (class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false))) { + return true; + } + + // we have a class path, let's include it + if (isset($this->classes[$class])) { + try { + require $this->classes[$class]; + } catch (sfException $e) { + $e->printStackTrace(); + } catch (Exception $e) { + sfException::createFromException($e)->printStackTrace(); + } + + return true; + } + + // see if the file exists in the current module lib directory + if ( + sfContext::hasInstance() + && ($module = sfContext::getInstance()->getModuleName()) + && isset($this->classes[$module.'/'.$class]) + ) { + try { + require $this->classes[$module.'/'.$class]; + } catch (sfException $e) { + $e->printStackTrace(); + } catch (Exception $e) { + sfException::createFromException($e)->printStackTrace(); + } + + return true; + } + + return false; } - - return false; - } } diff --git a/lib/autoload/sfAutoloadAgain.class.php b/lib/autoload/sfAutoloadAgain.class.php index 6d61df830..a2771e604 100644 --- a/lib/autoload/sfAutoloadAgain.class.php +++ b/lib/autoload/sfAutoloadAgain.class.php @@ -10,123 +10,109 @@ /** * Autoload again for dev environments. - * - * @package symfony - * @subpackage autoload + * * @author Kris Wallsmith - * @version SVN: $Id$ */ class sfAutoloadAgain { - static protected - $instance = null; - - protected - $registered = false, - $reloaded = false; - - /** - * Returns the singleton autoloader. - * - * @return sfAutoloadAgain - */ - static public function getInstance() - { - if (null === self::$instance) + protected static $instance; + + protected $registered = false; + protected $reloaded = false; + + /** + * Constructor. + */ + protected function __construct() { - self::$instance = new self(); } - return self::$instance; - } - - /** - * Constructor. - */ - protected function __construct() - { - } - - /** - * Reloads the autoloader. - * - * @param string $class - * - * @return boolean - */ - public function autoload($class) - { - // only reload once - if ($this->reloaded) + /** + * Returns the singleton autoloader. + * + * @return sfAutoloadAgain + */ + public static function getInstance() { - return false; - } + if (null === self::$instance) { + self::$instance = new self(); + } - $autoloads = spl_autoload_functions(); + return self::$instance; + } - // as of PHP 5.2.11, spl_autoload_functions() returns the object as the first element of the array instead of the class name - if (version_compare(PHP_VERSION, '5.2.11', '>=')) + /** + * Reloads the autoloader. + * + * @param string $class + * + * @return bool + */ + public function autoload($class) { - foreach ($autoloads as $position => $autoload) - { - if (is_array($autoload) && $this === $autoload[0]) - { - break; + // only reload once + if ($this->reloaded) { + return false; + } + + $autoloads = spl_autoload_functions(); + + // as of PHP 5.2.11, spl_autoload_functions() returns the object as the first element of the array instead of the class name + if (version_compare(PHP_VERSION, '5.2.11', '>=')) { + foreach ($autoloads as $position => $autoload) { + if (is_array($autoload) && $this === $autoload[0]) { + break; + } + } + } else { + $position = array_search([__CLASS__, 'autoload'], $autoloads, true); } - } + + if (isset($autoloads[$position + 1])) { + $this->unregister(); + $this->register(); + + // since we're rearranged things, call the chain again + spl_autoload_call($class); + + return class_exists($class, false) || interface_exists($class, false); + } + + $autoload = sfAutoload::getInstance(); + $autoload->reloadClasses(true); + + $this->reloaded = true; + + return $autoload->autoload($class); } - else + + /** + * Returns true if the autoloader is registered. + * + * @return bool + */ + public function isRegistered() { - $position = array_search(array(__CLASS__, 'autoload'), $autoloads, true); + return $this->registered; } - if (isset($autoloads[$position + 1])) + /** + * Registers the autoloader function. + */ + public function register() { - $this->unregister(); - $this->register(); - - // since we're rearranged things, call the chain again - spl_autoload_call($class); - - return class_exists($class, false) || interface_exists($class, false); + if (!$this->isRegistered()) { + spl_autoload_register([$this, 'autoload']); + $this->registered = true; + } } - $autoload = sfAutoload::getInstance(); - $autoload->reloadClasses(true); - - $this->reloaded = true; - - return $autoload->autoload($class); - } - - /** - * Returns true if the autoloader is registered. - * - * @return boolean - */ - public function isRegistered() - { - return $this->registered; - } - - /** - * Registers the autoloader function. - */ - public function register() - { - if (!$this->isRegistered()) + /** + * Unregisters the autoloader function. + */ + public function unregister() { - spl_autoload_register(array($this, 'autoload')); - $this->registered = true; + spl_autoload_unregister([$this, 'autoload']); + $this->registered = false; } - } - - /** - * Unregisters the autoloader function. - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'autoload')); - $this->registered = false; - } } diff --git a/lib/autoload/sfCoreAutoload.class.php b/lib/autoload/sfCoreAutoload.class.php index 6d9957e17..ccc3ef7bb 100755 --- a/lib/autoload/sfCoreAutoload.class.php +++ b/lib/autoload/sfCoreAutoload.class.php @@ -8,10 +8,8 @@ * file that was distributed with this source code. */ -/** - * The current symfony version. - */ -define('SYMFONY_VERSION', '1.6.0'); +// The current symfony version. +define('SYMFONY_VERSION', '1.5.20-dev'); /** * sfCoreAutoload class. @@ -19,527 +17,512 @@ * This class is a singleton as PHP seems to be unable to register 2 autoloaders that are instances * of the same class (why?). * - * @package symfony - * @subpackage autoload * @author Fabien Potencier - * @version SVN: $Id: sfCoreAutoload.class.php 32415 2011-03-30 16:09:00Z Kris.Wallsmith - * */ class sfCoreAutoload { - static protected - $registered = false, - $instance = null; + protected static $registered = false; + protected static $instance; - protected - $baseDir = null; + protected $baseDir; - protected function __construct() - { - $this->baseDir = realpath(__DIR__.'/..'); - } + // Don't edit this property by hand. + // To update it, use sfCoreAutoload::make() + protected $classes = [ + 'sfaction' => 'action/sfAction.class.php', + 'sfactionstack' => 'action/sfActionStack.class.php', + 'sfactionstackentry' => 'action/sfActionStackEntry.class.php', + 'sfactions' => 'action/sfActions.class.php', + 'sfcomponent' => 'action/sfComponent.class.php', + 'sfcomponents' => 'action/sfComponents.class.php', + 'sfdata' => 'addon/sfData.class.php', + 'sfpager' => 'addon/sfPager.class.php', + 'sfautoload' => 'autoload/sfAutoload.class.php', + 'sfautoloadagain' => 'autoload/sfAutoloadAgain.class.php', + 'sfcoreautoload' => 'autoload/sfCoreAutoload.class.php', + 'sfsimpleautoload' => 'autoload/sfSimpleAutoload.class.php', + 'sfapcucache' => 'cache/sfAPCuCache.class.php', + 'sfcache' => 'cache/sfCache.class.php', + 'sffilecache' => 'cache/sfFileCache.class.php', + 'sffunctioncache' => 'cache/sfFunctionCache.class.php', + 'sfmemcachecache' => 'cache/sfMemcacheCache.class.php', + 'sfnocache' => 'cache/sfNoCache.class.php', + 'sfsqlitecache' => 'cache/sfSQLiteCache.class.php', + 'sfansicolorformatter' => 'command/sfAnsiColorFormatter.class.php', + 'sfcommandapplication' => 'command/sfCommandApplication.class.php', + 'sfcommandargument' => 'command/sfCommandArgument.class.php', + 'sfcommandargumentset' => 'command/sfCommandArgumentSet.class.php', + 'sfcommandargumentsexception' => 'command/sfCommandArgumentsException.class.php', + 'sfcommandexception' => 'command/sfCommandException.class.php', + 'sfcommandlogger' => 'command/sfCommandLogger.class.php', + 'sfcommandmanager' => 'command/sfCommandManager.class.php', + 'sfcommandoption' => 'command/sfCommandOption.class.php', + 'sfcommandoptionset' => 'command/sfCommandOptionSet.class.php', + 'sfformatter' => 'command/sfFormatter.class.php', + 'sfsymfonycommandapplication' => 'command/sfSymfonyCommandApplication.class.php', + 'sfapplicationconfiguration' => 'config/sfApplicationConfiguration.class.php', + 'sfautoloadconfighandler' => 'config/sfAutoloadConfigHandler.class.php', + 'sfcacheconfighandler' => 'config/sfCacheConfigHandler.class.php', + 'sfcompileconfighandler' => 'config/sfCompileConfigHandler.class.php', + 'sfconfig' => 'config/sfConfig.class.php', + 'sfconfigcache' => 'config/sfConfigCache.class.php', + 'sfconfighandler' => 'config/sfConfigHandler.class.php', + 'sfdatabaseconfighandler' => 'config/sfDatabaseConfigHandler.class.php', + 'sfdefineenvironmentconfighandler' => 'config/sfDefineEnvironmentConfigHandler.class.php', + 'sffactoryconfighandler' => 'config/sfFactoryConfigHandler.class.php', + 'sffilterconfighandler' => 'config/sfFilterConfigHandler.class.php', + 'sfgeneratorconfighandler' => 'config/sfGeneratorConfigHandler.class.php', + 'sfpluginconfiguration' => 'config/sfPluginConfiguration.class.php', + 'sfpluginconfigurationgeneric' => 'config/sfPluginConfigurationGeneric.class.php', + 'sfprojectconfiguration' => 'config/sfProjectConfiguration.class.php', + 'sfrootconfighandler' => 'config/sfRootConfigHandler.class.php', + 'sfroutingconfighandler' => 'config/sfRoutingConfigHandler.class.php', + 'sfsecurityconfighandler' => 'config/sfSecurityConfigHandler.class.php', + 'sfserviceconfighandler' => 'config/sfServiceConfigHandler.class.php', + 'sfsimpleyamlconfighandler' => 'config/sfSimpleYamlConfigHandler.class.php', + 'sfviewconfighandler' => 'config/sfViewConfigHandler.class.php', + 'sfyamlconfighandler' => 'config/sfYamlConfigHandler.class.php', + 'sfcontroller' => 'controller/sfController.class.php', + 'sffrontwebcontroller' => 'controller/sfFrontWebController.class.php', + 'sfwebcontroller' => 'controller/sfWebController.class.php', + 'sfdatabase' => 'database/sfDatabase.class.php', + 'sfdatabasemanager' => 'database/sfDatabaseManager.class.php', + 'sfmysqldatabase' => 'database/sfMySQLDatabase.class.php', + 'sfmysqlidatabase' => 'database/sfMySQLiDatabase.class.php', + 'sfpdodatabase' => 'database/sfPDODatabase.class.php', + 'sfpostgresqldatabase' => 'database/sfPostgreSQLDatabase.class.php', + 'sfdebug' => 'debug/sfDebug.class.php', + 'sftimer' => 'debug/sfTimer.class.php', + 'sftimermanager' => 'debug/sfTimerManager.class.php', + 'sfwebdebug' => 'debug/sfWebDebug.class.php', + 'sfwebdebugpanel' => 'debug/sfWebDebugPanel.class.php', + 'sfwebdebugpanelcache' => 'debug/sfWebDebugPanelCache.class.php', + 'sfwebdebugpanelconfig' => 'debug/sfWebDebugPanelConfig.class.php', + 'sfwebdebugpanellogs' => 'debug/sfWebDebugPanelLogs.class.php', + 'sfwebdebugpanelmailer' => 'debug/sfWebDebugPanelMailer.class.php', + 'sfwebdebugpanelmemory' => 'debug/sfWebDebugPanelMemory.class.php', + 'sfwebdebugpanelsymfonyversion' => 'debug/sfWebDebugPanelSymfonyVersion.class.php', + 'sfwebdebugpaneltimer' => 'debug/sfWebDebugPanelTimer.class.php', + 'sfwebdebugpanelview' => 'debug/sfWebDebugPanelView.class.php', + 'sfoutputescaper' => 'escaper/sfOutputEscaper.class.php', + 'sfoutputescaperarraydecorator' => 'escaper/sfOutputEscaperArrayDecorator.class.php', + 'sfoutputescapergetterdecorator' => 'escaper/sfOutputEscaperGetterDecorator.class.php', + 'sfoutputescaperiteratordecorator' => 'escaper/sfOutputEscaperIteratorDecorator.class.php', + 'sfoutputescaperobjectdecorator' => 'escaper/sfOutputEscaperObjectDecorator.class.php', + 'sfoutputescapersafe' => 'escaper/sfOutputEscaperSafe.class.php', + 'sfevent' => 'event/sfEvent.class.php', + 'sfeventdispatcher' => 'event/sfEventDispatcher.class.php', + 'sfcacheexception' => 'exception/sfCacheException.class.php', + 'sfconfigurationexception' => 'exception/sfConfigurationException.class.php', + 'sfcontrollerexception' => 'exception/sfControllerException.class.php', + 'sfdatabaseexception' => 'exception/sfDatabaseException.class.php', + 'sferror404exception' => 'exception/sfError404Exception.class.php', + 'sfexception' => 'exception/sfException.class.php', + 'sffactoryexception' => 'exception/sfFactoryException.class.php', + 'sffileexception' => 'exception/sfFileException.class.php', + 'sffilterexception' => 'exception/sfFilterException.class.php', + 'sfforwardexception' => 'exception/sfForwardException.class.php', + 'sfinitializationexception' => 'exception/sfInitializationException.class.php', + 'sfparseexception' => 'exception/sfParseException.class.php', + 'sfrenderexception' => 'exception/sfRenderException.class.php', + 'sfsecurityexception' => 'exception/sfSecurityException.class.php', + 'sfstopexception' => 'exception/sfStopException.class.php', + 'sfstorageexception' => 'exception/sfStorageException.class.php', + 'sfviewexception' => 'exception/sfViewException.class.php', + 'sfbasicsecurityfilter' => 'filter/sfBasicSecurityFilter.class.php', + 'sfcachefilter' => 'filter/sfCacheFilter.class.php', + 'sfcommonfilter' => 'filter/sfCommonFilter.class.php', + 'sfexecutionfilter' => 'filter/sfExecutionFilter.class.php', + 'sffilter' => 'filter/sfFilter.class.php', + 'sffilterchain' => 'filter/sfFilterChain.class.php', + 'sfrenderingfilter' => 'filter/sfRenderingFilter.class.php', + 'sfformfilter' => 'form/addon/sfFormFilter.class.php', + 'sfformobject' => 'form/addon/sfFormObject.class.php', + 'sfformsymfony' => 'form/addon/sfFormSymfony.class.php', + 'sfform' => 'form/sfForm.class.php', + 'sfformfield' => 'form/sfFormField.class.php', + 'sfformfieldschema' => 'form/sfFormFieldSchema.class.php', + 'sfgenerator' => 'generator/sfGenerator.class.php', + 'sfgeneratormanager' => 'generator/sfGeneratorManager.class.php', + 'sfmodelgenerator' => 'generator/sfModelGenerator.class.php', + 'sfmodelgeneratorconfiguration' => 'generator/sfModelGeneratorConfiguration.class.php', + 'sfmodelgeneratorconfigurationfield' => 'generator/sfModelGeneratorConfigurationField.class.php', + 'sfmodelgeneratorhelper' => 'generator/sfModelGeneratorHelper.class.php', + 'tgettext' => 'i18n/Gettext/TGettext.class.php', + 'sfi18napplicationextract' => 'i18n/extract/sfI18nApplicationExtract.class.php', + 'sfi18nextract' => 'i18n/extract/sfI18nExtract.class.php', + 'sfi18nextractorinterface' => 'i18n/extract/sfI18nExtractorInterface.class.php', + 'sfi18nmoduleextract' => 'i18n/extract/sfI18nModuleExtract.class.php', + 'sfi18nphpextractor' => 'i18n/extract/sfI18nPhpExtractor.class.php', + 'sfi18nyamlextractor' => 'i18n/extract/sfI18nYamlExtractor.class.php', + 'sfi18nyamlgeneratorextractor' => 'i18n/extract/sfI18nYamlGeneratorExtractor.class.php', + 'sfi18nyamlvalidateextractor' => 'i18n/extract/sfI18nYamlValidateExtractor.class.php', + 'sfchoiceformat' => 'i18n/sfChoiceFormat.class.php', + 'sfcultureinfo' => 'i18n/sfCultureInfo.class.php', + 'sfdateformat' => 'i18n/sfDateFormat.class.php', + 'sfdatetimeformatinfo' => 'i18n/sfDateTimeFormatInfo.class.php', + 'sfi18n' => 'i18n/sfI18N.class.php', + 'sfimessagesource' => 'i18n/sfIMessageSource.class.php', + 'sfmessageformat' => 'i18n/sfMessageFormat.class.php', + 'sfmessagesource' => 'i18n/sfMessageSource.class.php', + 'sfmessagesource_aggregate' => 'i18n/sfMessageSource_Aggregate.class.php', + 'sfmessagesource_database' => 'i18n/sfMessageSource_Database.class.php', + 'sfmessagesource_file' => 'i18n/sfMessageSource_File.class.php', + 'sfmessagesource_mysql' => 'i18n/sfMessageSource_MySQL.class.php', + 'sfmessagesource_mysqli' => 'i18n/sfMessageSource_MySQLi.class.php', + 'sfmessagesource_sqlite' => 'i18n/sfMessageSource_SQLite.class.php', + 'sfmessagesource_sqlite3' => 'i18n/sfMessageSource_SQLite3.class.php', + 'sfmessagesource_xliff' => 'i18n/sfMessageSource_XLIFF.class.php', + 'sfmessagesource_gettext' => 'i18n/sfMessageSource_gettext.class.php', + 'sfnumberformat' => 'i18n/sfNumberFormat.class.php', + 'sfnumberformatinfo' => 'i18n/sfNumberFormatInfo.class.php', + 'sfaggregatelogger' => 'log/sfAggregateLogger.class.php', + 'sfconsolelogger' => 'log/sfConsoleLogger.class.php', + 'sfeventlogger' => 'log/sfEventLogger.class.php', + 'sffilelogger' => 'log/sfFileLogger.class.php', + 'sflogger' => 'log/sfLogger.class.php', + 'sfloggerinterface' => 'log/sfLoggerInterface.class.php', + 'sfloggerwrapper' => 'log/sfLoggerWrapper.class.php', + 'sfnologger' => 'log/sfNoLogger.class.php', + 'sfpsrloggeradapter' => 'log/sfPsrLoggerAdapter.class.php', + 'sfstreamlogger' => 'log/sfStreamLogger.class.php', + 'sfvarlogger' => 'log/sfVarLogger.class.php', + 'sfwebdebuglogger' => 'log/sfWebDebugLogger.class.php', + 'sfmailer' => 'mailer/sfMailer.class.php', + 'sfmailermessageloggerplugin' => 'mailer/sfMailerMessageLoggerPlugin.class.php', + 'sfnomailer' => 'mailer/sfNoMailer.class.php', + 'sfpearconfig' => 'plugin/sfPearConfig.class.php', + 'sfpeardownloader' => 'plugin/sfPearDownloader.class.php', + 'sfpearenvironment' => 'plugin/sfPearEnvironment.class.php', + 'sfpearfrontendplugin' => 'plugin/sfPearFrontendPlugin.class.php', + 'sfpearrest' => 'plugin/sfPearRest.class.php', + 'sfpearrest10' => 'plugin/sfPearRest10.class.php', + 'sfpearrest11' => 'plugin/sfPearRest11.class.php', + 'sfpearrestplugin' => 'plugin/sfPearRestPlugin.class.php', + 'sfplugindependencyexception' => 'plugin/sfPluginDependencyException.class.php', + 'sfpluginexception' => 'plugin/sfPluginException.class.php', + 'sfpluginmanager' => 'plugin/sfPluginManager.class.php', + 'sfpluginrecursivedependencyexception' => 'plugin/sfPluginRecursiveDependencyException.class.php', + 'sfpluginrestexception' => 'plugin/sfPluginRestException.class.php', + 'sfsymfonypluginmanager' => 'plugin/sfSymfonyPluginManager.class.php', + 'sfrequest' => 'request/sfRequest.class.php', + 'sfwebrequest' => 'request/sfWebRequest.class.php', + 'sfresponse' => 'response/sfResponse.class.php', + 'sfwebresponse' => 'response/sfWebResponse.class.php', + 'sfobjectroute' => 'routing/sfObjectRoute.class.php', + 'sfobjectroutecollection' => 'routing/sfObjectRouteCollection.class.php', + 'sfpatternrouting' => 'routing/sfPatternRouting.class.php', + 'sfrequestroute' => 'routing/sfRequestRoute.class.php', + 'sfroute' => 'routing/sfRoute.class.php', + 'sfroutecollection' => 'routing/sfRouteCollection.class.php', + 'sfrouting' => 'routing/sfRouting.class.php', + 'sfservicecontainer' => 'service/sfServiceContainer.class.php', + 'sfservicecontainerbuilder' => 'service/sfServiceContainerBuilder.class.php', + 'sfservicecontainerdumper' => 'service/sfServiceContainerDumper.class.php', + 'sfservicecontainerdumpergraphviz' => 'service/sfServiceContainerDumperGraphviz.class.php', + 'sfservicecontainerdumperinterface' => 'service/sfServiceContainerDumperInterface.class.php', + 'sfservicecontainerdumperphp' => 'service/sfServiceContainerDumperPhp.class.php', + 'sfservicecontainerinterface' => 'service/sfServiceContainerInterface.class.php', + 'sfservicecontainerloader' => 'service/sfServiceContainerLoader.class.php', + 'sfservicecontainerloaderarray' => 'service/sfServiceContainerLoaderArray.class.php', + 'sfservicecontainerloaderinterface' => 'service/sfServiceContainerLoaderInterface.class.php', + 'sfservicedefinition' => 'service/sfServiceDefinition.class.php', + 'sfserviceparameter' => 'service/sfServiceParameter.class.php', + 'sfservicereference' => 'service/sfServiceReference.class.php', + 'sfcachesessionstorage' => 'storage/sfCacheSessionStorage.class.php', + 'sfdatabasesessionstorage' => 'storage/sfDatabaseSessionStorage.class.php', + 'sfmysqlsessionstorage' => 'storage/sfMySQLSessionStorage.class.php', + 'sfmysqlisessionstorage' => 'storage/sfMySQLiSessionStorage.class.php', + 'sfnostorage' => 'storage/sfNoStorage.class.php', + 'sfpdosessionstorage' => 'storage/sfPDOSessionStorage.class.php', + 'sfpostgresqlsessionstorage' => 'storage/sfPostgreSQLSessionStorage.class.php', + 'sfsessionstorage' => 'storage/sfSessionStorage.class.php', + 'sfsessionteststorage' => 'storage/sfSessionTestStorage.class.php', + 'sfstorage' => 'storage/sfStorage.class.php', + 'sfapproutestask' => 'task/app/sfAppRoutesTask.class.php', + 'sfcachecleartask' => 'task/cache/sfCacheClearTask.class.php', + 'sfconfigureauthortask' => 'task/configure/sfConfigureAuthorTask.class.php', + 'sfgenerateapptask' => 'task/generator/sfGenerateAppTask.class.php', + 'sfgeneratemoduletask' => 'task/generator/sfGenerateModuleTask.class.php', + 'sfgenerateprojecttask' => 'task/generator/sfGenerateProjectTask.class.php', + 'sfgeneratetasktask' => 'task/generator/sfGenerateTaskTask.class.php', + 'sfgeneratorbasetask' => 'task/generator/sfGeneratorBaseTask.class.php', + 'sfhelptask' => 'task/help/sfHelpTask.class.php', + 'sflisttask' => 'task/help/sfListTask.class.php', + 'sfi18nextracttask' => 'task/i18n/sfI18nExtractTask.class.php', + 'sfi18nfindtask' => 'task/i18n/sfI18nFindTask.class.php', + 'sflogcleartask' => 'task/log/sfLogClearTask.class.php', + 'sflogrotatetask' => 'task/log/sfLogRotateTask.class.php', + 'sfpluginaddchanneltask' => 'task/plugin/sfPluginAddChannelTask.class.php', + 'sfpluginbasetask' => 'task/plugin/sfPluginBaseTask.class.php', + 'sfplugininstalltask' => 'task/plugin/sfPluginInstallTask.class.php', + 'sfpluginlisttask' => 'task/plugin/sfPluginListTask.class.php', + 'sfpluginpublishassetstask' => 'task/plugin/sfPluginPublishAssetsTask.class.php', + 'sfpluginuninstalltask' => 'task/plugin/sfPluginUninstallTask.class.php', + 'sfpluginupgradetask' => 'task/plugin/sfPluginUpgradeTask.class.php', + 'sfprojectclearcontrollerstask' => 'task/project/sfProjectClearControllersTask.class.php', + 'sfprojectdeploytask' => 'task/project/sfProjectDeployTask.class.php', + 'sfprojectdisabletask' => 'task/project/sfProjectDisableTask.class.php', + 'sfprojectenabletask' => 'task/project/sfProjectEnableTask.class.php', + 'sfprojectoptimizetask' => 'task/project/sfProjectOptimizeTask.class.php', + 'sfprojectpermissionstask' => 'task/project/sfProjectPermissionsTask.class.php', + 'sfprojectsendemailstask' => 'task/project/sfProjectSendEmailsTask.class.php', + 'sfdeprecatedclassesvalidation' => 'task/project/validation/sfDeprecatedClassesValidation.class.php', + 'sfdeprecatedconfigurationfilesvalidation' => 'task/project/validation/sfDeprecatedConfigurationFilesValidation.class.php', + 'sfdeprecatedhelpersvalidation' => 'task/project/validation/sfDeprecatedHelpersValidation.class.php', + 'sfdeprecatedmethodsvalidation' => 'task/project/validation/sfDeprecatedMethodsValidation.class.php', + 'sfdeprecatedpluginsvalidation' => 'task/project/validation/sfDeprecatedPluginsValidation.class.php', + 'sfdeprecatedsettingsvalidation' => 'task/project/validation/sfDeprecatedSettingsValidation.class.php', + 'sfparameterholdervalidation' => 'task/project/validation/sfParameterHolderValidation.class.php', + 'sfvalidation' => 'task/project/validation/sfValidation.class.php', + 'sfbasetask' => 'task/sfBaseTask.class.php', + 'sfcommandapplicationtask' => 'task/sfCommandApplicationTask.class.php', + 'sffilesystem' => 'task/sfFilesystem.class.php', + 'sftask' => 'task/sfTask.class.php', + 'lime_symfony' => 'task/symfony/lime_symfony.php', + 'sfsymfonytesttask' => 'task/symfony/sfSymfonyTestTask.class.php', + 'sflimeharness' => 'task/test/sfLimeHarness.class.php', + 'sftestalltask' => 'task/test/sfTestAllTask.class.php', + 'sftestbasetask' => 'task/test/sfTestBaseTask.class.php', + 'sftestcoveragetask' => 'task/test/sfTestCoverageTask.class.php', + 'sftestfunctionaltask' => 'task/test/sfTestFunctionalTask.class.php', + 'sftestplugintask' => 'task/test/sfTestPluginTask.class.php', + 'sftestunittask' => 'task/test/sfTestUnitTask.class.php', + 'sftestbrowser' => 'test/sfTestBrowser.class.php', + 'sftestfunctional' => 'test/sfTestFunctional.class.php', + 'sftestfunctionalbase' => 'test/sfTestFunctionalBase.class.php', + 'sftester' => 'test/sfTester.class.php', + 'sftesterform' => 'test/sfTesterForm.class.php', + 'sftestermailer' => 'test/sfTesterMailer.class.php', + 'sftesterrequest' => 'test/sfTesterRequest.class.php', + 'sftesterresponse' => 'test/sfTesterResponse.class.php', + 'sftesteruser' => 'test/sfTesterUser.class.php', + 'sftesterviewcache' => 'test/sfTesterViewCache.class.php', + 'sfbasicsecurityuser' => 'user/sfBasicSecurityUser.class.php', + 'sfsecurityuser' => 'user/sfSecurityUser.class.php', + 'sfuser' => 'user/sfUser.class.php', + 'sfbrowser' => 'util/sfBrowser.class.php', + 'sfbrowserbase' => 'util/sfBrowserBase.class.php', + 'sfcallable' => 'util/sfCallable.class.php', + 'sfclassmanipulator' => 'util/sfClassManipulator.class.php', + 'sfcontext' => 'util/sfContext.class.php', + 'sfdomcssselector' => 'util/sfDomCssSelector.class.php', + 'sffinder' => 'util/sfFinder.class.php', + 'sfinflector' => 'util/sfInflector.class.php', + 'sfnamespacedparameterholder' => 'util/sfNamespacedParameterHolder.class.php', + 'sfparameterholder' => 'util/sfParameterHolder.class.php', + 'sftoolkit' => 'util/sfToolkit.class.php', + 'sfvalidatori18nchoicecountry' => 'validator/i18n/sfValidatorI18nChoiceCountry.class.php', + 'sfvalidatori18nchoicelanguage' => 'validator/i18n/sfValidatorI18nChoiceLanguage.class.php', + 'sfvalidatori18nchoicetimezone' => 'validator/i18n/sfValidatorI18nChoiceTimezone.class.php', + 'sfvalidatedfile' => 'validator/sfValidatedFile.class.php', + 'sfvalidatorand' => 'validator/sfValidatorAnd.class.php', + 'sfvalidatorbase' => 'validator/sfValidatorBase.class.php', + 'sfvalidatorboolean' => 'validator/sfValidatorBoolean.class.php', + 'sfvalidatorcsrftoken' => 'validator/sfValidatorCSRFToken.class.php', + 'sfvalidatorcallback' => 'validator/sfValidatorCallback.class.php', + 'sfvalidatorchoice' => 'validator/sfValidatorChoice.class.php', + 'sfvalidatordate' => 'validator/sfValidatorDate.class.php', + 'sfvalidatordaterange' => 'validator/sfValidatorDateRange.class.php', + 'sfvalidatordatetime' => 'validator/sfValidatorDateTime.class.php', + 'sfvalidatordecorator' => 'validator/sfValidatorDecorator.class.php', + 'sfvalidatoremail' => 'validator/sfValidatorEmail.class.php', + 'sfvalidatorequal' => 'validator/sfValidatorEqual.class.php', + 'sfvalidatorerror' => 'validator/sfValidatorError.class.php', + 'sfvalidatorerrorschema' => 'validator/sfValidatorErrorSchema.class.php', + 'sfvalidatorfile' => 'validator/sfValidatorFile.class.php', + 'sfvalidatorfilemulti' => 'validator/sfValidatorFileMulti.class.php', + 'sfvalidatorfromdescription' => 'validator/sfValidatorFromDescription.class.php', + 'sfvalidatorinteger' => 'validator/sfValidatorInteger.class.php', + 'sfvalidatorip' => 'validator/sfValidatorIp.class.php', + 'sfvalidatornumber' => 'validator/sfValidatorNumber.class.php', + 'sfvalidatoror' => 'validator/sfValidatorOr.class.php', + 'sfvalidatorpass' => 'validator/sfValidatorPass.class.php', + 'sfvalidatorregex' => 'validator/sfValidatorRegex.class.php', + 'sfvalidatorschema' => 'validator/sfValidatorSchema.class.php', + 'sfvalidatorschemacompare' => 'validator/sfValidatorSchemaCompare.class.php', + 'sfvalidatorschemafilter' => 'validator/sfValidatorSchemaFilter.class.php', + 'sfvalidatorstring' => 'validator/sfValidatorString.class.php', + 'sfvalidatortime' => 'validator/sfValidatorTime.class.php', + 'sfvalidatorurl' => 'validator/sfValidatorUrl.class.php', + 'sfphpview' => 'view/sfPHPView.class.php', + 'sfpartialview' => 'view/sfPartialView.class.php', + 'sfview' => 'view/sfView.class.php', + 'sfviewcachemanager' => 'view/sfViewCacheManager.class.php', + 'sfviewparameterholder' => 'view/sfViewParameterHolder.class.php', + 'sfwidgetformi18nchoicecountry' => 'widget/i18n/sfWidgetFormI18nChoiceCountry.class.php', + 'sfwidgetformi18nchoicecurrency' => 'widget/i18n/sfWidgetFormI18nChoiceCurrency.class.php', + 'sfwidgetformi18nchoicelanguage' => 'widget/i18n/sfWidgetFormI18nChoiceLanguage.class.php', + 'sfwidgetformi18nchoicetimezone' => 'widget/i18n/sfWidgetFormI18nChoiceTimezone.class.php', + 'sfwidgetformi18ndate' => 'widget/i18n/sfWidgetFormI18nDate.class.php', + 'sfwidgetformi18ndatetime' => 'widget/i18n/sfWidgetFormI18nDateTime.class.php', + 'sfwidgetformi18ntime' => 'widget/i18n/sfWidgetFormI18nTime.class.php', + 'sfwidget' => 'widget/sfWidget.class.php', + 'sfwidgetform' => 'widget/sfWidgetForm.class.php', + 'sfwidgetformchoice' => 'widget/sfWidgetFormChoice.class.php', + 'sfwidgetformchoicebase' => 'widget/sfWidgetFormChoiceBase.class.php', + 'sfwidgetformdate' => 'widget/sfWidgetFormDate.class.php', + 'sfwidgetformdaterange' => 'widget/sfWidgetFormDateRange.class.php', + 'sfwidgetformdatetime' => 'widget/sfWidgetFormDateTime.class.php', + 'sfwidgetformfilterdate' => 'widget/sfWidgetFormFilterDate.class.php', + 'sfwidgetformfilterinput' => 'widget/sfWidgetFormFilterInput.class.php', + 'sfwidgetforminput' => 'widget/sfWidgetFormInput.class.php', + 'sfwidgetforminputcheckbox' => 'widget/sfWidgetFormInputCheckbox.class.php', + 'sfwidgetforminputfile' => 'widget/sfWidgetFormInputFile.class.php', + 'sfwidgetforminputfilemulti' => 'widget/sfWidgetFormInputFileMulti.class.php', + 'sfwidgetforminputfileeditable' => 'widget/sfWidgetFormInputFileEditable.class.php', + 'sfwidgetforminputhidden' => 'widget/sfWidgetFormInputHidden.class.php', + 'sfwidgetforminputpassword' => 'widget/sfWidgetFormInputPassword.class.php', + 'sfwidgetforminputread' => 'widget/sfWidgetFormInputRead.class.php', + 'sfwidgetforminputtext' => 'widget/sfWidgetFormInputText.class.php', + 'sfwidgetformschema' => 'widget/sfWidgetFormSchema.class.php', + 'sfwidgetformschemadecorator' => 'widget/sfWidgetFormSchemaDecorator.class.php', + 'sfwidgetformschemaformatter' => 'widget/sfWidgetFormSchemaFormatter.class.php', + 'sfwidgetformschemaformatterlist' => 'widget/sfWidgetFormSchemaFormatterList.class.php', + 'sfwidgetformschemaformattertable' => 'widget/sfWidgetFormSchemaFormatterTable.class.php', + 'sfwidgetformselect' => 'widget/sfWidgetFormSelect.class.php', + 'sfwidgetformselectcheckbox' => 'widget/sfWidgetFormSelectCheckbox.class.php', + 'sfwidgetformselectmany' => 'widget/sfWidgetFormSelectMany.class.php', + 'sfwidgetformselectradio' => 'widget/sfWidgetFormSelectRadio.class.php', + 'sfwidgetformtextarea' => 'widget/sfWidgetFormTextarea.class.php', + 'sfwidgetformtime' => 'widget/sfWidgetFormTime.class.php', + 'sfyaml' => 'yaml/sfYaml.class.php', + 'sfyamldumper' => 'yaml/sfYamlDumper.class.php', + 'sfyamlinline' => 'yaml/sfYamlInline.class.php', + 'sfyamlparser' => 'yaml/sfYamlParser.class.php', + ]; - /** - * Retrieves the singleton instance of this class. - * - * @return sfCoreAutoload A sfCoreAutoload implementation instance. - */ - static public function getInstance() - { - if (!isset(self::$instance)) + protected function __construct() { - self::$instance = new sfCoreAutoload(); + $this->baseDir = realpath(__DIR__.'/..'); } - return self::$instance; - } - - /** - * Register sfCoreAutoload in spl autoloader. - * - * @return void - * - * @throws sfException If unable to register SPL autoload function - */ - static public function register() - { - if (self::$registered) + /** + * Retrieves the singleton instance of this class. + * + * @return sfCoreAutoload a sfCoreAutoload implementation instance + */ + public static function getInstance() { - return; + if (!isset(self::$instance)) { + self::$instance = new sfCoreAutoload(); + } + + return self::$instance; } - ini_set('unserialize_callback_func', 'spl_autoload_call'); - if (false === spl_autoload_register(array(self::getInstance(), 'autoload'))) + /** + * Register sfCoreAutoload in spl autoloader. + * + * @throws sfException If unable to register SPL autoload function + */ + public static function register() { - throw new sfException(sprintf('Unable to register %s::autoload as an autoloading method.', get_class(self::getInstance()))); - } + if (self::$registered) { + return; + } - self::$registered = true; - } + ini_set('unserialize_callback_func', 'spl_autoload_call'); + if (false === spl_autoload_register([self::getInstance(), 'autoload'])) { + throw new sfException(sprintf('Unable to register %s::autoload as an autoloading method.', get_class(self::getInstance()))); + } - /** - * Unregister sfCoreAutoload from spl autoloader. - * - * @return void - */ - static public function unregister() - { - spl_autoload_unregister(array(self::getInstance(), 'autoload')); - self::$registered = false; - } + self::$registered = true; + } - /** - * Handles autoloading of classes. - * - * @param string $class A class name. - * - * @return boolean Returns true if the class has been loaded - */ - public function autoload($class) - { - if ($path = $this->getClassPath($class)) + /** + * Unregister sfCoreAutoload from spl autoloader. + */ + public static function unregister() { - require $path; - - return true; + spl_autoload_unregister([self::getInstance(), 'autoload']); + self::$registered = false; } - return false; - } + /** + * Handles autoloading of classes. + * + * @param string $class a class name + * + * @return bool Returns true if the class has been loaded + */ + public function autoload($class) + { + if ($path = $this->getClassPath($class)) { + require $path; - /** - * Returns the filename of the supplied class. - * - * @param string $class The class name (case insensitive) - * - * @return string|null An absolute path or null - */ - public function getClassPath($class) - { - $class = strtolower($class); + return true; + } - if (!isset($this->classes[$class])) - { - return null; + return false; } - return $this->baseDir.'/'.$this->classes[$class]; - } - - /** - * Returns the base directory this autoloader is working on. - * - * @return string The path to the symfony core lib directory - */ - public function getBaseDir() - { - return $this->baseDir; - } + /** + * Returns the filename of the supplied class. + * + * @param string $class The class name (case insensitive) + * + * @return string|null An absolute path or null + */ + public function getClassPath($class) + { + $class = strtolower($class); - /** - * Rebuilds the association array between class names and paths. - * - * This method overrides this file (__FILE__) - */ - static public function make() - { - $libDir = str_replace(DIRECTORY_SEPARATOR, '/', realpath(__DIR__.DIRECTORY_SEPARATOR.'..')); - require_once $libDir.'/util/sfFinder.class.php'; + if (!isset($this->classes[$class])) { + return null; + } - $files = sfFinder::type('file') - ->prune('plugins') - ->prune('vendor') - ->prune('skeleton') - ->prune('default') - ->prune('helper') - ->name('*.php') - ->in($libDir) - ; + return $this->baseDir.'/'.$this->classes[$class]; + } - sort($files, SORT_STRING); + /** + * Returns the base directory this autoloader is working on. + * + * @return string The path to the symfony core lib directory + */ + public function getBaseDir() + { + return $this->baseDir; + } - $classes = ''; - foreach ($files as $file) + /** + * Rebuilds the association array between class names and paths. + * + * This method overrides this file (__FILE__) + */ + public static function make() { - $file = str_replace(DIRECTORY_SEPARATOR, '/', $file); - $class = basename($file, false === strpos($file, '.class.php') ? '.php' : '.class.php'); + $libDir = str_replace(DIRECTORY_SEPARATOR, '/', realpath(__DIR__.DIRECTORY_SEPARATOR.'..')); - $contents = file_get_contents($file); - if (false !== stripos($contents, 'class '.$class) - || false !== stripos($contents, 'interface '.$class) - || false !== stripos($contents, 'trait '.$class)) - { - $classes .= sprintf(" '%s' => '%s',\n", strtolower($class), substr(str_replace($libDir, '', $file), 1)); - } - } + require_once $libDir.'/util/sfFinder.class.php'; + + $files = sfFinder::type('file') + ->prune('plugins') + ->prune('vendor') + ->prune('skeleton') + ->prune('default') + ->prune('helper') + ->name('*.php') + ->in($libDir) + ; + + sort($files, SORT_STRING); - $content = preg_replace('/protected \$classes = array *\(.*?\);/s', sprintf("protected \$classes = array(\n%s );", $classes), file_get_contents(__FILE__)); + $classes = ''; + foreach ($files as $file) { + $file = str_replace(DIRECTORY_SEPARATOR, '/', $file); + $class = basename($file, false === strpos($file, '.class.php') ? '.php' : '.class.php'); - file_put_contents(__FILE__, $content); - } + $contents = file_get_contents($file); + if (false !== stripos($contents, 'class '.$class) + || false !== stripos($contents, 'interface '.$class) + || false !== stripos($contents, 'trait '.$class)) { + $classes .= sprintf(" '%s' => '%s',\n", strtolower($class), substr(str_replace($libDir, '', $file), 1)); + } + } - // Don't edit this property by hand. - // To update it, use sfCoreAutoload::make() - protected $classes = array( - 'sfaction' => 'action/sfAction.class.php', - 'sfactionstack' => 'action/sfActionStack.class.php', - 'sfactionstackentry' => 'action/sfActionStackEntry.class.php', - 'sfactions' => 'action/sfActions.class.php', - 'sfcomponent' => 'action/sfComponent.class.php', - 'sfcomponents' => 'action/sfComponents.class.php', - 'sfdata' => 'addon/sfData.class.php', - 'sfpager' => 'addon/sfPager.class.php', - 'sfautoload' => 'autoload/sfAutoload.class.php', - 'sfautoloadagain' => 'autoload/sfAutoloadAgain.class.php', - 'sfcoreautoload' => 'autoload/sfCoreAutoload.class.php', - 'sfsimpleautoload' => 'autoload/sfSimpleAutoload.class.php', - 'sfapccache' => 'cache/sfAPCCache.class.php', - 'sfcache' => 'cache/sfCache.class.php', - 'sfeacceleratorcache' => 'cache/sfEAcceleratorCache.class.php', - 'sffilecache' => 'cache/sfFileCache.class.php', - 'sffunctioncache' => 'cache/sfFunctionCache.class.php', - 'sfmemcachecache' => 'cache/sfMemcacheCache.class.php', - 'sfnocache' => 'cache/sfNoCache.class.php', - 'sfsqlitecache' => 'cache/sfSQLiteCache.class.php', - 'sfxcachecache' => 'cache/sfXCacheCache.class.php', - 'sfansicolorformatter' => 'command/sfAnsiColorFormatter.class.php', - 'sfcommandapplication' => 'command/sfCommandApplication.class.php', - 'sfcommandargument' => 'command/sfCommandArgument.class.php', - 'sfcommandargumentset' => 'command/sfCommandArgumentSet.class.php', - 'sfcommandargumentsexception' => 'command/sfCommandArgumentsException.class.php', - 'sfcommandexception' => 'command/sfCommandException.class.php', - 'sfcommandlogger' => 'command/sfCommandLogger.class.php', - 'sfcommandmanager' => 'command/sfCommandManager.class.php', - 'sfcommandoption' => 'command/sfCommandOption.class.php', - 'sfcommandoptionset' => 'command/sfCommandOptionSet.class.php', - 'sfformatter' => 'command/sfFormatter.class.php', - 'sfsymfonycommandapplication' => 'command/sfSymfonyCommandApplication.class.php', - 'sfapplicationconfiguration' => 'config/sfApplicationConfiguration.class.php', - 'sfautoloadconfighandler' => 'config/sfAutoloadConfigHandler.class.php', - 'sfcacheconfighandler' => 'config/sfCacheConfigHandler.class.php', - 'sfcompileconfighandler' => 'config/sfCompileConfigHandler.class.php', - 'sfconfig' => 'config/sfConfig.class.php', - 'sfconfigcache' => 'config/sfConfigCache.class.php', - 'sfconfighandler' => 'config/sfConfigHandler.class.php', - 'sfdatabaseconfighandler' => 'config/sfDatabaseConfigHandler.class.php', - 'sfdefineenvironmentconfighandler' => 'config/sfDefineEnvironmentConfigHandler.class.php', - 'sffactoryconfighandler' => 'config/sfFactoryConfigHandler.class.php', - 'sffilterconfighandler' => 'config/sfFilterConfigHandler.class.php', - 'sfgeneratorconfighandler' => 'config/sfGeneratorConfigHandler.class.php', - 'sfpluginconfiguration' => 'config/sfPluginConfiguration.class.php', - 'sfpluginconfigurationgeneric' => 'config/sfPluginConfigurationGeneric.class.php', - 'sfprojectconfiguration' => 'config/sfProjectConfiguration.class.php', - 'sfrootconfighandler' => 'config/sfRootConfigHandler.class.php', - 'sfroutingconfighandler' => 'config/sfRoutingConfigHandler.class.php', - 'sfsecurityconfighandler' => 'config/sfSecurityConfigHandler.class.php', - 'sfserviceconfighandler' => 'config/sfServiceConfigHandler.class.php', - 'sfsimpleyamlconfighandler' => 'config/sfSimpleYamlConfigHandler.class.php', - 'sfviewconfighandler' => 'config/sfViewConfigHandler.class.php', - 'sfyamlconfighandler' => 'config/sfYamlConfigHandler.class.php', - 'sfcontroller' => 'controller/sfController.class.php', - 'sffrontwebcontroller' => 'controller/sfFrontWebController.class.php', - 'sfwebcontroller' => 'controller/sfWebController.class.php', - 'sfdatabase' => 'database/sfDatabase.class.php', - 'sfdatabasemanager' => 'database/sfDatabaseManager.class.php', - 'sfmysqlidatabase' => 'database/sfMySQLiDatabase.class.php', - 'sfpdodatabase' => 'database/sfPDODatabase.class.php', - 'sfpostgresqldatabase' => 'database/sfPostgreSQLDatabase.class.php', - 'sfdebug' => 'debug/sfDebug.class.php', - 'sftimer' => 'debug/sfTimer.class.php', - 'sftimermanager' => 'debug/sfTimerManager.class.php', - 'sfwebdebug' => 'debug/sfWebDebug.class.php', - 'sfwebdebugpanel' => 'debug/sfWebDebugPanel.class.php', - 'sfwebdebugpanelcache' => 'debug/sfWebDebugPanelCache.class.php', - 'sfwebdebugpanelconfig' => 'debug/sfWebDebugPanelConfig.class.php', - 'sfwebdebugpanellogs' => 'debug/sfWebDebugPanelLogs.class.php', - 'sfwebdebugpanelmailer' => 'debug/sfWebDebugPanelMailer.class.php', - 'sfwebdebugpanelmemory' => 'debug/sfWebDebugPanelMemory.class.php', - 'sfwebdebugpanelsymfonyversion' => 'debug/sfWebDebugPanelSymfonyVersion.class.php', - 'sfwebdebugpaneltimer' => 'debug/sfWebDebugPanelTimer.class.php', - 'sfwebdebugpanelview' => 'debug/sfWebDebugPanelView.class.php', - 'sfoutputescaper' => 'escaper/sfOutputEscaper.class.php', - 'sfoutputescaperarraydecorator' => 'escaper/sfOutputEscaperArrayDecorator.class.php', - 'sfoutputescapergetterdecorator' => 'escaper/sfOutputEscaperGetterDecorator.class.php', - 'sfoutputescaperiteratordecorator' => 'escaper/sfOutputEscaperIteratorDecorator.class.php', - 'sfoutputescaperobjectdecorator' => 'escaper/sfOutputEscaperObjectDecorator.class.php', - 'sfoutputescapersafe' => 'escaper/sfOutputEscaperSafe.class.php', - 'sfevent' => 'event/sfEvent.class.php', - 'sfeventdispatcher' => 'event/sfEventDispatcher.class.php', - 'sfcacheexception' => 'exception/sfCacheException.class.php', - 'sfconfigurationexception' => 'exception/sfConfigurationException.class.php', - 'sfcontrollerexception' => 'exception/sfControllerException.class.php', - 'sfdatabaseexception' => 'exception/sfDatabaseException.class.php', - 'sferror404exception' => 'exception/sfError404Exception.class.php', - 'sfexception' => 'exception/sfException.class.php', - 'sffactoryexception' => 'exception/sfFactoryException.class.php', - 'sffileexception' => 'exception/sfFileException.class.php', - 'sffilterexception' => 'exception/sfFilterException.class.php', - 'sfforwardexception' => 'exception/sfForwardException.class.php', - 'sfinitializationexception' => 'exception/sfInitializationException.class.php', - 'sfparseexception' => 'exception/sfParseException.class.php', - 'sfrenderexception' => 'exception/sfRenderException.class.php', - 'sfsecurityexception' => 'exception/sfSecurityException.class.php', - 'sfstopexception' => 'exception/sfStopException.class.php', - 'sfstorageexception' => 'exception/sfStorageException.class.php', - 'sfviewexception' => 'exception/sfViewException.class.php', - 'sfbasicsecurityfilter' => 'filter/sfBasicSecurityFilter.class.php', - 'sfcachefilter' => 'filter/sfCacheFilter.class.php', - 'sfcommonfilter' => 'filter/sfCommonFilter.class.php', - 'sfexecutionfilter' => 'filter/sfExecutionFilter.class.php', - 'sffilter' => 'filter/sfFilter.class.php', - 'sffilterchain' => 'filter/sfFilterChain.class.php', - 'sfrenderingfilter' => 'filter/sfRenderingFilter.class.php', - 'sfformfilter' => 'form/addon/sfFormFilter.class.php', - 'sfformobject' => 'form/addon/sfFormObject.class.php', - 'sfformsymfony' => 'form/addon/sfFormSymfony.class.php', - 'sfform' => 'form/sfForm.class.php', - 'sfformfield' => 'form/sfFormField.class.php', - 'sfformfieldschema' => 'form/sfFormFieldSchema.class.php', - 'sfgenerator' => 'generator/sfGenerator.class.php', - 'sfgeneratormanager' => 'generator/sfGeneratorManager.class.php', - 'sfmodelgenerator' => 'generator/sfModelGenerator.class.php', - 'sfmodelgeneratorconfiguration' => 'generator/sfModelGeneratorConfiguration.class.php', - 'sfmodelgeneratorconfigurationfield' => 'generator/sfModelGeneratorConfigurationField.class.php', - 'sfmodelgeneratorhelper' => 'generator/sfModelGeneratorHelper.class.php', - 'tgettext' => 'i18n/Gettext/TGettext.class.php', - 'sfi18napplicationextract' => 'i18n/extract/sfI18nApplicationExtract.class.php', - 'sfi18nextract' => 'i18n/extract/sfI18nExtract.class.php', - 'sfi18nextractorinterface' => 'i18n/extract/sfI18nExtractorInterface.class.php', - 'sfi18nmoduleextract' => 'i18n/extract/sfI18nModuleExtract.class.php', - 'sfi18nphpextractor' => 'i18n/extract/sfI18nPhpExtractor.class.php', - 'sfi18nyamlextractor' => 'i18n/extract/sfI18nYamlExtractor.class.php', - 'sfi18nyamlgeneratorextractor' => 'i18n/extract/sfI18nYamlGeneratorExtractor.class.php', - 'sfi18nyamlvalidateextractor' => 'i18n/extract/sfI18nYamlValidateExtractor.class.php', - 'sfchoiceformat' => 'i18n/sfChoiceFormat.class.php', - 'sfcultureinfo' => 'i18n/sfCultureInfo.class.php', - 'sfdateformat' => 'i18n/sfDateFormat.class.php', - 'sfdatetimeformatinfo' => 'i18n/sfDateTimeFormatInfo.class.php', - 'sfi18n' => 'i18n/sfI18N.class.php', - 'sfimessagesource' => 'i18n/sfIMessageSource.class.php', - 'sfmessageformat' => 'i18n/sfMessageFormat.class.php', - 'sfmessagesource' => 'i18n/sfMessageSource.class.php', - 'sfmessagesource_aggregate' => 'i18n/sfMessageSource_Aggregate.class.php', - 'sfmessagesource_database' => 'i18n/sfMessageSource_Database.class.php', - 'sfmessagesource_file' => 'i18n/sfMessageSource_File.class.php', - 'sfmessagesource_mysqli' => 'i18n/sfMessageSource_MySQLi.class.php', - 'sfmessagesource_sqlite' => 'i18n/sfMessageSource_SQLite.class.php', - 'sfmessagesource_sqlite3' => 'i18n/sfMessageSource_SQLite3.class.php', - 'sfmessagesource_xliff' => 'i18n/sfMessageSource_XLIFF.class.php', - 'sfmessagesource_gettext' => 'i18n/sfMessageSource_gettext.class.php', - 'sfnumberformat' => 'i18n/sfNumberFormat.class.php', - 'sfnumberformatinfo' => 'i18n/sfNumberFormatInfo.class.php', - 'sfaggregatelogger' => 'log/sfAggregateLogger.class.php', - 'sfconsolelogger' => 'log/sfConsoleLogger.class.php', - 'sfeventlogger' => 'log/sfEventLogger.class.php', - 'sffilelogger' => 'log/sfFileLogger.class.php', - 'sflogger' => 'log/sfLogger.class.php', - 'sfloggerinterface' => 'log/sfLoggerInterface.class.php', - 'sfloggerwrapper' => 'log/sfLoggerWrapper.class.php', - 'sfnologger' => 'log/sfNoLogger.class.php', - 'sfpsrloggeradapter' => 'log/sfPsrLoggerAdapter.class.php', - 'sfstreamlogger' => 'log/sfStreamLogger.class.php', - 'sfvarlogger' => 'log/sfVarLogger.class.php', - 'sfwebdebuglogger' => 'log/sfWebDebugLogger.class.php', - 'sfmailer' => 'mailer/sfMailer.class.php', - 'sfmailermessageloggerplugin' => 'mailer/sfMailerMessageLoggerPlugin.class.php', - 'sfnomailer' => 'mailer/sfNoMailer.class.php', - 'sfpearconfig' => 'plugin/sfPearConfig.class.php', - 'sfpeardownloader' => 'plugin/sfPearDownloader.class.php', - 'sfpearenvironment' => 'plugin/sfPearEnvironment.class.php', - 'sfpearfrontendplugin' => 'plugin/sfPearFrontendPlugin.class.php', - 'sfpearrest' => 'plugin/sfPearRest.class.php', - 'sfpearrest10' => 'plugin/sfPearRest10.class.php', - 'sfpearrest11' => 'plugin/sfPearRest11.class.php', - 'sfpearrestplugin' => 'plugin/sfPearRestPlugin.class.php', - 'sfplugindependencyexception' => 'plugin/sfPluginDependencyException.class.php', - 'sfpluginexception' => 'plugin/sfPluginException.class.php', - 'sfpluginmanager' => 'plugin/sfPluginManager.class.php', - 'sfpluginrecursivedependencyexception' => 'plugin/sfPluginRecursiveDependencyException.class.php', - 'sfpluginrestexception' => 'plugin/sfPluginRestException.class.php', - 'sfsymfonypluginmanager' => 'plugin/sfSymfonyPluginManager.class.php', - 'sfrequest' => 'request/sfRequest.class.php', - 'sfwebrequest' => 'request/sfWebRequest.class.php', - 'sfresponse' => 'response/sfResponse.class.php', - 'sfwebresponse' => 'response/sfWebResponse.class.php', - 'sfobjectroute' => 'routing/sfObjectRoute.class.php', - 'sfobjectroutecollection' => 'routing/sfObjectRouteCollection.class.php', - 'sfpatternrouting' => 'routing/sfPatternRouting.class.php', - 'sfrequestroute' => 'routing/sfRequestRoute.class.php', - 'sfroute' => 'routing/sfRoute.class.php', - 'sfroutecollection' => 'routing/sfRouteCollection.class.php', - 'sfrouting' => 'routing/sfRouting.class.php', - 'sfservicecontainer' => 'service/sfServiceContainer.class.php', - 'sfservicecontainerbuilder' => 'service/sfServiceContainerBuilder.class.php', - 'sfservicecontainerdumper' => 'service/sfServiceContainerDumper.class.php', - 'sfservicecontainerdumpergraphviz' => 'service/sfServiceContainerDumperGraphviz.class.php', - 'sfservicecontainerdumperinterface' => 'service/sfServiceContainerDumperInterface.class.php', - 'sfservicecontainerdumperphp' => 'service/sfServiceContainerDumperPhp.class.php', - 'sfservicecontainerinterface' => 'service/sfServiceContainerInterface.class.php', - 'sfservicecontainerloader' => 'service/sfServiceContainerLoader.class.php', - 'sfservicecontainerloaderarray' => 'service/sfServiceContainerLoaderArray.class.php', - 'sfservicecontainerloaderinterface' => 'service/sfServiceContainerLoaderInterface.class.php', - 'sfservicedefinition' => 'service/sfServiceDefinition.class.php', - 'sfserviceparameter' => 'service/sfServiceParameter.class.php', - 'sfservicereference' => 'service/sfServiceReference.class.php', - 'sfcachesessionstorage' => 'storage/sfCacheSessionStorage.class.php', - 'sfdatabasesessionstorage' => 'storage/sfDatabaseSessionStorage.class.php', - 'sfmysqlisessionstorage' => 'storage/sfMySQLiSessionStorage.class.php', - 'sfnostorage' => 'storage/sfNoStorage.class.php', - 'sfpdosessionstorage' => 'storage/sfPDOSessionStorage.class.php', - 'sfpostgresqlsessionstorage' => 'storage/sfPostgreSQLSessionStorage.class.php', - 'sfsessionstorage' => 'storage/sfSessionStorage.class.php', - 'sfsessionteststorage' => 'storage/sfSessionTestStorage.class.php', - 'sfstorage' => 'storage/sfStorage.class.php', - 'sfapproutestask' => 'task/app/sfAppRoutesTask.class.php', - 'sfcachecleartask' => 'task/cache/sfCacheClearTask.class.php', - 'sfconfigureauthortask' => 'task/configure/sfConfigureAuthorTask.class.php', - 'sfgenerateapptask' => 'task/generator/sfGenerateAppTask.class.php', - 'sfgeneratemoduletask' => 'task/generator/sfGenerateModuleTask.class.php', - 'sfgenerateprojecttask' => 'task/generator/sfGenerateProjectTask.class.php', - 'sfgeneratetasktask' => 'task/generator/sfGenerateTaskTask.class.php', - 'sfgeneratorbasetask' => 'task/generator/sfGeneratorBaseTask.class.php', - 'sfhelptask' => 'task/help/sfHelpTask.class.php', - 'sflisttask' => 'task/help/sfListTask.class.php', - 'sfi18nextracttask' => 'task/i18n/sfI18nExtractTask.class.php', - 'sfi18nfindtask' => 'task/i18n/sfI18nFindTask.class.php', - 'sflogcleartask' => 'task/log/sfLogClearTask.class.php', - 'sflogrotatetask' => 'task/log/sfLogRotateTask.class.php', - 'sfpluginaddchanneltask' => 'task/plugin/sfPluginAddChannelTask.class.php', - 'sfpluginbasetask' => 'task/plugin/sfPluginBaseTask.class.php', - 'sfplugininstalltask' => 'task/plugin/sfPluginInstallTask.class.php', - 'sfpluginlisttask' => 'task/plugin/sfPluginListTask.class.php', - 'sfpluginpublishassetstask' => 'task/plugin/sfPluginPublishAssetsTask.class.php', - 'sfpluginuninstalltask' => 'task/plugin/sfPluginUninstallTask.class.php', - 'sfpluginupgradetask' => 'task/plugin/sfPluginUpgradeTask.class.php', - 'sfprojectclearcontrollerstask' => 'task/project/sfProjectClearControllersTask.class.php', - 'sfprojectdeploytask' => 'task/project/sfProjectDeployTask.class.php', - 'sfprojectdisabletask' => 'task/project/sfProjectDisableTask.class.php', - 'sfprojectenabletask' => 'task/project/sfProjectEnableTask.class.php', - 'sfprojectoptimizetask' => 'task/project/sfProjectOptimizeTask.class.php', - 'sfprojectpermissionstask' => 'task/project/sfProjectPermissionsTask.class.php', - 'sfprojectsendemailstask' => 'task/project/sfProjectSendEmailsTask.class.php', - 'sfdeprecatedclassesvalidation' => 'task/project/validation/sfDeprecatedClassesValidation.class.php', - 'sfdeprecatedconfigurationfilesvalidation' => 'task/project/validation/sfDeprecatedConfigurationFilesValidation.class.php', - 'sfdeprecatedhelpersvalidation' => 'task/project/validation/sfDeprecatedHelpersValidation.class.php', - 'sfdeprecatedmethodsvalidation' => 'task/project/validation/sfDeprecatedMethodsValidation.class.php', - 'sfdeprecatedpluginsvalidation' => 'task/project/validation/sfDeprecatedPluginsValidation.class.php', - 'sfdeprecatedsettingsvalidation' => 'task/project/validation/sfDeprecatedSettingsValidation.class.php', - 'sfparameterholdervalidation' => 'task/project/validation/sfParameterHolderValidation.class.php', - 'sfvalidation' => 'task/project/validation/sfValidation.class.php', - 'sfbasetask' => 'task/sfBaseTask.class.php', - 'sfcommandapplicationtask' => 'task/sfCommandApplicationTask.class.php', - 'sffilesystem' => 'task/sfFilesystem.class.php', - 'sftask' => 'task/sfTask.class.php', - 'lime_symfony' => 'task/symfony/lime_symfony.php', - 'sfsymfonytesttask' => 'task/symfony/sfSymfonyTestTask.class.php', - 'sflimeharness' => 'task/test/sfLimeHarness.class.php', - 'sftestalltask' => 'task/test/sfTestAllTask.class.php', - 'sftestbasetask' => 'task/test/sfTestBaseTask.class.php', - 'sftestcoveragetask' => 'task/test/sfTestCoverageTask.class.php', - 'sftestfunctionaltask' => 'task/test/sfTestFunctionalTask.class.php', - 'sftestplugintask' => 'task/test/sfTestPluginTask.class.php', - 'sftestunittask' => 'task/test/sfTestUnitTask.class.php', - 'sftestbrowser' => 'test/sfTestBrowser.class.php', - 'sftestfunctional' => 'test/sfTestFunctional.class.php', - 'sftestfunctionalbase' => 'test/sfTestFunctionalBase.class.php', - 'sftester' => 'test/sfTester.class.php', - 'sftesterform' => 'test/sfTesterForm.class.php', - 'sftestermailer' => 'test/sfTesterMailer.class.php', - 'sftesterrequest' => 'test/sfTesterRequest.class.php', - 'sftesterresponse' => 'test/sfTesterResponse.class.php', - 'sftesteruser' => 'test/sfTesterUser.class.php', - 'sftesterviewcache' => 'test/sfTesterViewCache.class.php', - 'sfbasicsecurityuser' => 'user/sfBasicSecurityUser.class.php', - 'sfsecurityuser' => 'user/sfSecurityUser.class.php', - 'sfuser' => 'user/sfUser.class.php', - 'sfbrowser' => 'util/sfBrowser.class.php', - 'sfbrowserbase' => 'util/sfBrowserBase.class.php', - 'sfcallable' => 'util/sfCallable.class.php', - 'sfclassmanipulator' => 'util/sfClassManipulator.class.php', - 'sfcontext' => 'util/sfContext.class.php', - 'sfdomcssselector' => 'util/sfDomCssSelector.class.php', - 'sffinder' => 'util/sfFinder.class.php', - 'sfinflector' => 'util/sfInflector.class.php', - 'sfnamespacedparameterholder' => 'util/sfNamespacedParameterHolder.class.php', - 'sfparameterholder' => 'util/sfParameterHolder.class.php', - 'sftoolkit' => 'util/sfToolkit.class.php', - 'sfvalidatori18nchoicecountry' => 'validator/i18n/sfValidatorI18nChoiceCountry.class.php', - 'sfvalidatori18nchoicelanguage' => 'validator/i18n/sfValidatorI18nChoiceLanguage.class.php', - 'sfvalidatori18nchoicetimezone' => 'validator/i18n/sfValidatorI18nChoiceTimezone.class.php', - 'sfvalidatedfile' => 'validator/sfValidatedFile.class.php', - 'sfvalidatorand' => 'validator/sfValidatorAnd.class.php', - 'sfvalidatorbase' => 'validator/sfValidatorBase.class.php', - 'sfvalidatorboolean' => 'validator/sfValidatorBoolean.class.php', - 'sfvalidatorcsrftoken' => 'validator/sfValidatorCSRFToken.class.php', - 'sfvalidatorcallback' => 'validator/sfValidatorCallback.class.php', - 'sfvalidatorchoice' => 'validator/sfValidatorChoice.class.php', - 'sfvalidatordate' => 'validator/sfValidatorDate.class.php', - 'sfvalidatordaterange' => 'validator/sfValidatorDateRange.class.php', - 'sfvalidatordatetime' => 'validator/sfValidatorDateTime.class.php', - 'sfvalidatordecorator' => 'validator/sfValidatorDecorator.class.php', - 'sfvalidatoremail' => 'validator/sfValidatorEmail.class.php', - 'sfvalidatorequal' => 'validator/sfValidatorEqual.class.php', - 'sfvalidatorerror' => 'validator/sfValidatorError.class.php', - 'sfvalidatorerrorschema' => 'validator/sfValidatorErrorSchema.class.php', - 'sfvalidatorfile' => 'validator/sfValidatorFile.class.php', - 'sfvalidatorfilemulti' => 'validator/sfValidatorFileMulti.class.php', - 'sfvalidatorfromdescription' => 'validator/sfValidatorFromDescription.class.php', - 'sfvalidatorinteger' => 'validator/sfValidatorInteger.class.php', - 'sfvalidatorip' => 'validator/sfValidatorIp.class.php', - 'sfvalidatornumber' => 'validator/sfValidatorNumber.class.php', - 'sfvalidatoror' => 'validator/sfValidatorOr.class.php', - 'sfvalidatorpass' => 'validator/sfValidatorPass.class.php', - 'sfvalidatorregex' => 'validator/sfValidatorRegex.class.php', - 'sfvalidatorschema' => 'validator/sfValidatorSchema.class.php', - 'sfvalidatorschemacompare' => 'validator/sfValidatorSchemaCompare.class.php', - 'sfvalidatorschemafilter' => 'validator/sfValidatorSchemaFilter.class.php', - 'sfvalidatorstring' => 'validator/sfValidatorString.class.php', - 'sfvalidatortime' => 'validator/sfValidatorTime.class.php', - 'sfvalidatorurl' => 'validator/sfValidatorUrl.class.php', - 'sfphpview' => 'view/sfPHPView.class.php', - 'sfpartialview' => 'view/sfPartialView.class.php', - 'sfview' => 'view/sfView.class.php', - 'sfviewcachemanager' => 'view/sfViewCacheManager.class.php', - 'sfviewparameterholder' => 'view/sfViewParameterHolder.class.php', - 'sfwidgetformi18nchoicecountry' => 'widget/i18n/sfWidgetFormI18nChoiceCountry.class.php', - 'sfwidgetformi18nchoicecurrency' => 'widget/i18n/sfWidgetFormI18nChoiceCurrency.class.php', - 'sfwidgetformi18nchoicelanguage' => 'widget/i18n/sfWidgetFormI18nChoiceLanguage.class.php', - 'sfwidgetformi18nchoicetimezone' => 'widget/i18n/sfWidgetFormI18nChoiceTimezone.class.php', - 'sfwidgetformi18ndate' => 'widget/i18n/sfWidgetFormI18nDate.class.php', - 'sfwidgetformi18ndatetime' => 'widget/i18n/sfWidgetFormI18nDateTime.class.php', - 'sfwidgetformi18ntime' => 'widget/i18n/sfWidgetFormI18nTime.class.php', - 'sfwidget' => 'widget/sfWidget.class.php', - 'sfwidgetform' => 'widget/sfWidgetForm.class.php', - 'sfwidgetformchoice' => 'widget/sfWidgetFormChoice.class.php', - 'sfwidgetformchoicebase' => 'widget/sfWidgetFormChoiceBase.class.php', - 'sfwidgetformdate' => 'widget/sfWidgetFormDate.class.php', - 'sfwidgetformdaterange' => 'widget/sfWidgetFormDateRange.class.php', - 'sfwidgetformdatetime' => 'widget/sfWidgetFormDateTime.class.php', - 'sfwidgetformfilterdate' => 'widget/sfWidgetFormFilterDate.class.php', - 'sfwidgetformfilterinput' => 'widget/sfWidgetFormFilterInput.class.php', - 'sfwidgetforminput' => 'widget/sfWidgetFormInput.class.php', - 'sfwidgetforminputcheckbox' => 'widget/sfWidgetFormInputCheckbox.class.php', - 'sfwidgetforminputfile' => 'widget/sfWidgetFormInputFile.class.php', - 'sfwidgetforminputfilemulti' => 'widget/sfWidgetFormInputFileMulti.class.php', - 'sfwidgetforminputfileeditable' => 'widget/sfWidgetFormInputFileEditable.class.php', - 'sfwidgetforminputhidden' => 'widget/sfWidgetFormInputHidden.class.php', - 'sfwidgetforminputpassword' => 'widget/sfWidgetFormInputPassword.class.php', - 'sfwidgetforminputread' => 'widget/sfWidgetFormInputRead.class.php', - 'sfwidgetforminputtext' => 'widget/sfWidgetFormInputText.class.php', - 'sfwidgetformschema' => 'widget/sfWidgetFormSchema.class.php', - 'sfwidgetformschemadecorator' => 'widget/sfWidgetFormSchemaDecorator.class.php', - 'sfwidgetformschemaformatter' => 'widget/sfWidgetFormSchemaFormatter.class.php', - 'sfwidgetformschemaformatterlist' => 'widget/sfWidgetFormSchemaFormatterList.class.php', - 'sfwidgetformschemaformattertable' => 'widget/sfWidgetFormSchemaFormatterTable.class.php', - 'sfwidgetformselect' => 'widget/sfWidgetFormSelect.class.php', - 'sfwidgetformselectcheckbox' => 'widget/sfWidgetFormSelectCheckbox.class.php', - 'sfwidgetformselectmany' => 'widget/sfWidgetFormSelectMany.class.php', - 'sfwidgetformselectradio' => 'widget/sfWidgetFormSelectRadio.class.php', - 'sfwidgetformtextarea' => 'widget/sfWidgetFormTextarea.class.php', - 'sfwidgetformtime' => 'widget/sfWidgetFormTime.class.php', - 'sfyaml' => 'yaml/sfYaml.class.php', - 'sfyamldumper' => 'yaml/sfYamlDumper.class.php', - 'sfyamlinline' => 'yaml/sfYamlInline.class.php', - 'sfyamlparser' => 'yaml/sfYamlParser.class.php', - ); + $content = preg_replace('/protected \$classes = array *\(.*?\);/s', sprintf("protected \$classes = array(\n%s );", $classes), file_get_contents(__FILE__)); + + file_put_contents(__FILE__, $content); + } } diff --git a/lib/autoload/sfSimpleAutoload.class.php b/lib/autoload/sfSimpleAutoload.class.php index 66ff5c1b4..85674e7a0 100755 --- a/lib/autoload/sfSimpleAutoload.class.php +++ b/lib/autoload/sfSimpleAutoload.class.php @@ -14,329 +14,286 @@ * This class is a singleton as PHP seems to be unable to register 2 autoloaders that are instances * of the same class (why?). * - * @package symfony - * @subpackage autoload * @author Fabien Potencier - * @version SVN: $Id$ */ class sfSimpleAutoload { - static protected - $registered = false, - $instance = null; - - protected - $cacheFile = null, - $cacheLoaded = false, - $cacheChanged = false, - $dirs = array(), - $files = array(), - $classes = array(), - $overriden = array(); - - protected function __construct($cacheFile = null) - { - if (null !== $cacheFile) + protected static $registered = false; + protected static $instance; + + protected $cacheFile; + protected $cacheLoaded = false; + protected $cacheChanged = false; + protected $dirs = []; + protected $files = []; + protected $classes = []; + protected $overriden = []; + + protected function __construct($cacheFile = null) { - $this->cacheFile = $cacheFile; - } + if (null !== $cacheFile) { + $this->cacheFile = $cacheFile; + } - $this->loadCache(); - } - - /** - * Retrieves the singleton instance of this class. - * - * @param string $cacheFile The file path to save the cache - * - * @return sfSimpleAutoload A sfSimpleAutoload implementation instance. - */ - static public function getInstance($cacheFile = null) - { - if (!isset(self::$instance)) - { - self::$instance = new sfSimpleAutoload($cacheFile); + $this->loadCache(); } - return self::$instance; - } - - /** - * Register sfSimpleAutoload in spl autoloader. - * - * @return void - * - * @throws sfException - */ - static public function register() - { - if (self::$registered) + /** + * Retrieves the singleton instance of this class. + * + * @param string $cacheFile The file path to save the cache + * + * @return sfSimpleAutoload a sfSimpleAutoload implementation instance + */ + public static function getInstance($cacheFile = null) { - return; - } + if (!isset(self::$instance)) { + self::$instance = new sfSimpleAutoload($cacheFile); + } - ini_set('unserialize_callback_func', 'spl_autoload_call'); - if (false === spl_autoload_register(array(self::getInstance(), 'autoload'))) - { - throw new sfException(sprintf('Unable to register %s::autoload as an autoloading method.', get_class(self::getInstance()))); + return self::$instance; } - if (self::getInstance()->cacheFile) + /** + * Register sfSimpleAutoload in spl autoloader. + * + * @throws sfException + */ + public static function register() { - register_shutdown_function(array(self::getInstance(), 'saveCache')); - } + if (self::$registered) { + return; + } - self::$registered = true; - } - - /** - * Unregister sfSimpleAutoload from spl autoloader. - * - * @return void - */ - static public function unregister() - { - spl_autoload_unregister(array(self::getInstance(), 'autoload')); - self::$registered = false; - } - - /** - * Handles autoloading of classes. - * - * @param string $class A class name. - * - * @return boolean Returns true if the class has been loaded - */ - public function autoload($class) - { - $class = strtolower($class); - - // class already exists - if (class_exists($class, false) || interface_exists($class, false)) - { - return true; - } + ini_set('unserialize_callback_func', 'spl_autoload_call'); + if (false === spl_autoload_register([self::getInstance(), 'autoload'])) { + throw new sfException(sprintf('Unable to register %s::autoload as an autoloading method.', get_class(self::getInstance()))); + } - // we have a class path, let's include it - if (isset($this->classes[$class])) - { - try - { - require $this->classes[$class]; - } - catch (sfException $e) - { - $e->printStackTrace(); - } - catch (Exception $e) - { - sfException::createFromException($e)->printStackTrace(); - } - - return true; - } + if (self::getInstance()->cacheFile) { + register_shutdown_function([self::getInstance(), 'saveCache']); + } - return false; - } + self::$registered = true; + } - /** - * Loads the cache. - */ - public function loadCache() - { - if (!$this->cacheFile || !is_readable($this->cacheFile)) + /** + * Unregister sfSimpleAutoload from spl autoloader. + */ + public static function unregister() { - return; + spl_autoload_unregister([self::getInstance(), 'autoload']); + self::$registered = false; } - list($this->classes, $this->dirs, $this->files) = unserialize(file_get_contents($this->cacheFile)); - - $this->cacheLoaded = true; - $this->cacheChanged = false; - } - - /** - * Saves the cache. - */ - public function saveCache() - { - if ($this->cacheChanged) + /** + * Handles autoloading of classes. + * + * @param string $class a class name + * + * @return bool Returns true if the class has been loaded + */ + public function autoload($class) { - if (is_writable(dirname($this->cacheFile))) - { - file_put_contents($this->cacheFile, serialize(array($this->classes, $this->dirs, $this->files))); - } + $class = strtolower($class); - $this->cacheChanged = false; - } - } + // class already exists + if (class_exists($class, false) || interface_exists($class, false)) { + return true; + } - /** - * Reloads cache. - */ - public function reload() - { - $this->classes = array(); - $this->cacheLoaded = false; + // we have a class path, let's include it + if (isset($this->classes[$class])) { + try { + require $this->classes[$class]; + } catch (sfException $e) { + $e->printStackTrace(); + } catch (Exception $e) { + sfException::createFromException($e)->printStackTrace(); + } + + return true; + } - foreach ($this->dirs as $dir) - { - $this->addDirectory($dir); + return false; } - foreach ($this->files as $file) + /** + * Loads the cache. + */ + public function loadCache() { - $this->addFile($file); + if (!$this->cacheFile || !is_readable($this->cacheFile)) { + return; + } + + list($this->classes, $this->dirs, $this->files) = unserialize(file_get_contents($this->cacheFile)); + + $this->cacheLoaded = true; + $this->cacheChanged = false; } - foreach ($this->overriden as $class => $path) + /** + * Saves the cache. + */ + public function saveCache() { - $this->classes[$class] = $path; + if ($this->cacheChanged) { + if (is_writable(dirname($this->cacheFile))) { + file_put_contents($this->cacheFile, serialize([$this->classes, $this->dirs, $this->files])); + } + + $this->cacheChanged = false; + } } - $this->cacheLoaded = true; - $this->cacheChanged = true; - } - - /** - * Removes the cache. - */ - public function removeCache() - { - @unlink($this->cacheFile); - } - - /** - * Adds a directory to the autoloading system if not yet present and give it the highest possible precedence. - * - * @param string $dir The directory to look for classes - * @param string $ext The extension to look for - */ - public function addDirectory($dir, $ext = '.php') - { - $finder = sfFinder::type('file')->follow_link()->name('*'.$ext); - - if ($dirs = glob($dir)) + /** + * Reloads cache. + */ + public function reload() { - foreach ($dirs as $dir) - { - if (false !== $key = array_search($dir, $this->dirs)) - { - unset($this->dirs[$key]); - $this->dirs[] = $dir; - - if ($this->cacheLoaded) - { - continue; - } + $this->classes = []; + $this->cacheLoaded = false; + + foreach ($this->dirs as $dir) { + $this->addDirectory($dir); } - else - { - $this->dirs[] = $dir; + + foreach ($this->files as $file) { + $this->addFile($file); + } + + foreach ($this->overriden as $class => $path) { + $this->classes[$class] = $path; } + $this->cacheLoaded = true; $this->cacheChanged = true; - $this->addFiles($finder->in($dir), false); - } } - } - - /** - * Adds files to the autoloading system. - * - * @param array $files An array of files - * @param Boolean $register Whether to register those files as single entities (used when reloading) - */ - public function addFiles(array $files, $register = true) - { - foreach ($files as $file) + + /** + * Removes the cache. + */ + public function removeCache() { - $this->addFile($file, $register); + @unlink($this->cacheFile); } - } - - /** - * Adds a file to the autoloading system. - * - * @param string $file A file path - * @param Boolean $register Whether to register those files as single entities (used when reloading) - */ - public function addFile($file, $register = true) - { - if (!is_file($file)) + + /** + * Adds a directory to the autoloading system if not yet present and give it the highest possible precedence. + * + * @param string $dir The directory to look for classes + * @param string $ext The extension to look for + */ + public function addDirectory($dir, $ext = '.php') { - return; + $finder = sfFinder::type('file')->follow_link()->name('*'.$ext); + + if ($dirs = glob($dir)) { + foreach ($dirs as $dir) { + if (false !== $key = array_search($dir, $this->dirs)) { + unset($this->dirs[$key]); + $this->dirs[] = $dir; + + if ($this->cacheLoaded) { + continue; + } + } else { + $this->dirs[] = $dir; + } + + $this->cacheChanged = true; + $this->addFiles($finder->in($dir), false); + } + } } - if (in_array($file, $this->files)) + /** + * Adds files to the autoloading system. + * + * @param array $files An array of files + * @param bool $register Whether to register those files as single entities (used when reloading) + */ + public function addFiles(array $files, $register = true) { - if ($this->cacheLoaded) - { - return; - } + foreach ($files as $file) { + $this->addFile($file, $register); + } } - else + + /** + * Adds a file to the autoloading system. + * + * @param string $file A file path + * @param bool $register Whether to register those files as single entities (used when reloading) + */ + public function addFile($file, $register = true) { - if ($register) - { - $this->files[] = $file; - } + if (!is_file($file)) { + return; + } + + if (in_array($file, $this->files)) { + if ($this->cacheLoaded) { + return; + } + } else { + if ($register) { + $this->files[] = $file; + } + } + + if ($register) { + $this->cacheChanged = true; + } + + preg_match_all('~^\s*(?:abstract\s+|final\s+)?(?:class|interface|trait)\s+(\w+)~mi', file_get_contents($file), $classes); + foreach ($classes[1] as $class) { + $this->classes[strtolower($class)] = $file; + } } - if ($register) + /** + * Sets the path for a particular class. + * + * @param string $class A PHP class name + * @param string $path An absolute path + */ + public function setClassPath($class, $path) { - $this->cacheChanged = true; + $class = strtolower($class); + + $this->overriden[$class] = $path; + + $this->classes[$class] = $path; } - preg_match_all('~^\s*(?:abstract\s+|final\s+)?(?:class|interface|trait)\s+(\w+)~mi', file_get_contents($file), $classes); - foreach ($classes[1] as $class) + /** + * Returns the path where a particular class can be found. + * + * @param string $class A PHP class name + * + * @return string|null An absolute path + */ + public function getClassPath($class) { - $this->classes[strtolower($class)] = $file; + $class = strtolower($class); + + return isset($this->classes[$class]) ? $this->classes[$class] : null; } - } - - /** - * Sets the path for a particular class. - * - * @param string $class A PHP class name - * @param string $path An absolute path - */ - public function setClassPath($class, $path) - { - $class = strtolower($class); - - $this->overriden[$class] = $path; - - $this->classes[$class] = $path; - } - - /** - * Returns the path where a particular class can be found. - * - * @param string $class A PHP class name - * - * @return string|null An absolute path - */ - public function getClassPath($class) - { - $class = strtolower($class); - - return isset($this->classes[$class]) ? $this->classes[$class] : null; - } - - /** - * Loads configuration from the supplied files. - * - * @param array $files An array of autoload.yml files - * - * @see sfAutoloadConfigHandler - */ - public function loadConfiguration(array $files) - { - $config = new sfAutoloadConfigHandler(); - foreach ($config->evaluate($files) as $class => $file) + + /** + * Loads configuration from the supplied files. + * + * @param array $files An array of autoload.yml files + * + * @see sfAutoloadConfigHandler + */ + public function loadConfiguration(array $files) { - $this->setClassPath($class, $file); + $config = new sfAutoloadConfigHandler(); + foreach ($config->evaluate($files) as $class => $file) { + $this->setClassPath($class, $file); + } } - } } diff --git a/lib/cache/sfAPCCache.class.php b/lib/cache/sfAPCCache.class.php deleted file mode 100644 index 78376490b..000000000 --- a/lib/cache/sfAPCCache.class.php +++ /dev/null @@ -1,220 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Cache class that stores cached content in APC. - * - * @package symfony - * @subpackage cache - * @author Fabien Potencier - * @version SVN: $Id$ - */ -class sfAPCCache extends sfCache -{ - protected $enabled; - - /** - * Initializes this sfCache instance. - * - * Available options: - * - * * see sfCache for options available for all drivers - * - * @see sfCache - * @inheritdoc - */ - public function initialize($options = array()) - { - parent::initialize($options); - - $this->enabled = function_exists('apc_store') && ini_get('apc.enabled'); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function get($key, $default = null) - { - if (!$this->enabled) - { - return $default; - } - - $value = $this->fetch($this->getOption('prefix').$key, $has); - - return $has ? $value : $default; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function has($key) - { - if (!$this->enabled) - { - return false; - } - - $this->fetch($this->getOption('prefix').$key, $has); - - return $has; - } - - private function fetch($key, &$success) - { - $has = null; - $value = apc_fetch($key, $has); - // the second argument was added in APC 3.0.17. If it is still null we fall back to the value returned - if (null !== $has) - { - $success = $has; - } - else - { - $success = $value !== false; - } - - return $value; - } - - - /** - * @see sfCache - * @inheritdoc - */ - public function set($key, $data, $lifetime = null) - { - if (!$this->enabled) - { - return true; - } - - return apc_store($this->getOption('prefix').$key, $data, $this->getLifetime($lifetime)); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function remove($key) - { - if (!$this->enabled) - { - return true; - } - - return apc_delete($this->getOption('prefix').$key); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function clean($mode = sfCache::ALL) - { - if (!$this->enabled) - { - return true; - } - - if (sfCache::ALL === $mode) - { - return apc_clear_cache('user'); - } - } - - /** - * @see sfCache - * @inheritdoc - */ - public function getLastModified($key) - { - if ($info = $this->getCacheInfo($key)) - { - return $info['creation_time'] + $info['ttl'] > time() ? $info['mtime'] : 0; - } - - return 0; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function getTimeout($key) - { - if ($info = $this->getCacheInfo($key)) - { - return $info['creation_time'] + $info['ttl'] > time() ? $info['creation_time'] + $info['ttl'] : 0; - } - - return 0; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function removePattern($pattern) - { - if (!$this->enabled) - { - return true; - } - - $infos = apc_cache_info('user'); - if (!is_array($infos['cache_list'])) - { - return; - } - - $regexp = self::patternToRegexp($this->getOption('prefix').$pattern); - - foreach ($infos['cache_list'] as $info) - { - if (preg_match($regexp, $info['info'])) - { - apc_delete($info['info']); - } - } - } - - /** - * Gets the cache info - * - * @param string $key The cache key - * - * @return string - */ - protected function getCacheInfo($key) - { - if (!$this->enabled) - { - return false; - } - - $infos = apc_cache_info('user'); - - if (is_array($infos['cache_list'])) - { - foreach ($infos['cache_list'] as $info) - { - if ($this->getOption('prefix').$key == $info['info']) - { - return $info; - } - } - } - - return null; - } -} diff --git a/lib/cache/sfAPCuCache.class.php b/lib/cache/sfAPCuCache.class.php new file mode 100644 index 000000000..673eede28 --- /dev/null +++ b/lib/cache/sfAPCuCache.class.php @@ -0,0 +1,204 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Cache class that stores cached content in APCu. + * + * @author Fabien Potencier + * @author Paulo M + */ +class sfAPCuCache extends sfCache +{ + protected $enabled; + + /** + * Initializes this sfCache instance. + * + * Available options: + * + * * see sfCache for options available for all drivers + * + * @see sfCache + */ + public function initialize($options = []) + { + parent::initialize($options); + + $this->enabled = function_exists('apcu_store') && ini_get('apc.enabled'); + } + + /** + * @see sfCache + * + * @param mixed|null $default + */ + public function get($key, $default = null) + { + if (!$this->enabled) { + return $default; + } + + $value = $this->fetch($this->getOption('prefix').$key, $has); + + return $has ? $value : $default; + } + + /** + * @see sfCache + */ + public function has($key) + { + if (!$this->enabled) { + return false; + } + + $this->fetch($this->getOption('prefix').$key, $has); + + return $has; + } + + /** + * @see sfCache + * + * @param mixed|null $lifetime + */ + public function set($key, $data, $lifetime = null) + { + if (!$this->enabled) { + return true; + } + + return apcu_store($this->getOption('prefix').$key, $data, $this->getLifetime($lifetime)); + } + + /** + * @see sfCache + */ + public function remove($key) + { + if (!$this->enabled) { + return true; + } + + return apcu_delete($this->getOption('prefix').$key); + } + + /** + * @see sfCache + */ + public function clean($mode = sfCache::ALL) + { + if (!$this->enabled) { + return true; + } + + if (sfCache::ALL === $mode) { + return apcu_clear_cache(); + } + + return true; + } + + /** + * @see sfCache + */ + public function getLastModified($key) + { + if ($info = $this->getCacheInfo($key)) { + return $info['creation_time'] + $info['ttl'] > time() ? $info['mtime'] : 0; + } + + return 0; + } + + /** + * @see sfCache + */ + public function getTimeout($key) + { + if ($info = $this->getCacheInfo($key)) { + return $info['creation_time'] + $info['ttl'] > time() ? $info['creation_time'] + $info['ttl'] : 0; + } + + return 0; + } + + /** + * @see sfCache + */ + public function removePattern($pattern) + { + if (!$this->enabled) { + return true; + } + + $infos = apcu_cache_info(); + if (!is_array($infos['cache_list'])) { + return true; + } + + $regexp = $this->patternToRegexp($this->getOption('prefix').$pattern); + + foreach ($infos['cache_list'] as $info) { + if (preg_match($regexp, $info['info'])) { + apcu_delete($info['info']); + } + } + + return true; + } + + /** + * Gets the cache info. + * + * @param string $key The cache key + * + * @return string|false|array + */ + protected function getCacheInfo($key) + { + if (!$this->enabled) { + return false; + } + + $infos = apcu_cache_info(); + + if (is_array($infos['cache_list'])) { + foreach ($infos['cache_list'] as $info) { + if ($this->getOption('prefix').$key == $info['info']) { + return $info; + } + } + } + + return null; + } + + /** + * @param string $key + * + * @param-out bool $success + * + * @return false|mixed + */ + private function fetch($key, &$success) + { + $has = null; + $value = apcu_fetch($key, $has); + // the second argument was added in APC 3.0.17. If it is still null we fall back to the value returned + if (null !== $has) { + $success = $has; + } else { + $success = false !== $value; + } + + return $value; + } +} diff --git a/lib/cache/sfCache.class.php b/lib/cache/sfCache.class.php index 3be0e55c6..60b9a2858 100644 --- a/lib/cache/sfCache.class.php +++ b/lib/cache/sfCache.class.php @@ -11,227 +11,220 @@ /** * sfCache is an abstract class for all cache classes in symfony. * - * @package symfony - * @subpackage cache * @author Fabien Potencier - * @version SVN: $Id$ */ abstract class sfCache { - const OLD = 1; - const ALL = 2; - const SEPARATOR = ':'; - - protected - $options = array(); - - /** - * Class constructor. - * - * @see initialize() - * - * @param array $options - */ - public function __construct($options = array()) - { - $this->initialize($options); - } - - /** - * Initializes this sfCache instance. - * - * @param array $options An array of options. - * - * Available options: - * - * * automatic_cleaning_factor: The automatic cleaning process destroy too old (for the given life time) (default value: 1000) - * cache files when a new cache file is written. - * 0 => no automatic cache cleaning - * 1 => systematic cache cleaning - * x (integer) > 1 => automatic cleaning randomly 1 times on x cache write - * - * * lifetime (optional): The default life time (default value: 86400) - * - * @throws sfInitializationException If an error occurs while initializing this sfCache instance. - */ - public function initialize($options = array()) - { - $this->options = array_merge(array( - 'automatic_cleaning_factor' => 1000, - 'lifetime' => 86400, - 'prefix' => md5(__DIR__), - ), $options); - - $this->options['prefix'] .= self::SEPARATOR; - } - - /** - * Gets the cache content for a given key. - * - * @param string $key The cache key - * @param mixed $default The default value is the key does not exist or not valid anymore - * - * @return string The data of the cache - */ - abstract public function get($key, $default = null); - - /** - * Returns true if there is a cache for the given key. - * - * @param string $key The cache key - * - * @return Boolean true if the cache exists, false otherwise - */ - abstract public function has($key); - - /** - * Saves some data in the cache. - * - * @param string $key The cache key - * @param string $data The data to put in cache - * @param int $lifetime The lifetime - * - * @return Boolean true if no problem - */ - abstract public function set($key, $data, $lifetime = null); - - /** - * Removes a content from the cache. - * - * @param string $key The cache key - * - * @return Boolean true if no problem - */ - abstract public function remove($key); - - /** - * Removes content from the cache that matches the given pattern. - * - * @param string $pattern The cache key pattern - * - * @return Boolean true if no problem - * - * @see patternToRegexp - */ - abstract public function removePattern($pattern); - - /** - * Cleans the cache. - * - * @param int $mode The clean mode - * sfCache::ALL: remove all keys (default) - * sfCache::OLD: remove all expired keys - * - * @return Boolean true if no problem - */ - abstract public function clean($mode = self::ALL); - - /** - * Returns the timeout for the given key. - * - * @param string $key The cache key - * - * @return int The timeout time - */ - abstract public function getTimeout($key); - - /** - * Returns the last modification date of the given key. - * - * @param string $key The cache key - * - * @return int The last modified time (timestamp) - */ - abstract public function getLastModified($key); - - /** - * Gets many keys at once. - * - * @param array $keys An array of keys - * - * @return array An associative array of data from cache - */ - public function getMany($keys) - { - $data = array(); - foreach ($keys as $key) + public const OLD = 1; + public const ALL = 2; + public const SEPARATOR = ':'; + + protected $options = []; + + /** + * Class constructor. + * + * @see initialize() + * + * @param array $options + */ + public function __construct($options = []) { - $data[$key] = $this->get($key); + $this->initialize($options); } - return $data; - } - - /** - * Computes lifetime. - * - * @param integer $lifetime Lifetime in seconds - * - * @return integer Lifetime in seconds - */ - public function getLifetime($lifetime) - { - return null === $lifetime ? $this->getOption('lifetime') : $lifetime; - } - - /** - * Gets the backend object. - * - * @return mixed The backend object - * - * @throws sfException - */ - public function getBackend() - { - throw new sfException('This cache class does not have a backend object.'); - } - - /** - * Gets an option value. - * - * @param string $name The option name - * @param mixed $default The default value - * - * @return mixed The option value - */ - public function getOption($name, $default = null) - { - return isset($this->options[$name]) ? $this->options[$name] : $default; - } - - /** - * Sets an option value. - * - * @param string $name The option name - * @param mixed $value The option value - * - * @return mixed - */ - public function setOption($name, $value) - { - return $this->options[$name] = $value; - } - - /** - * Converts a pattern to a regular expression. - * - * A pattern can use some special characters: - * - * - * Matches a namespace (foo:*:bar) - * - ** Matches one or more namespaces (foo:**:bar) - * - * @param string $pattern A pattern - * - * @return string A regular expression - */ - protected function patternToRegexp($pattern) - { - $regexp = str_replace( - array('\\*\\*', '\\*'), - array('.+?', '[^'.preg_quote(sfCache::SEPARATOR, '#').']+'), - preg_quote($pattern, '#') - ); - - return '#^'.$regexp.'$#'; - } + /** + * Initializes this sfCache instance. + * + * @param array $options An array of options. + * + * Available options: + * + * * automatic_cleaning_factor: The automatic cleaning process destroy too old (for the given life time) (default value: 1000) + * cache files when a new cache file is written. + * 0 => no automatic cache cleaning + * 1 => systematic cache cleaning + * x (integer) > 1 => automatic cleaning randomly 1 times on x cache write + * + * * lifetime (optional): The default life time (default value: 86400) + * + * @throws sfInitializationException If an error occurs while initializing this sfCache instance + */ + public function initialize($options = []) + { + $this->options = array_merge([ + 'automatic_cleaning_factor' => 1000, + 'lifetime' => 86400, + 'prefix' => md5(__DIR__), + ], $options); + + $this->options['prefix'] .= self::SEPARATOR; + } + + /** + * Gets the cache content for a given key. + * + * @param string $key The cache key + * @param mixed $default The default value is the key does not exist or not valid anymore + * + * @return string The data of the cache + */ + abstract public function get($key, $default = null); + + /** + * Returns true if there is a cache for the given key. + * + * @param string $key The cache key + * + * @return bool true if the cache exists, false otherwise + */ + abstract public function has($key); + + /** + * Saves some data in the cache. + * + * @param string $key The cache key + * @param string $data The data to put in cache + * @param int $lifetime The lifetime + * + * @return bool true if no problem + */ + abstract public function set($key, $data, $lifetime = null); + + /** + * Removes a content from the cache. + * + * @param string $key The cache key + * + * @return bool true if no problem + */ + abstract public function remove($key); + + /** + * Removes content from the cache that matches the given pattern. + * + * @param string $pattern The cache key pattern + * + * @return bool true if no problem + * + * @see patternToRegexp + */ + abstract public function removePattern($pattern); + + /** + * Cleans the cache. + * + * @param int $mode The clean mode + * sfCache::ALL: remove all keys (default) + * sfCache::OLD: remove all expired keys + * + * @return bool true if no problem + */ + abstract public function clean($mode = self::ALL); + + /** + * Returns the timeout for the given key. + * + * @param string $key The cache key + * + * @return int The timeout time + */ + abstract public function getTimeout($key); + + /** + * Returns the last modification date of the given key. + * + * @param string $key The cache key + * + * @return int The last modified time (timestamp) + */ + abstract public function getLastModified($key); + + /** + * Gets many keys at once. + * + * @param array $keys An array of keys + * + * @return array An associative array of data from cache + */ + public function getMany($keys) + { + $data = []; + foreach ($keys as $key) { + $data[$key] = $this->get($key); + } + + return $data; + } + + /** + * Computes lifetime. + * + * @param int $lifetime Lifetime in seconds + * + * @return int Lifetime in seconds + */ + public function getLifetime($lifetime) + { + return null === $lifetime ? $this->getOption('lifetime') : $lifetime; + } + + /** + * Gets the backend object. + * + * @return mixed The backend object + * + * @throws sfException + */ + public function getBackend() + { + throw new sfException('This cache class does not have a backend object.'); + } + + /** + * Gets an option value. + * + * @param string $name The option name + * @param mixed $default The default value + * + * @return mixed The option value + */ + public function getOption($name, $default = null) + { + return isset($this->options[$name]) ? $this->options[$name] : $default; + } + + /** + * Sets an option value. + * + * @param string $name The option name + * @param mixed $value The option value + */ + public function setOption($name, $value) + { + return $this->options[$name] = $value; + } + + /** + * Converts a pattern to a regular expression. + * + * A pattern can use some special characters: + * + * - * Matches a namespace (foo:*:bar) + * - ** Matches one or more namespaces (foo:**:bar) + * + * @param string $pattern A pattern + * + * @return string A regular expression + */ + protected function patternToRegexp($pattern) + { + $regexp = str_replace( + ['\\*\\*', '\\*'], + ['.+?', '[^'.preg_quote(sfCache::SEPARATOR, '#').']+'], + preg_quote($pattern, '#') + ); + + return '#^'.$regexp.'$#'; + } } diff --git a/lib/cache/sfEAcceleratorCache.class.php b/lib/cache/sfEAcceleratorCache.class.php deleted file mode 100644 index ab08da295..000000000 --- a/lib/cache/sfEAcceleratorCache.class.php +++ /dev/null @@ -1,192 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Cache class that stores cached content in EAccelerator. - * - * @package symfony - * @subpackage cache - * @author Fabien Potencier - * @version SVN: $Id$ - */ -class sfEAcceleratorCache extends sfCache -{ - /** - * Initializes this sfCache instance. - * - * Available options: - * - * * see sfCache for options available for all drivers - * - * @see sfCache - * - * @param array $options - * - * @throws sfInitializationException - */ - public function initialize($options = array()) - { - parent::initialize($options); - - if (!function_exists('eaccelerator_put') || !ini_get('eaccelerator.enable')) - { - throw new sfInitializationException('You must have EAccelerator installed and enabled to use sfEAcceleratorCache class (or perhaps you forgot to add --with-eaccelerator-shared-memory when installing).'); - } - } - - /** - * @see sfCache - * - * @param string $key - * @param mixed $default - * - * @return null|string - */ - public function get($key, $default = null) - { - $value = eaccelerator_get($this->getOption('prefix').$key); - - return null === $value ? $default : $value; - } - - /** - * @see sfCache - * - * @param string $key - * - * @return bool - */ - public function has($key) - { - return null !== eaccelerator_get($this->getOption('prefix'.$key)); - } - - /** - * @see sfCache - * - * @param string $key - * @param string $data - * @param int|null $lifetime - * - * @return bool - */ - public function set($key, $data, $lifetime = null) - { - return eaccelerator_put($this->getOption('prefix').$key, $data, $this->getLifetime($lifetime)); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function remove($key) - { - return eaccelerator_rm($this->getOption('prefix').$key); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function removePattern($pattern) - { - $infos = eaccelerator_list_keys(); - - if (is_array($infos)) - { - $regexp = self::patternToRegexp($this->getOption('prefix').$pattern); - - foreach ($infos as $info) - { - if (preg_match($regexp, $info['name'])) - { - eaccelerator_rm($this->getOption('prefix').$key); - } - } - } - } - - /** - * @see sfCache - * @inheritdoc - */ - public function clean($mode = sfCache::ALL) - { - if (sfCache::OLD === $mode) - { - return eaccelerator_gc(); - } - - $infos = eaccelerator_list_keys(); - if (is_array($infos)) - { - foreach ($infos as $info) - { - if (false !== strpos($info['name'], $this->getOption('prefix'))) - { - // eaccelerator bug (http://eaccelerator.net/ticket/287) - $key = 0 === strpos($info['name'], ':') ? substr($info['name'], 1) : $info['name']; - if (!eaccelerator_rm($key)) - { - return false; - } - } - } - } - - return true; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function getLastModified($key) - { - if ($info = $this->getCacheInfo($key)) - { - return $info['created']; - } - - return 0; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function getTimeout($key) - { - if ($info = $this->getCacheInfo($key)) - { - return -1 == $info['ttl'] ? 0 : $info['created'] + $info['ttl']; - } - - return 0; - } - - protected function getCacheInfo($key) - { - $infos = eaccelerator_list_keys(); - - if (is_array($infos)) - { - foreach ($infos as $info) - { - if ($this->getOption('prefix').$key == $info['name']) - { - return $info; - } - } - } - - return null; - } -} diff --git a/lib/cache/sfFileCache.class.php b/lib/cache/sfFileCache.class.php index f84be899f..dd5a9864e 100644 --- a/lib/cache/sfFileCache.class.php +++ b/lib/cache/sfFileCache.class.php @@ -11,343 +11,305 @@ /** * Cache class that stores content in files. * - * @package symfony - * @subpackage cache * @author Fabien Potencier - * @version SVN: $Id$ */ class sfFileCache extends sfCache { - const READ_DATA = 1; - const READ_TIMEOUT = 2; - const READ_LAST_MODIFIED = 4; - - const EXTENSION = '.cache'; - - /** - * Initializes this sfCache instance. - * - * Available options: - * - * * cache_dir: The directory where to put cache files - * - * * see sfCache for options available for all drivers - * - * @see sfCache - * @inheritdoc - */ - public function initialize($options = array()) - { - parent::initialize($options); - - if (!$this->getOption('cache_dir')) + public const READ_DATA = 1; + public const READ_TIMEOUT = 2; + public const READ_LAST_MODIFIED = 4; + + public const EXTENSION = '.cache'; + + /** + * Initializes this sfCache instance. + * + * Available options: + * + * * cache_dir: The directory where to put cache files + * + * * see sfCache for options available for all drivers + * + * @see sfCache + */ + public function initialize($options = []) { - throw new sfInitializationException('You must pass a "cache_dir" option to initialize a sfFileCache object.'); + parent::initialize($options); + + if (!$this->getOption('cache_dir')) { + throw new sfInitializationException('You must pass a "cache_dir" option to initialize a sfFileCache object.'); + } + + $this->setcache_dir($this->getOption('cache_dir')); } - $this->setcache_dir($this->getOption('cache_dir')); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function get($key, $default = null) - { - $file_path = $this->getFilePath($key); - if (!is_file($file_path)) + /** + * @see sfCache + * + * @param mixed|null $default + */ + public function get($key, $default = null) { - return $default; - } + $file_path = $this->getFilePath($key); + if (!is_file($file_path)) { + return $default; + } - $data = $this->read($file_path, self::READ_DATA); + $data = $this->read($file_path, self::READ_DATA); - if ($data[self::READ_DATA] === null) - { - return $default; + if (null === $data[self::READ_DATA]) { + return $default; + } + + return $data[self::READ_DATA]; } - return $data[self::READ_DATA]; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function has($key) - { - $path = $this->getFilePath($key); - - return is_file($path) && $this->isValid($path); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function set($key, $data, $lifetime = null) - { - if ($this->getOption('automatic_cleaning_factor') > 0 && mt_rand(1, $this->getOption('automatic_cleaning_factor')) == 1) + /** + * @see sfCache + */ + public function has($key) { - $this->clean(sfCache::OLD); + $path = $this->getFilePath($key); + + return is_file($path) && $this->isValid($path); } - return $this->write($this->getFilePath($key), $data, time() + $this->getLifetime($lifetime)); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function remove($key) - { - return @unlink($this->getFilePath($key)); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function removePattern($pattern) - { - if (false !== strpos($pattern, '**')) + /** + * @see sfCache + * + * @param mixed|null $lifetime + */ + public function set($key, $data, $lifetime = null) { - $pattern = str_replace(sfCache::SEPARATOR, DIRECTORY_SEPARATOR, $pattern).self::EXTENSION; - - $regexp = self::patternToRegexp($pattern); - $paths = array(); - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->getOption('cache_dir'))) as $path) - { - if (preg_match($regexp, str_replace($this->getOption('cache_dir').DIRECTORY_SEPARATOR, '', $path))) - { - $paths[] = $path; + if ($this->getOption('automatic_cleaning_factor') > 0 && 1 == mt_rand(1, $this->getOption('automatic_cleaning_factor'))) { + $this->clean(sfCache::OLD); } - } + + return $this->write($this->getFilePath($key), $data, time() + $this->getLifetime($lifetime)); } - else + + /** + * @see sfCache + */ + public function remove($key) { - $paths = glob($this->getOption('cache_dir').DIRECTORY_SEPARATOR.str_replace(sfCache::SEPARATOR, DIRECTORY_SEPARATOR, $pattern).self::EXTENSION); + return @unlink($this->getFilePath($key)); } - foreach ($paths as $path) + /** + * @see sfCache + */ + public function removePattern($pattern) { - if (is_dir($path)) - { - sfToolkit::clearDirectory($path); - } - else - { - @unlink($path); - } + if (false !== strpos($pattern, '**')) { + $pattern = str_replace(sfCache::SEPARATOR, DIRECTORY_SEPARATOR, $pattern).self::EXTENSION; + + $regexp = self::patternToRegexp($pattern); + $paths = []; + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->getOption('cache_dir'))) as $path) { + if (preg_match($regexp, str_replace($this->getOption('cache_dir').DIRECTORY_SEPARATOR, '', $path))) { + $paths[] = $path; + } + } + } else { + $paths = glob($this->getOption('cache_dir').DIRECTORY_SEPARATOR.str_replace(sfCache::SEPARATOR, DIRECTORY_SEPARATOR, $pattern).self::EXTENSION); + } + + foreach ($paths as $path) { + if (is_dir($path)) { + sfToolkit::clearDirectory($path); + } else { + @unlink($path); + } + } + + return true; } - } - - /** - * @see sfCache - * @inheritdoc - */ - public function clean($mode = sfCache::ALL) - { - if (!is_dir($this->getOption('cache_dir'))) + + /** + * @see sfCache + */ + public function clean($mode = sfCache::ALL) { - return true; + if (!is_dir($this->getOption('cache_dir'))) { + return true; + } + + $result = true; + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->getOption('cache_dir'))) as $file) { + if (sfCache::ALL == $mode || !$this->isValid($file)) { + $result = @unlink($file) && $result; + } + } + + return $result; } - $result = true; - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->getOption('cache_dir'))) as $file) + /** + * @see sfCache + */ + public function getTimeout($key) { - if (sfCache::ALL == $mode || !$this->isValid($file)) - { - $result = @unlink($file) && $result; - } - } + $path = $this->getFilePath($key); - return $result; - } + if (!is_file($path)) { + return 0; + } - /** - * @see sfCache - * @inheritdoc - */ - public function getTimeout($key) - { - $path = $this->getFilePath($key); + $data = $this->read($path, self::READ_TIMEOUT); - if (!is_file($path)) - { - return 0; + return $data[self::READ_TIMEOUT] < time() ? 0 : $data[self::READ_TIMEOUT]; } - $data = $this->read($path, self::READ_TIMEOUT); + /** + * @see sfCache + */ + public function getLastModified($key) + { + $path = $this->getFilePath($key); - return $data[self::READ_TIMEOUT] < time() ? 0 : $data[self::READ_TIMEOUT]; - } + if (!is_file($path)) { + return 0; + } - /** - * @see sfCache - * @inheritdoc - */ - public function getLastModified($key) - { - $path = $this->getFilePath($key); + $data = $this->read($path, self::READ_TIMEOUT | self::READ_LAST_MODIFIED); - if (!is_file($path)) - { - return 0; - } + if ($data[self::READ_TIMEOUT] < time()) { + return 0; + } - $data = $this->read($path, self::READ_TIMEOUT | self::READ_LAST_MODIFIED); + return $data[self::READ_LAST_MODIFIED]; + } - if ($data[self::READ_TIMEOUT] < time()) + protected function isValid($path) { - return 0; + $data = $this->read($path, self::READ_TIMEOUT); + + return time() < $data[self::READ_TIMEOUT]; } - return $data[self::READ_LAST_MODIFIED]; - } - - protected function isValid($path) - { - $data = $this->read($path, self::READ_TIMEOUT); - return time() < $data[self::READ_TIMEOUT]; - } - - /** - * Converts a cache key to a full path. - * - * @param string $key The cache key - * - * @return string The full path to the cache file - */ - protected function getFilePath($key) - { - return $this->getOption('cache_dir').DIRECTORY_SEPARATOR.str_replace(sfCache::SEPARATOR, DIRECTORY_SEPARATOR, $key).self::EXTENSION; - } - - /** - * Reads the cache file and returns the content. - * - * @param string $path The file path - * @param mixed $type The type of data you want to be returned - * sfFileCache::READ_DATA: The cache content - * sfFileCache::READ_TIMEOUT: The timeout - * sfFileCache::READ_LAST_MODIFIED: The last modification timestamp - * - * @return array the (meta)data of the cache file. E.g. $data[sfFileCache::READ_DATA] - * - * @throws sfCacheException - */ - protected function read($path, $type = self::READ_DATA) - { - if (!$fp = @fopen($path, 'rb')) + + /** + * Converts a cache key to a full path. + * + * @param string $key The cache key + * + * @return string The full path to the cache file + */ + protected function getFilePath($key) { - throw new sfCacheException(sprintf('Unable to read cache file "%s".', $path)); + return $this->getOption('cache_dir').DIRECTORY_SEPARATOR.str_replace(sfCache::SEPARATOR, DIRECTORY_SEPARATOR, $key).self::EXTENSION; } - @flock($fp, LOCK_SH); - $data[self::READ_TIMEOUT] = (int) @stream_get_contents($fp, 12, 0); - if ($type != self::READ_TIMEOUT && time() < $data[self::READ_TIMEOUT]) + /** + * Reads the cache file and returns the content. + * + * @param string $path The file path + * @param mixed $type The type of data you want to be returned + * sfFileCache::READ_DATA: The cache content + * sfFileCache::READ_TIMEOUT: The timeout + * sfFileCache::READ_LAST_MODIFIED: The last modification timestamp + * + * @return array the (meta)data of the cache file. E.g. $data[sfFileCache::READ_DATA] + * + * @throws sfCacheException + */ + protected function read($path, $type = self::READ_DATA) { - if ($type & self::READ_LAST_MODIFIED) - { - $data[self::READ_LAST_MODIFIED] = (int) @stream_get_contents($fp, 12, 12); - } - if ($type & self::READ_DATA) - { - fseek($fp, 0, SEEK_END); - $length = ftell($fp) - 24; - fseek($fp, 24); - - if ($length > 0) - { - $data[self::READ_DATA] = @fread($fp, $length); + if (!$fp = @fopen($path, 'rb')) { + throw new sfCacheException(sprintf('Unable to read cache file "%s".', $path)); } - else - { - $data[self::READ_DATA] = ''; + + @flock($fp, LOCK_SH); + $data[self::READ_TIMEOUT] = (int) @stream_get_contents($fp, 12, 0); + if (self::READ_TIMEOUT != $type && time() < $data[self::READ_TIMEOUT]) { + if ($type & self::READ_LAST_MODIFIED) { + $data[self::READ_LAST_MODIFIED] = (int) @stream_get_contents($fp, 12, 12); + } + if ($type & self::READ_DATA) { + fseek($fp, 0, SEEK_END); + $length = ftell($fp) - 24; + fseek($fp, 24); + + if ($length > 0) { + $data[self::READ_DATA] = @fread($fp, $length); + } else { + $data[self::READ_DATA] = ''; + } + } + } else { + $data[self::READ_LAST_MODIFIED] = null; + $data[self::READ_DATA] = null; } - } - } - else - { - $data[self::READ_LAST_MODIFIED] = null; - $data[self::READ_DATA] = null; + @flock($fp, LOCK_UN); + @fclose($fp); + + return $data; } - @flock($fp, LOCK_UN); - @fclose($fp); - - return $data; - } - - /** - * Writes the given data in the cache file. - * - * @param string $path The file path - * @param string $data The data to put in cache - * @param integer $timeout The timeout timestamp - * - * @return boolean true if ok, otherwise false - * - * @throws sfCacheException - */ - protected function write($path, $data, $timeout) - { - $current_umask = umask(); - umask(0000); - - $cacheDir = dirname($path); - if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) + + /** + * Writes the given data in the cache file. + * + * @param string $path The file path + * @param string $data The data to put in cache + * @param int $timeout The timeout timestamp + * + * @return bool true if ok, otherwise false + * + * @throws sfCacheException + */ + protected function write($path, $data, $timeout) { - throw new \sfCacheException(sprintf('Cache was not able to create a directory "%s".', $cacheDir)); - } + $current_umask = umask(); + umask(0000); - $tmpFile = tempnam($cacheDir, basename($path)); + $cacheDir = dirname($path); + if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) { + throw new sfCacheException(sprintf('Cache was not able to create a directory "%s".', $cacheDir)); + } - if (!$fp = @fopen($tmpFile, 'wb')) - { - throw new sfCacheException(sprintf('Unable to write cache file "%s".', $tmpFile)); - } + $tmpFile = tempnam($cacheDir, basename($path)); - @fwrite($fp, str_pad($timeout, 12, 0, STR_PAD_LEFT)); - @fwrite($fp, str_pad(time(), 12, 0, STR_PAD_LEFT)); - @fwrite($fp, $data); - @fclose($fp); + if (!$fp = @fopen($tmpFile, 'wb')) { + throw new sfCacheException(sprintf('Unable to write cache file "%s".', $tmpFile)); + } - // Hack from Agavi (http://trac.agavi.org/changeset/3979) - // With php < 5.2.6 on win32, renaming to an already existing file doesn't work, but copy does, - // so we simply assume that when rename() fails that we are on win32 and try to use copy() - if (!@rename($tmpFile, $path)) - { - if (copy($tmpFile, $path)) - { - unlink($tmpFile); - } - } + @fwrite($fp, str_pad($timeout, 12, 0, STR_PAD_LEFT)); + @fwrite($fp, str_pad(time(), 12, 0, STR_PAD_LEFT)); + @fwrite($fp, $data); + @fclose($fp); + + // Hack from Agavi (http://trac.agavi.org/changeset/3979) + // With php < 5.2.6 on win32, renaming to an already existing file doesn't work, but copy does, + // so we simply assume that when rename() fails that we are on win32 and try to use copy() + if (!@rename($tmpFile, $path)) { + if (copy($tmpFile, $path)) { + unlink($tmpFile); + } + } - chmod($path, 0666); - umask($current_umask); - - return true; - } - - /** - * Sets the cache root directory. - * - * @param string $cache_dir The directory where to put the cache files - */ - protected function setcache_dir($cache_dir) - { - // remove last DIRECTORY_SEPARATOR - if (DIRECTORY_SEPARATOR == substr($cache_dir, -1)) - { - $cache_dir = substr($cache_dir, 0, -1); + chmod($path, 0666); + umask($current_umask); + + return true; } - // create cache dir if needed - if (!is_dir($cache_dir)) + /** + * Sets the cache root directory. + * + * @param string $cache_dir The directory where to put the cache files + */ + protected function setcache_dir($cache_dir) { - $current_umask = umask(0000); - @mkdir($cache_dir, 0777, true); - umask($current_umask); + // remove last DIRECTORY_SEPARATOR + if (DIRECTORY_SEPARATOR == substr($cache_dir, -1)) { + $cache_dir = substr($cache_dir, 0, -1); + } + + // create cache dir if needed + if (!is_dir($cache_dir)) { + $current_umask = umask(0000); + @mkdir($cache_dir, 0777, true); + umask($current_umask); + } } - } } diff --git a/lib/cache/sfFunctionCache.class.php b/lib/cache/sfFunctionCache.class.php index 109a8d1a4..8d890099d 100644 --- a/lib/cache/sfFunctionCache.class.php +++ b/lib/cache/sfFunctionCache.class.php @@ -11,104 +11,96 @@ /** * This class can be used to cache the result and output of any PHP callable (function and method calls). * - * @package symfony - * @subpackage cache * @author Fabien Potencier - * @version SVN: $Id$ */ class sfFunctionCache { - protected $cache = null; + protected $cache; - /** - * Constructor. - * - * @param sfCache $cache An sfCache object instance - */ - public function __construct(sfCache $cache) - { - $this->cache = $cache; - } - - /** - * Calls a cacheable function or method (or not if there is already a cache for it). - * - * Arguments of this method are read with func_get_args. So it doesn't appear in the function definition. - * - * The first argument can be any PHP callable: - * - * $cache->call('functionName', array($arg1, $arg2)); - * $cache->call(array($object, 'methodName'), array($arg1, $arg2)); - * - * @param mixed $callable A PHP callable - * @param array $arguments An array of arguments to pass to the callable - * @return mixed The result of the function/method - * - * @throws Exception - * @throws sfException - */ - public function call($callable, $arguments = array()) - { - // Generate a cache id - $key = $this->computeCacheKey($callable, $arguments); - - $serialized = $this->cache->get($key); - if ($serialized !== null) + /** + * Constructor. + * + * @param sfCache $cache An sfCache object instance + */ + public function __construct(sfCache $cache) { - $data = unserialize($serialized); + $this->cache = $cache; } - else + + /** + * Calls a cacheable function or method (or not if there is already a cache for it). + * + * Arguments of this method are read with func_get_args. So it doesn't appear in the function definition. + * + * The first argument can be any PHP callable: + * + * $cache->call('functionName', array($arg1, $arg2)); + * $cache->call(array($object, 'methodName'), array($arg1, $arg2)); + * + * @param mixed $callable A PHP callable + * @param array $arguments An array of arguments to pass to the callable + * + * @return mixed The result of the function/method + * + * @throws Exception + * @throws sfException + */ + public function call($callable, $arguments = []) { - $data = array(); + // Generate a cache id + $key = $this->computeCacheKey($callable, $arguments); - if (!is_callable($callable)) - { - throw new sfException('The first argument to call() must be a valid callable.'); - } + $serialized = $this->cache->get($key); + if (null !== $serialized) { + $data = unserialize($serialized); + } else { + $data = []; - ob_start(); - ob_implicit_flush(false); + if (!is_callable($callable)) { + throw new sfException('The first argument to call() must be a valid callable.'); + } - try - { - $data['result'] = call_user_func_array($callable, $arguments); - } - catch (Exception $e) - { - ob_end_clean(); - throw $e; - } + ob_start(); + ob_implicit_flush(false); - $data['output'] = ob_get_clean(); + try { + $data['result'] = call_user_func_array($callable, $arguments); + } catch (Exception $e) { + ob_end_clean(); - $this->cache->set($key, serialize($data)); - } + throw $e; + } + + $data['output'] = ob_get_clean(); - echo $data['output']; + $this->cache->set($key, serialize($data)); + } - return $data['result']; - } + echo $data['output']; - /** - * Returns the cache instance. - * - * @return sfCache The sfCache instance - */ - public function getCache() - { - return $this->cache; - } + return $data['result']; + } - /** - * Computes the cache key for a given callable and the arguments. - * - * @param mixed $callable A PHP callable - * @param array $arguments An array of arguments to pass to the callable - * - * @return string The associated cache key - */ - public function computeCacheKey($callable, $arguments = array()) - { - return md5(serialize($callable).serialize($arguments)); - } + /** + * Returns the cache instance. + * + * @return sfCache The sfCache instance + */ + public function getCache() + { + return $this->cache; + } + + /** + * Computes the cache key for a given callable and the arguments. + * + * @param mixed $callable A PHP callable + * @param array $arguments An array of arguments to pass to the callable + * + * @return string The associated cache key + */ + public function computeCacheKey($callable, $arguments = []) + { + return md5(serialize($callable).serialize($arguments)); + } } diff --git a/lib/cache/sfMemcacheCache.class.php b/lib/cache/sfMemcacheCache.class.php index de611e9ed..0caae1753 100644 --- a/lib/cache/sfMemcacheCache.class.php +++ b/lib/cache/sfMemcacheCache.class.php @@ -11,297 +11,266 @@ /** * Cache class that stores cached content in memcache. * - * @package symfony - * @subpackage cache * @author Fabien Potencier - * @version SVN: $Id$ */ class sfMemcacheCache extends sfCache { - /** @var Memcache */ - protected $memcache = null; - - /** - * Initializes this sfCache instance. - * - * Available options: - * - * * memcache: A memcache object (optional) - * - * * host: The default host (default to localhost) - * * port: The port for the default server (default to 11211) - * * persistent: true if the connection must be persistent, false otherwise (true by default) - * - * * servers: An array of additional servers (keys: host, port, persistent) - * - * * see sfCache for options available for all drivers - * - * @see sfCache - * @inheritdoc - */ - public function initialize($options = array()) - { - parent::initialize($options); - - if (!class_exists('Memcache')) + /** @var Memcache */ + protected $memcache; + + /** + * Initializes this sfCache instance. + * + * Available options: + * + * * memcache: A memcache object (optional) + * + * * host: The default host (default to localhost) + * * port: The port for the default server (default to 11211) + * * persistent: true if the connection must be persistent, false otherwise (true by default) + * + * * servers: An array of additional servers (keys: host, port, persistent) + * + * * see sfCache for options available for all drivers + * + * @see sfCache + */ + public function initialize($options = []) { - throw new sfInitializationException('You must have memcache installed and enabled to use sfMemcacheCache class.'); - } + parent::initialize($options); - if ($this->getOption('memcache')) - { - $this->memcache = $this->getOption('memcache'); - } - else - { - $this->memcache = new Memcache(); - - if ($this->getOption('servers')) - { - foreach ($this->getOption('servers') as $server) - { - $port = isset($server['port']) ? $server['port'] : 11211; - if (!$this->memcache->addServer($server['host'], $port, isset($server['persistent']) ? $server['persistent'] : true)) - { - throw new sfInitializationException(sprintf('Unable to connect to the memcache server (%s:%s).', $server['host'], $port)); - } + if (!class_exists('Memcache')) { + throw new sfInitializationException('You must have memcache installed and enabled to use sfMemcacheCache class.'); } - } - else - { - $method = $this->getOption('persistent', true) ? 'pconnect' : 'connect'; - if (!$this->memcache->$method($this->getOption('host', 'localhost'), $this->getOption('port', 11211), $this->getOption('timeout', 1))) - { - throw new sfInitializationException(sprintf('Unable to connect to the memcache server (%s:%s).', $this->getOption('host', 'localhost'), $this->getOption('port', 11211))); + + if ($this->getOption('memcache')) { + $this->memcache = $this->getOption('memcache'); + } else { + $this->memcache = new Memcache(); + + if ($this->getOption('servers')) { + foreach ($this->getOption('servers') as $server) { + $port = isset($server['port']) ? $server['port'] : 11211; + if (!$this->memcache->addServer($server['host'], $port, isset($server['persistent']) ? $server['persistent'] : true)) { + throw new sfInitializationException(sprintf('Unable to connect to the memcache server (%s:%s).', $server['host'], $port)); + } + } + } else { + $method = $this->getOption('persistent', true) ? 'pconnect' : 'connect'; + if (!$this->memcache->{$method}($this->getOption('host', 'localhost'), $this->getOption('port', 11211), $this->getOption('timeout', 1))) { + throw new sfInitializationException(sprintf('Unable to connect to the memcache server (%s:%s).', $this->getOption('host', 'localhost'), $this->getOption('port', 11211))); + } + } } - } } - } - - /** - * @see sfCache - * @return Memcache - */ - public function getBackend() - { - return $this->memcache; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function get($key, $default = null) - { - $value = $this->memcache->get($this->getOption('prefix').$key); - - return (false === $value && false === $this->getMetadata($key)) ? $default : $value; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function has($key) - { - if (false === $this->memcache->get($this->getOption('prefix') . $key)) + + /** + * @see sfCache + * + * @return Memcache + */ + public function getBackend() { - // if there is metadata, $key exists with a false value - return !(false === $this->getMetadata($key)); + return $this->memcache; } - return true; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function set($key, $data, $lifetime = null) - { - $lifetime = null === $lifetime ? $this->getOption('lifetime') : $lifetime; - - // save metadata - $this->setMetadata($key, $lifetime); - - // save key for removePattern() - if ($this->getOption('storeCacheInfo', false)) + /** + * @see sfCache + * + * @param mixed|null $default + */ + public function get($key, $default = null) { - $this->setCacheInfo($key); + $value = $this->memcache->get($this->getOption('prefix').$key); + + return (false === $value && false === $this->getMetadata($key)) ? $default : $value; } - if (false !== $this->memcache->replace($this->getOption('prefix').$key, $data, false, time() + $lifetime)) + /** + * @see sfCache + */ + public function has($key) { - return true; + if (false === $this->memcache->get($this->getOption('prefix').$key)) { + // if there is metadata, $key exists with a false value + return !(false === $this->getMetadata($key)); + } + + return true; } - return $this->memcache->set($this->getOption('prefix').$key, $data, false, time() + $lifetime); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function remove($key) - { - // delete metadata - $this->memcache->delete($this->getOption('prefix').'_metadata'.self::SEPARATOR.$key, 0); - if ($this->getOption('storeCacheInfo', false)) + /** + * @see sfCache + * + * @param mixed|null $lifetime + */ + public function set($key, $data, $lifetime = null) { - $this->setCacheInfo($key, true); + $lifetime = null === $lifetime ? $this->getOption('lifetime') : $lifetime; + + // save metadata + $this->setMetadata($key, $lifetime); + + // save key for removePattern() + if ($this->getOption('storeCacheInfo', false)) { + $this->setCacheInfo($key); + } + + if (false !== $this->memcache->replace($this->getOption('prefix').$key, $data, false, time() + $lifetime)) { + return true; + } + + return $this->memcache->set($this->getOption('prefix').$key, $data, false, time() + $lifetime); } - return $this->memcache->delete($this->getOption('prefix').$key, 0); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function clean($mode = sfCache::ALL) - { - if (sfCache::ALL === $mode) + + /** + * @see sfCache + */ + public function remove($key) { - return $this->memcache->flush(); + // delete metadata + $this->memcache->delete($this->getOption('prefix').'_metadata'.self::SEPARATOR.$key, 0); + if ($this->getOption('storeCacheInfo', false)) { + $this->setCacheInfo($key, true); + } + + return $this->memcache->delete($this->getOption('prefix').$key, 0); } - } - - /** - * @see sfCache - * @inheritdoc - */ - public function getLastModified($key) - { - if (false === ($retval = $this->getMetadata($key))) + + /** + * @see sfCache + */ + public function clean($mode = sfCache::ALL) { - return 0; - } + if (sfCache::ALL === $mode) { + return $this->memcache->flush(); + } - return $retval['lastModified']; - } + return true; + } - /** - * @see sfCache - * @inheritdoc - */ - public function getTimeout($key) - { - if (false === ($retval = $this->getMetadata($key))) + /** + * @see sfCache + */ + public function getLastModified($key) { - return 0; + if (false === ($retval = $this->getMetadata($key))) { + return 0; + } + + return $retval['lastModified']; } - return $retval['timeout']; - } - - /** - * @see sfCache - * @inheritdoc - * - * @throws sfCacheException - */ - public function removePattern($pattern) - { - if (!$this->getOption('storeCacheInfo', false)) + /** + * @see sfCache + */ + public function getTimeout($key) { - throw new sfCacheException('To use the "removePattern" method, you must set the "storeCacheInfo" option to "true".'); + if (false === ($retval = $this->getMetadata($key))) { + return 0; + } + + return $retval['timeout']; } - $regexp = self::patternToRegexp($this->getOption('prefix').$pattern); - foreach ($this->getCacheInfo() as $key) + /** + * @see sfCache + * + * @throws sfCacheException + */ + public function removePattern($pattern) { - if (preg_match($regexp, $key)) - { - $this->remove(substr($key, strlen($this->getOption('prefix')))); - } + if (!$this->getOption('storeCacheInfo', false)) { + throw new sfCacheException('To use the "removePattern" method, you must set the "storeCacheInfo" option to "true".'); + } + + $regexp = self::patternToRegexp($this->getOption('prefix').$pattern); + foreach ($this->getCacheInfo() as $key) { + if (preg_match($regexp, $key)) { + $this->remove(substr($key, strlen($this->getOption('prefix')))); + } + } + + return true; } - } - - /** - * @see sfCache - * @inheritdoc - */ - public function getMany($keys) - { - $values = array(); - $prefix = $this->getOption('prefix'); - $prefixed_keys = array_map(function($k) use ($prefix) { return $prefix . $k; }, $keys); - - foreach ($this->memcache->get($prefixed_keys) as $key => $value) + + /** + * @see sfCache + */ + public function getMany($keys) { - $values[str_replace($prefix, '', $key)] = $value; + $values = []; + $prefix = $this->getOption('prefix'); + $prefixed_keys = array_map(function ($k) use ($prefix) { return $prefix.$k; }, $keys); + + foreach ($this->memcache->get($prefixed_keys) as $key => $value) { + $values[str_replace($prefix, '', $key)] = $value; + } + + return $values; } - return $values; - } - - /** - * Gets metadata about a key in the cache. - * - * @param string $key A cache key - * - * @return array An array of metadata information - */ - protected function getMetadata($key) - { - return $this->memcache->get($this->getOption('prefix').'_metadata'.self::SEPARATOR.$key); - } - - /** - * Stores metadata about a key in the cache. - * - * @param string $key A cache key - * @param string $lifetime The lifetime - */ - protected function setMetadata($key, $lifetime) - { - $this->memcache->set($this->getOption('prefix').'_metadata'.self::SEPARATOR.$key, array('lastModified' => time(), 'timeout' => time() + $lifetime), false, time() + $lifetime); - } - - /** - * Updates the cache information for the given cache key. - * - * @param string $key The cache key - * @param boolean $delete Delete key or not - */ - protected function setCacheInfo($key, $delete = false) - { - $keys = $this->memcache->get($this->getOption('prefix').'_metadata'); - if (!is_array($keys)) + /** + * Gets metadata about a key in the cache. + * + * @param string $key A cache key + * + * @return array An array of metadata information + */ + protected function getMetadata($key) { - $keys = array(); + return $this->memcache->get($this->getOption('prefix').'_metadata'.self::SEPARATOR.$key); } - if ($delete) + /** + * Stores metadata about a key in the cache. + * + * @param string $key A cache key + * @param string $lifetime The lifetime + */ + protected function setMetadata($key, $lifetime) { - if (($k = array_search($this->getOption('prefix').$key, $keys)) !== false) - { - unset($keys[$k]); - } + $this->memcache->set($this->getOption('prefix').'_metadata'.self::SEPARATOR.$key, ['lastModified' => time(), 'timeout' => time() + $lifetime], false, time() + $lifetime); } - else + + /** + * Updates the cache information for the given cache key. + * + * @param string $key The cache key + * @param bool $delete Delete key or not + */ + protected function setCacheInfo($key, $delete = false) { - if (!in_array($this->getOption('prefix').$key, $keys)) - { - $keys[] = $this->getOption('prefix').$key; - } + $keys = $this->memcache->get($this->getOption('prefix').'_metadata'); + if (!is_array($keys)) { + $keys = []; + } + + if ($delete) { + if (($k = array_search($this->getOption('prefix').$key, $keys)) !== false) { + unset($keys[$k]); + } + } else { + if (!in_array($this->getOption('prefix').$key, $keys)) { + $keys[] = $this->getOption('prefix').$key; + } + } + + $this->memcache->set($this->getOption('prefix').'_metadata', $keys, 0); } - $this->memcache->set($this->getOption('prefix').'_metadata', $keys, 0); - } - - /** - * Gets cache information. - * - * @return array - */ - protected function getCacheInfo() - { - $keys = $this->memcache->get($this->getOption('prefix').'_metadata'); - if (!is_array($keys)) + /** + * Gets cache information. + * + * @return array + */ + protected function getCacheInfo() { - return array(); - } + $keys = $this->memcache->get($this->getOption('prefix').'_metadata'); + if (!is_array($keys)) { + return []; + } - return $keys; - } + return $keys; + } } diff --git a/lib/cache/sfNoCache.class.php b/lib/cache/sfNoCache.class.php index 9891a98e4..788d68dc2 100644 --- a/lib/cache/sfNoCache.class.php +++ b/lib/cache/sfNoCache.class.php @@ -11,82 +11,75 @@ /** * Cache class that does nothing. * - * @package symfony - * @subpackage cache * @author Fabien Potencier - * @version SVN: $Id$ */ class sfNoCache extends sfCache { - /** - * @see sfCache - * @inheritdoc - */ - public function get($key, $default = null) - { - return $default; - } + /** + * @see sfCache + * + * @param mixed|null $default + */ + public function get($key, $default = null) + { + return $default; + } - /** - * @see sfCache - * @inheritdoc - */ - public function has($key) - { - return false; - } + /** + * @see sfCache + */ + public function has($key) + { + return false; + } - /** - * @see sfCache - * @inheritdoc - */ - public function set($key, $data, $lifetime = null) - { - return true; - } + /** + * @see sfCache + * + * @param mixed|null $lifetime + */ + public function set($key, $data, $lifetime = null) + { + return true; + } - /** - * @see sfCache - * @inheritdoc - */ - public function remove($key) - { - return true; - } + /** + * @see sfCache + */ + public function remove($key) + { + return true; + } - /** - * @see sfCache - * @inheritdoc - */ - public function removePattern($pattern) - { - return true; - } + /** + * @see sfCache + */ + public function removePattern($pattern) + { + return true; + } - /** - * @see sfCache - * @inheritdoc - */ - public function clean($mode = self::ALL) - { - return true; - } + /** + * @see sfCache + */ + public function clean($mode = self::ALL) + { + return true; + } - /** - * @see sfCache - * @inheritdoc - */ - public function getLastModified($key) - { - return 0; - } + /** + * @see sfCache + */ + public function getLastModified($key) + { + return 0; + } - /** - * @see sfCache - * @inheritdoc - */ - public function getTimeout($key) - { - return 0; - } + /** + * @see sfCache + */ + public function getTimeout($key) + { + return 0; + } } diff --git a/lib/cache/sfSQLiteCache.class.php b/lib/cache/sfSQLiteCache.class.php index 093e0a0db..30484ad2d 100644 --- a/lib/cache/sfSQLiteCache.class.php +++ b/lib/cache/sfSQLiteCache.class.php @@ -11,341 +11,304 @@ /** * Cache class that stores cached content in a SQLite database. * - * @package symfony - * @subpackage cache * @author Fabien Potencier - * @version SVN: $Id$ */ class sfSQLiteCache extends sfCache { - protected - $dbh = null, - $sqlLiteVersion = null, - $database = ''; - - /** - * Initializes this sfCache instance. - * - * Available options: - * - * * database: File where to put the cache database (or :memory: to store cache in memory) - * - * * see sfCache for options available for all drivers - * - * @see sfCache - * @inheritdoc - */ - public function initialize($options = array()) - { - if (!extension_loaded('SQLite') && !extension_loaded('pdo_SQLite')) + protected $dbh; + protected $sqlLiteVersion; + protected $database = ''; + + /** + * Initializes this sfCache instance. + * + * Available options: + * + * * database: File where to put the cache database (or :memory: to store cache in memory) + * + * * see sfCache for options available for all drivers + * + * @see sfCache + */ + public function initialize($options = []) { - throw new sfConfigurationException('sfSQLiteCache class needs "sqlite" or "pdo_sqlite" extension to be loaded.'); - } + if (!extension_loaded('SQLite') && !extension_loaded('pdo_SQLite')) { + throw new sfConfigurationException('sfSQLiteCache class needs "sqlite" or "pdo_sqlite" extension to be loaded.'); + } - parent::initialize($options); + parent::initialize($options); - if (!$this->getOption('database')) - { - throw new sfInitializationException('You must pass a "database" option to initialize a sfSQLiteCache object.'); - } + if (!$this->getOption('database')) { + throw new sfInitializationException('You must pass a "database" option to initialize a sfSQLiteCache object.'); + } - $this->setDatabase($this->getOption('database')); - } - - /** - * @see sfCache - * @inheritdo - * @return SQLiteDatabase|SQLite3 - */ - public function getBackend() - { - return $this->dbh; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function get($key, $default = null) - { - if ($this->isSqLite3()) - { - $data = $this->dbh->querySingle(sprintf("SELECT data FROM cache WHERE key = '%s' AND timeout > %d", $this->dbh->escapeString($key), time())); - } - else - { - $data = $this->dbh->singleQuery(sprintf("SELECT data FROM cache WHERE key = '%s' AND timeout > %d", sqlite_escape_string($key), time())); + $this->setDatabase($this->getOption('database')); } - return null === $data ? $default : $data; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function has($key) - { - if ($this->isSqLite3()) + /** + * @see sfCache + * + * @inheritdo + * + * @return SQLite3|SQLiteDatabase + */ + public function getBackend() { - return (integer) $this->dbh->querySingle(sprintf("SELECT count(*) FROM cache WHERE key = '%s' AND timeout > %d", $this->dbh->escapeString($key), time())); + return $this->dbh; } - return (boolean) $this->dbh->query(sprintf("SELECT key FROM cache WHERE key = '%s' AND timeout > %d", sqlite_escape_string($key), time()))->numRows(); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function set($key, $data, $lifetime = null) - { - if ($this->getOption('automatic_cleaning_factor') > 0 && mt_rand(1, $this->getOption('automatic_cleaning_factor')) == 1) + /** + * @see sfCache + * + * @param mixed|null $default + */ + public function get($key, $default = null) { - $this->clean(sfCache::OLD); + if ($this->isSqLite3()) { + $data = $this->dbh->querySingle(sprintf("SELECT data FROM cache WHERE key = '%s' AND timeout > %d", $this->dbh->escapeString($key), time())); + } else { + $data = $this->dbh->singleQuery(sprintf("SELECT data FROM cache WHERE key = '%s' AND timeout > %d", sqlite_escape_string($key), time())); + } + + return null === $data ? $default : $data; } - if ($this->isSqLite3()) + /** + * @see sfCache + */ + public function has($key) { - return $this->dbh->exec(sprintf("INSERT OR REPLACE INTO cache (key, data, timeout, last_modified) VALUES ('%s', '%s', %d, %d)", $this->dbh->escapeString($key), $this->dbh->escapeString($data), time() + $this->getLifetime($lifetime), time())); - } + if ($this->isSqLite3()) { + return (int) $this->dbh->querySingle(sprintf("SELECT count(*) FROM cache WHERE key = '%s' AND timeout > %d", $this->dbh->escapeString($key), time())); + } - return (boolean) $this->dbh->query(sprintf("INSERT OR REPLACE INTO cache (key, data, timeout, last_modified) VALUES ('%s', '%s', %d, %d)", sqlite_escape_string($key), sqlite_escape_string($data), time() + $this->getLifetime($lifetime), time())); - } + return (bool) $this->dbh->query(sprintf("SELECT key FROM cache WHERE key = '%s' AND timeout > %d", sqlite_escape_string($key), time()))->numRows(); + } - /** - * @see sfCache - * @inheritdoc - */ - public function remove($key) - { - if ($this->isSqLite3()) + /** + * @see sfCache + * + * @param mixed|null $lifetime + */ + public function set($key, $data, $lifetime = null) { - return $this->dbh->exec(sprintf("DELETE FROM cache WHERE key = '%s'", $this->dbh->escapeString($key))); - } + if ($this->getOption('automatic_cleaning_factor') > 0 && 1 == mt_rand(1, $this->getOption('automatic_cleaning_factor'))) { + $this->clean(sfCache::OLD); + } - return (boolean) $this->dbh->query(sprintf("DELETE FROM cache WHERE key = '%s'", sqlite_escape_string($key))); - } + if ($this->isSqLite3()) { + return $this->dbh->exec(sprintf("INSERT OR REPLACE INTO cache (key, data, timeout, last_modified) VALUES ('%s', '%s', %d, %d)", $this->dbh->escapeString($key), $this->dbh->escapeString($data), time() + $this->getLifetime($lifetime), time())); + } - /** - * @see sfCache - * @inheritdoc - */ - public function removePattern($pattern) - { - if ($this->isSqLite3()) - { - return $this->dbh->exec(sprintf("DELETE FROM cache WHERE REGEXP('%s', key)", $this->dbh->escapeString(self::patternToRegexp($pattern)))); + return (bool) $this->dbh->query(sprintf("INSERT OR REPLACE INTO cache (key, data, timeout, last_modified) VALUES ('%s', '%s', %d, %d)", sqlite_escape_string($key), sqlite_escape_string($data), time() + $this->getLifetime($lifetime), time())); } - return (boolean) $this->dbh->query(sprintf("DELETE FROM cache WHERE REGEXP('%s', key)", sqlite_escape_string(self::patternToRegexp($pattern)))); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function clean($mode = sfCache::ALL) - { - if ($this->isSqLite3()) + /** + * @see sfCache + */ + public function remove($key) { - $res = $this->dbh->exec("DELETE FROM cache".(sfCache::OLD == $mode ? sprintf(" WHERE timeout < '%s'", time()) : '')); - - if ($res) - { - return (boolean) $this->dbh->changes(); - } + if ($this->isSqLite3()) { + return $this->dbh->exec(sprintf("DELETE FROM cache WHERE key = '%s'", $this->dbh->escapeString($key))); + } - return false; + return (bool) $this->dbh->query(sprintf("DELETE FROM cache WHERE key = '%s'", sqlite_escape_string($key))); } - return (boolean) $this->dbh->query("DELETE FROM cache".(sfCache::OLD == $mode ? sprintf(" WHERE timeout < '%s'", time()) : ''))->numRows(); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function getTimeout($key) - { - if ($this->isSqLite3()) + /** + * @see sfCache + */ + public function removePattern($pattern) { - $rs = $this->dbh->querySingle(sprintf("SELECT timeout FROM cache WHERE key = '%s' AND timeout > %d", $this->dbh->escapeString($key), time())); + if ($this->isSqLite3()) { + return $this->dbh->exec(sprintf("DELETE FROM cache WHERE REGEXP('%s', key)", $this->dbh->escapeString(self::patternToRegexp($pattern)))); + } - return null === $rs ? 0 : $rs; + return (bool) $this->dbh->query(sprintf("DELETE FROM cache WHERE REGEXP('%s', key)", sqlite_escape_string(self::patternToRegexp($pattern)))); } - $rs = $this->dbh->query(sprintf("SELECT timeout FROM cache WHERE key = '%s' AND timeout > %d", sqlite_escape_string($key), time())); + /** + * @see sfCache + */ + public function clean($mode = sfCache::ALL) + { + if ($this->isSqLite3()) { + $res = $this->dbh->exec('DELETE FROM cache'.(sfCache::OLD == $mode ? sprintf(" WHERE timeout < '%s'", time()) : '')); - return $rs->numRows() ? (int) $rs->fetchSingle() : 0; - } + if ($res) { + return (bool) $this->dbh->changes(); + } - /** - * @see sfCache - * @inheritdoc - */ - public function getLastModified($key) - { - if ($this->isSqLite3()) - { - $rs = $this->dbh->querySingle(sprintf("SELECT last_modified FROM cache WHERE key = '%s' AND timeout > %d", $this->dbh->escapeString($key), time())); + return false; + } - return null === $rs ? 0 : $rs; + return (bool) $this->dbh->query('DELETE FROM cache'.(sfCache::OLD == $mode ? sprintf(" WHERE timeout < '%s'", time()) : ''))->numRows(); } - $rs = $this->dbh->query(sprintf("SELECT last_modified FROM cache WHERE key = '%s' AND timeout > %d", sqlite_escape_string($key), time())); + /** + * @see sfCache + */ + public function getTimeout($key) + { + if ($this->isSqLite3()) { + $rs = $this->dbh->querySingle(sprintf("SELECT timeout FROM cache WHERE key = '%s' AND timeout > %d", $this->dbh->escapeString($key), time())); - return $rs->numRows() ? (int) $rs->fetchSingle() : 0; - } + return null === $rs ? 0 : $rs; + } - /** - * Sets the database name. - * - * @param string $database The database name where to store the cache - * - * @throws sfCacheException - */ - protected function setDatabase($database) - { - $this->database = $database; + $rs = $this->dbh->query(sprintf("SELECT timeout FROM cache WHERE key = '%s' AND timeout > %d", sqlite_escape_string($key), time())); - $new = false; - if (':memory:' == $database) - { - $new = true; + return $rs->numRows() ? (int) $rs->fetchSingle() : 0; } - else if (!is_file($database)) + + /** + * @see sfCache + */ + public function getLastModified($key) { - $new = true; - - // create cache dir if needed - $dir = dirname($database); - $current_umask = umask(0000); - if (!is_dir($dir)) - { - @mkdir($dir, 0777, true); - } - - touch($database); - umask($current_umask); + if ($this->isSqLite3()) { + $rs = $this->dbh->querySingle(sprintf("SELECT last_modified FROM cache WHERE key = '%s' AND timeout > %d", $this->dbh->escapeString($key), time())); + + return null === $rs ? 0 : $rs; + } + + $rs = $this->dbh->query(sprintf("SELECT last_modified FROM cache WHERE key = '%s' AND timeout > %d", sqlite_escape_string($key), time())); + + return $rs->numRows() ? (int) $rs->fetchSingle() : 0; } - if ($this->isSqLite3()) + /** + * Callback used when deleting keys from cache. + * + * @param string $regexp + * @param string $key + * + * @return int + */ + public function removePatternRegexpCallback($regexp, $key) { - $this->dbh = new SQLite3($this->database); - if ('not an error' !== $errmsg = $this->dbh->lastErrorMsg()) - { - throw new sfCacheException(sprintf('Unable to connect to SQLite database: %s.', $errmsg)); - } + return preg_match($regexp, $key); } - else + + /** + * @see sfCache + */ + public function getMany($keys) { - if (!$this->dbh = new SQLiteDatabase($this->database, 0644, $errmsg)) - { - throw new sfCacheException(sprintf('Unable to connect to SQLite database: %s.', $errmsg)); - } - } + if ($this->isSqLite3()) { + $data = []; + if ($results = $this->dbh->query(sprintf("SELECT key, data FROM cache WHERE key IN ('%s') AND timeout > %d", implode('\', \'', array_map([$this->dbh, 'escapeString'], $keys)), time()))) { + while ($row = $results->fetchArray()) { + $data[$row['key']] = $row['data']; + } + } + + return $data; + } - $this->dbh->createFunction('regexp', array($this, 'removePatternRegexpCallback'), 2); + $rows = $this->dbh->arrayQuery(sprintf("SELECT key, data FROM cache WHERE key IN ('%s') AND timeout > %d", implode('\', \'', array_map('sqlite_escape_string', $keys)), time())); - if ($new) - { - $this->createSchema(); + $data = []; + foreach ($rows as $row) { + $data[$row['key']] = $row['data']; + } + + return $data; } - } - - /** - * Callback used when deleting keys from cache. - * @param string $regexp - * @param string $key - * @return int - */ - public function removePatternRegexpCallback($regexp, $key) - { - return preg_match($regexp, $key); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function getMany($keys) - { - if ($this->isSqLite3()) + + /** + * Sets the database name. + * + * @param string $database The database name where to store the cache + * + * @throws sfCacheException + */ + protected function setDatabase($database) { - $data = array(); - if ($results = $this->dbh->query(sprintf("SELECT key, data FROM cache WHERE key IN ('%s') AND timeout > %d", implode('\', \'', array_map(array($this->dbh, 'escapeString'), $keys)), time()))) - { - while ($row = $results->fetchArray()) - { - $data[$row['key']] = $row['data']; + $this->database = $database; + + $new = false; + if (':memory:' == $database) { + $new = true; + } elseif (!is_file($database)) { + $new = true; + + // create cache dir if needed + $dir = dirname($database); + $current_umask = umask(0000); + if (!is_dir($dir)) { + @mkdir($dir, 0777, true); + } + + touch($database); + umask($current_umask); } - } - return $data; - } + if ($this->isSqLite3()) { + $this->dbh = new SQLite3($this->database); + if ('not an error' !== $errmsg = $this->dbh->lastErrorMsg()) { + throw new sfCacheException(sprintf('Unable to connect to SQLite database: %s.', $errmsg)); + } + } else { + if (!$this->dbh = new SQLiteDatabase($this->database, 0644, $errmsg)) { + throw new sfCacheException(sprintf('Unable to connect to SQLite database: %s.', $errmsg)); + } + } - $rows = $this->dbh->arrayQuery(sprintf("SELECT key, data FROM cache WHERE key IN ('%s') AND timeout > %d", implode('\', \'', array_map('sqlite_escape_string', $keys)), time())); + $this->dbh->createFunction('regexp', [$this, 'removePatternRegexpCallback'], 2); - $data = array(); - foreach ($rows as $row) - { - $data[$row['key']] = $row['data']; + if ($new) { + $this->createSchema(); + } } - return $data; - } - - /** - * Creates the database schema. - * - * @throws sfCacheException - */ - protected function createSchema() - { - $statements = array( - 'CREATE TABLE [cache] ( + /** + * Creates the database schema. + * + * @throws sfCacheException + */ + protected function createSchema() + { + $statements = [ + 'CREATE TABLE [cache] ( [key] VARCHAR(255), [data] LONGVARCHAR, [timeout] TIMESTAMP, [last_modified] TIMESTAMP )', - 'CREATE UNIQUE INDEX [cache_unique] ON [cache] ([key])', - ); + 'CREATE UNIQUE INDEX [cache_unique] ON [cache] ([key])', + ]; - foreach ($statements as $statement) - { - if (false === $this->dbh->query($statement)) - { - $message = $this->isSqLite3() ? $this->dbh->lastErrorMsg() : sqlite_error_string($this->dbh->lastError()); + foreach ($statements as $statement) { + if (false === $this->dbh->query($statement)) { + $message = $this->isSqLite3() ? $this->dbh->lastErrorMsg() : sqlite_error_string($this->dbh->lastError()); - throw new sfCacheException($message); - } + throw new sfCacheException($message); + } + } } - } - - /** - * Checks if sqlite is version 3 - * - * @return boolean - */ - protected function isSqLite3() - { - return 3 === $this->getSqLiteVersion(); - } - - /** - * Get sqlite version number - * - * @return integer - */ - protected function getSqLiteVersion() - { - if (null === $this->sqlLiteVersion) + + /** + * Checks if sqlite is version 3. + * + * @return bool + */ + protected function isSqLite3() { - $this->sqlLiteVersion = version_compare(PHP_VERSION, '5.3', '>') ? 3 : 2; + return 3 === $this->getSqLiteVersion(); } - return $this->sqlLiteVersion; - } + /** + * Get sqlite version number. + * + * @return int + */ + protected function getSqLiteVersion() + { + if (null === $this->sqlLiteVersion) { + $this->sqlLiteVersion = 3; + } + + return $this->sqlLiteVersion; + } } diff --git a/lib/cache/sfXCacheCache.class.php b/lib/cache/sfXCacheCache.class.php deleted file mode 100644 index 5d2642270..000000000 --- a/lib/cache/sfXCacheCache.class.php +++ /dev/null @@ -1,229 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Cache class that stores cached content in XCache. - * - * @package symfony - * @subpackage cache - * @author Fabien Potencier - * @version SVN: $Id$ - */ -class sfXCacheCache extends sfCache -{ - /** - * Initializes this sfCache instance. - * - * Available options: - * - * * see sfCache for options available for all drivers - * - * @see sfCache - * @inheritdoc - */ - public function initialize($options = array()) - { - parent::initialize($options); - - if (!function_exists('xcache_set')) - { - throw new sfInitializationException('You must have XCache installed and enabled to use sfXCacheCache class.'); - } - - if (!ini_get('xcache.var_size')) - { - throw new sfInitializationException('You must set the "xcache.var_size" variable to a value greater than 0 to use sfXCacheCache class.'); - } - } - - /** - * @see sfCache - * @inheritdoc - */ - public function get($key, $default = null) - { - - $set = $this->getBaseValue($key); - - if (!is_array($set) || !array_key_exists('data', $set)) - { - - return $default; - } - - return $set['data']; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function has($key) - { - return xcache_isset($this->getOption('prefix').$key); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function set($key, $data, $lifetime = null) - { - $lifetime = $this->getLifetime($lifetime); - - $set = array( - 'timeout' => time() + $lifetime, - 'data' => $data, - 'ctime' => time() - ); - - return xcache_set($this->getOption('prefix').$key, $set, $lifetime); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function remove($key) - { - return xcache_unset($this->getOption('prefix').$key); - } - - /** - * @see sfCache - * @inheritdoc - */ - public function clean($mode = sfCache::ALL) - { - if ($mode !== sfCache::ALL) - { - return true; - } - - $this->checkAuth(); - - for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++) - { - if (false === xcache_clear_cache(XC_TYPE_VAR, $i)) - { - return false; - } - } - - return true; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function getLastModified($key) - { - $set = $this->getBaseValue($key); - - if (!is_array($set) || !array_key_exists('ctime', $set)) - { - - return 0; - } - - return $set['ctime']; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function getTimeout($key) - { - - $set = $this->getBaseValue($key); - - if (!is_array($set) || !array_key_exists('timeout', $set)) - { - - return 0; - } - - return $set['timeout']; - } - - /** - * @param string $key - * @return mixed|null - */ - public function getBaseValue($key) - { - return xcache_isset($this->getOption('prefix').$key) ? xcache_get($this->getOption('prefix').$key) : null; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function removePattern($pattern) - { - $this->checkAuth(); - - $regexp = self::patternToRegexp($this->getOption('prefix').$pattern); - - for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++) - { - $infos = xcache_list(XC_TYPE_VAR, $i); - if (!is_array($infos['cache_list'])) - { - return; - } - - foreach ($infos['cache_list'] as $info) - { - if (preg_match($regexp, $info['name'])) - { - xcache_unset($info['name']); - } - } - } - } - - /** - * @param string $key - * @return array|null - */ - public function getCacheInfo($key) - { - $this->checkAuth(); - - for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++) - { - $infos = xcache_list(XC_TYPE_VAR, $i); - - if (is_array($infos['cache_list'])) - { - foreach ($infos['cache_list'] as $info) - { - if ($this->getOption('prefix').$key == $info['name']) - { - return $info; - } - } - } - } - - return null; - } - - protected function checkAuth() - { - if (ini_get('xcache.admin.enable_auth')) - { - throw new sfConfigurationException('To use all features of the "sfXCacheCache" class, you must set "xcache.admin.enable_auth" to "Off" in your php.ini.'); - } - } -} diff --git a/lib/command/cli.php b/lib/command/cli.php index 37a4f635d..e5f6904e9 100644 --- a/lib/command/cli.php +++ b/lib/command/cli.php @@ -9,41 +9,33 @@ */ // Try autoloading using composer if available. -if (!file_exists($autoload = __DIR__.'/../../../../autoload.php')) -{ - $autoload = __DIR__.'/../../autoload.php'; +if (!file_exists($autoload = __DIR__.'/../../../../autoload.php')) { + $autoload = __DIR__.'/../../autoload.php'; } // Fall back to classic Symfony loading -if (!file_exists($autoload)) -{ - require_once(__DIR__.'/../autoload/sfCoreAutoload.class.php'); - sfCoreAutoload::register(); -} -else -{ - require_once $autoload; +if (!file_exists($autoload)) { + require_once __DIR__.'/../autoload/sfCoreAutoload.class.php'; + sfCoreAutoload::register(); +} else { + require_once $autoload; } -try -{ - $dispatcher = new sfEventDispatcher(); - $logger = new sfCommandLogger($dispatcher); +try { + $dispatcher = new sfEventDispatcher(); + $logger = new sfCommandLogger($dispatcher); - $application = new sfSymfonyCommandApplication($dispatcher, null, array('symfony_lib_dir' => realpath(__DIR__.'/..'))); - $statusCode = $application->run(); -} -catch (Exception $e) -{ - if (!isset($application)) - { - throw $e; - } + $application = new sfSymfonyCommandApplication($dispatcher, null, ['symfony_lib_dir' => realpath(__DIR__.'/..')]); + $statusCode = $application->run(); +} catch (Exception $e) { + if (!isset($application)) { + throw $e; + } - $application->renderException($e); - $statusCode = $e->getCode(); + $application->renderException($e); + $statusCode = $e->getCode(); - exit(is_numeric($statusCode) && $statusCode ? $statusCode : 1); + exit(is_numeric($statusCode) && $statusCode ? $statusCode : 1); } exit(is_numeric($statusCode) ? $statusCode : 0); diff --git a/lib/command/sfAnsiColorFormatter.class.php b/lib/command/sfAnsiColorFormatter.class.php index 904da78b2..6bb298b84 100644 --- a/lib/command/sfAnsiColorFormatter.class.php +++ b/lib/command/sfAnsiColorFormatter.class.php @@ -11,120 +11,107 @@ /** * sfAnsiColorFormatter provides methods to colorize text to be displayed on a console. * - * @package symfony - * @subpackage command * @author Fabien Potencier - * @version SVN: $Id$ */ class sfAnsiColorFormatter extends sfFormatter { - protected - $styles = array( - 'ERROR' => array('bg' => 'red', 'fg' => 'white', 'bold' => true), - 'INFO' => array('fg' => 'green', 'bold' => true), - 'COMMENT' => array('fg' => 'yellow'), - 'QUESTION' => array('bg' => 'cyan', 'fg' => 'black', 'bold' => false), - ), - $options = array('bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8), - $foreground = array('black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37), - $background = array('black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47); + protected $styles = [ + 'ERROR' => ['bg' => 'red', 'fg' => 'white', 'bold' => true], + 'INFO' => ['fg' => 'green', 'bold' => true], + 'COMMENT' => ['fg' => 'yellow'], + 'QUESTION' => ['bg' => 'cyan', 'fg' => 'black', 'bold' => false], + ]; + protected $options = ['bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8]; + protected $foreground = ['black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37]; + protected $background = ['black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47]; - /** - * Sets a new style. - * - * @param string $name The style name - * @param array $options An array of options - */ - public function setStyle($name, $options = array()) - { - $this->styles[$name] = $options; - } - - /** - * Formats a text according to the given style or parameters. - * - * @param string $text The test to style - * @param mixed $parameters An array of options or a style name - * - * @return string The styled text - */ - public function format($text = '', $parameters = array()) - { - if (!is_array($parameters) && 'NONE' == $parameters) + /** + * Sets a new style. + * + * @param string $name The style name + * @param array $options An array of options + */ + public function setStyle($name, $options = []) { - return $text; + $this->styles[$name] = $options; } - if (!is_array($parameters) && isset($this->styles[$parameters])) + /** + * Formats a text according to the given style or parameters. + * + * @param string $text The test to style + * @param mixed $parameters An array of options or a style name + * + * @return string The styled text + */ + public function format($text = '', $parameters = []) { - $parameters = $this->styles[$parameters]; - } + if (!is_array($parameters) && 'NONE' == $parameters) { + return $text; + } - $codes = array(); - if (isset($parameters['fg'])) - { - $codes[] = $this->foreground[$parameters['fg']]; - } - if (isset($parameters['bg'])) - { - $codes[] = $this->background[$parameters['bg']]; - } - foreach ($this->options as $option => $value) - { - if (isset($parameters[$option]) && $parameters[$option]) - { - $codes[] = $value; - } - } + if (!is_array($parameters) && isset($this->styles[$parameters])) { + $parameters = $this->styles[$parameters]; + } - return "\033[".implode(';', $codes).'m'.$text."\033[0m"; - } - - /** - * Formats a message within a section. - * - * @param string $section The section name - * @param string $text The text message - * @param integer $size The maximum size allowed for a line - * @param string $style The color scheme to apply to the section string (INFO, ERROR, COMMENT or QUESTION) - * - * @return string - */ - public function formatSection($section, $text, $size = null, $style = 'INFO') - { - if (null === $size) - { - $size = $this->size; + $codes = []; + if (isset($parameters['fg'])) { + $codes[] = $this->foreground[$parameters['fg']]; + } + if (isset($parameters['bg'])) { + $codes[] = $this->background[$parameters['bg']]; + } + foreach ($this->options as $option => $value) { + if (isset($parameters[$option]) && $parameters[$option]) { + $codes[] = $value; + } + } + + return "\033[".implode(';', $codes).'m'.$text."\033[0m"; } - $style = array_key_exists($style, $this->styles) ? $style : 'INFO'; - $width = 9 + strlen($this->format('', $style)); + /** + * Formats a message within a section. + * + * @param string $section The section name + * @param string $text The text message + * @param int $size The maximum size allowed for a line + * @param string $style The color scheme to apply to the section string (INFO, ERROR, COMMENT or QUESTION) + * + * @return string + */ + public function formatSection($section, $text, $size = null, $style = 'INFO') + { + if (null === $size) { + $size = $this->size; + } - return sprintf(">> %-${width}s %s", $this->format($section, $style), $this->excerpt($text, $size - 4 - (strlen($section) > 9 ? strlen($section) : 9))); - } + $style = array_key_exists($style, $this->styles) ? $style : 'INFO'; + $width = 9 + strlen($this->format('', $style)); - /** - * Truncates a line. - * - * @param string $text The text - * @param integer $size The maximum size of the returned string - * - * @return string The truncated string - */ - public function excerpt($text, $size = null) - { - if (!$size) - { - $size = $this->size; + return sprintf(">> %-{$width}s %s", $this->format($section, $style), $this->excerpt($text, $size - 4 - (strlen($section) > 9 ? strlen($section) : 9))); } - if (strlen($text) < $size) + /** + * Truncates a line. + * + * @param string $text The text + * @param int $size The maximum size of the returned string + * + * @return string The truncated string + */ + public function excerpt($text, $size = null) { - return $text; - } + if (!$size) { + $size = $this->size; + } + + if (strlen($text) < $size) { + return $text; + } - $subsize = floor(($size - 3) / 2); + $subsize = floor(($size - 3) / 2); - return substr($text, 0, $subsize).$this->format('...', 'INFO').substr($text, -$subsize); - } + return substr($text, 0, $subsize).$this->format('...', 'INFO').substr($text, -$subsize); + } } diff --git a/lib/command/sfCommandApplication.class.php b/lib/command/sfCommandApplication.class.php index 39878e3e8..0135428b3 100644 --- a/lib/command/sfCommandApplication.class.php +++ b/lib/command/sfCommandApplication.class.php @@ -11,702 +11,654 @@ /** * sfCommandApplication manages the lifecycle of a CLI application. * - * @package symfony - * @subpackage command * @author Fabien Potencier - * @version SVN: $Id$ */ abstract class sfCommandApplication { - /** @var sfCommandManager */ - protected $commandManager = null; - /** @var bool */ - protected $trace = false; - /** @var bool */ - protected $verbose = true; - /** @var bool */ - protected $debug = true; - /** @var bool */ - protected $nowrite = false; - /** @var string */ - protected $name = 'UNKNOWN'; - /** @var string */ - protected $version = 'UNKNOWN'; - /** @var array */ - protected $tasks = array(); - /** @var sfTask */ - protected $currentTask = null; - /** @var sfEventDispatcher */ - protected $dispatcher = null; - /** @var array */ - protected $options = array(); - /** @var sfFormatter */ - protected $formatter = null; - /** @var mixed */ - protected $commandOptions; - /** - * Constructor. - * - * @param sfEventDispatcher $dispatcher A sfEventDispatcher instance - * @param sfFormatter $formatter A sfFormatter instance - * @param array $options An array of options - */ - public function __construct(sfEventDispatcher $dispatcher, sfFormatter $formatter = null, $options = array()) - { - $this->dispatcher = $dispatcher; - $this->formatter = null === $formatter ? $this->guessBestFormatter(STDOUT) : $formatter; - $this->options = $options; - - $this->fixCgi(); - - $argumentSet = new sfCommandArgumentSet(array( - new sfCommandArgument('task', sfCommandArgument::REQUIRED, 'The task to execute'), - )); - $optionSet = new sfCommandOptionSet(array( - new sfCommandOption('--help', '-H', sfCommandOption::PARAMETER_NONE, 'Display this help message.'), - new sfCommandOption('--quiet', '-q', sfCommandOption::PARAMETER_NONE, 'Do not log messages to standard output.'), - new sfCommandOption('--trace', '-t', sfCommandOption::PARAMETER_NONE, 'Turn on invoke/execute tracing, enable full backtrace.'), - new sfCommandOption('--version', '-V', sfCommandOption::PARAMETER_NONE, 'Display the program version.'), - new sfCommandOption('--color', '', sfCommandOption::PARAMETER_NONE, 'Forces ANSI color output.'), - new sfCommandOption('--no-color','', sfCommandOption::PARAMETER_NONE, 'Restricts output from including color, even when possible'), - new sfCommandOption('--no-debug','', sfCommandOption::PARAMETER_NONE, 'Disable debug'), - )); - $this->commandManager = new sfCommandManager($argumentSet, $optionSet); - - $this->configure(); - - $this->registerTasks(); - } - - /** - * Configures the current command application. - */ - abstract public function configure(); - - /** - * Returns the value of a given option. - * - * @param string $name The option name - * - * @return mixed The option value - */ - public function getOption($name) - { - return isset($this->options[$name]) ? $this->options[$name] : null; - } - - /** - * Returns the formatter instance. - * - * @return sfFormatter The formatter instance - */ - public function getFormatter() - { - return $this->formatter; - } - - /** - * Sets the formatter instance. - * - * @param sfFormatter $formatter The formatter instance - */ - public function setFormatter(sfFormatter $formatter) - { - $this->formatter = $formatter; - - foreach ($this->getTasks() as $task) - { - $task->setFormatter($formatter); - } - } - - public function clearTasks() - { - $this->tasks = array(); - } - - /** - * Registers an array of task objects. - * - * If you pass null, this method will register all available tasks. - * - * @param array $tasks An array of tasks - */ - public function registerTasks($tasks = null) - { - if (null === $tasks) - { - $tasks = $this->autodiscoverTasks(); - } + /** @var sfCommandManager */ + protected $commandManager; - foreach ($tasks as $task) - { - $this->registerTask($task); - } - } - - /** - * Registers a task object. - * - * @param sfTask $task An sfTask object - * - * @throws sfCommandException - */ - public function registerTask(sfTask $task) - { - if (isset($this->tasks[$task->getFullName()])) - { - throw new sfCommandException(sprintf('The task named "%s" in "%s" task is already registered by the "%s" task.', $task->getFullName(), get_class($task), get_class($this->tasks[$task->getFullName()]))); - } + /** @var bool */ + protected $trace = false; - $this->tasks[$task->getFullName()] = $task; + /** @var bool */ + protected $verbose = true; - foreach ($task->getAliases() as $alias) - { - if (isset($this->tasks[$alias])) - { - throw new sfCommandException(sprintf('A task named "%s" is already registered.', $alias)); - } + /** @var bool */ + protected $debug = true; - $this->tasks[$alias] = $task; - } - } - - /** - * Autodiscovers task classes. - * - * @return array An array of tasks instances - */ - public function autodiscoverTasks() - { - $tasks = array(); - foreach (get_declared_classes() as $class) + /** @var bool */ + protected $nowrite = false; + + /** @var string */ + protected $name = 'UNKNOWN'; + + /** @var string */ + protected $version = 'UNKNOWN'; + + /** @var array */ + protected $tasks = []; + + /** @var sfTask */ + protected $currentTask; + + /** @var sfEventDispatcher */ + protected $dispatcher; + + /** @var array */ + protected $options = []; + + /** @var sfFormatter */ + protected $formatter; + + protected $commandOptions; + + /** + * Constructor. + * + * @param sfEventDispatcher $dispatcher A sfEventDispatcher instance + * @param sfFormatter $formatter A sfFormatter instance + * @param array $options An array of options + */ + public function __construct(sfEventDispatcher $dispatcher, ?sfFormatter $formatter = null, $options = []) { - $r = new ReflectionClass($class); + $this->dispatcher = $dispatcher; + $this->formatter = null === $formatter ? $this->guessBestFormatter(STDOUT) : $formatter; + $this->options = $options; + + $this->fixCgi(); + + $argumentSet = new sfCommandArgumentSet([ + new sfCommandArgument('task', sfCommandArgument::REQUIRED, 'The task to execute'), + ]); + $optionSet = new sfCommandOptionSet([ + new sfCommandOption('--help', '-H', sfCommandOption::PARAMETER_NONE, 'Display this help message.'), + new sfCommandOption('--quiet', '-q', sfCommandOption::PARAMETER_NONE, 'Do not log messages to standard output.'), + new sfCommandOption('--trace', '-t', sfCommandOption::PARAMETER_NONE, 'Turn on invoke/execute tracing, enable full backtrace.'), + new sfCommandOption('--version', '-V', sfCommandOption::PARAMETER_NONE, 'Display the program version.'), + new sfCommandOption('--color', '', sfCommandOption::PARAMETER_NONE, 'Forces ANSI color output.'), + new sfCommandOption('--no-color', '', sfCommandOption::PARAMETER_NONE, 'Restricts output from including color, even when possible'), + new sfCommandOption('--no-debug', '', sfCommandOption::PARAMETER_NONE, 'Disable debug'), + ]); + $this->commandManager = new sfCommandManager($argumentSet, $optionSet); - if ($r->isSubclassOf('sfTask') && !$r->isAbstract()) - { - $tasks[] = new $class($this->dispatcher, $this->formatter); - } + $this->configure(); + + $this->registerTasks(); } - return $tasks; - } - - /** - * Returns all registered tasks. - * - * @return array An array of sfTask objects - */ - public function getTasks() - { - return $this->tasks; - } - - /** - * Returns a registered task by name or alias. - * - * @param string $name The task name or alias - * - * @return sfTask An sfTask object - * - * @throws sfCommandException - */ - public function getTask($name) - { - if (!isset($this->tasks[$name])) + /** + * Configures the current command application. + */ + abstract public function configure(); + + /** + * Returns the value of a given option. + * + * @param string $name The option name + * + * @return mixed The option value + */ + public function getOption($name) { - throw new sfCommandException(sprintf('The task "%s" does not exist.', $name)); + return isset($this->options[$name]) ? $this->options[$name] : null; } - return $this->tasks[$name]; - } - - /** - * Runs the current application. - * - * @param mixed $options The command line options - * - * @return integer 0 if everything went fine, or an error code - */ - public function run($options = null) - { - $this->handleOptions($options); - $arguments = $this->commandManager->getArgumentValues(); - - $this->currentTask = $this->getTaskToExecute($arguments['task']); - - $ret = $this->currentTask->runFromCLI($this->commandManager, $this->commandOptions); - - $this->currentTask = null; - - return $ret; - } - - /** - * Gets the name of the application. - * - * @return string The application name - */ - public function getName() - { - return $this->name; - } - - /** - * Sets the application name. - * - * @param string $name The application name - */ - public function setName($name) - { - $this->name = $name; - } - - /** - * Gets the application version. - * - * @return string The application version - */ - public function getVersion() - { - return $this->version; - } - - /** - * Sets the application version. - * - * @param string $version The application version - */ - public function setVersion($version) - { - $this->version = $version; - } - - /** - * Returns the long version of the application. - * - * @return string The long application version - */ - public function getLongVersion() - { - return sprintf('%s version %s', $this->getName(), $this->formatter->format($this->getVersion(), 'INFO'))."\n"; - } - - /** - * Returns whether the application must be verbose. - * - * @return Boolean true if the application must be verbose, false otherwise - */ - public function isVerbose() - { - return $this->verbose; - } - - /** - * Returns whether the application must activate the trace. - * - * @return Boolean true if the application must activate the trace, false otherwise - */ - public function withTrace() - { - return $this->trace; - } - - /** - * Returns whether the application must be verbose. - * - * @return Boolean true if the application is in debug mode, false otherwise - */ - public function isDebug() - { - return $this->debug; - } - - /** - * Outputs a help message for the current application. - */ - public function help() - { - $messages = array( - $this->formatter->format('Usage:', 'COMMENT'), - sprintf(" %s [options] task_name [arguments]\n", $this->getName()), - $this->formatter->format('Options:', 'COMMENT'), - ); - - foreach ($this->commandManager->getOptionSet()->getOptions() as $option) + /** + * Returns the formatter instance. + * + * @return sfFormatter The formatter instance + */ + public function getFormatter() { - $messages[] = sprintf(' %-24s %s %s', - $this->formatter->format('--'.$option->getName(), 'INFO'), - $option->getShortcut() ? $this->formatter->format('-'.$option->getShortcut(), 'INFO') : ' ', - $option->getHelp() - ); + return $this->formatter; } - $this->dispatcher->notify(new sfEvent($this, 'command.log', $messages)); - } - - /** - * Parses and handles command line options. - * - * @param mixed $options The command line options - */ - protected function handleOptions($options = null) - { - $this->commandManager->process($options); - $this->commandOptions = $options; - - // the order of option processing matters - if( $this->commandManager->getOptionSet()->hasOption('no-color') && false !== $this->commandManager->getOptionValue('no-color') ) + /** + * Sets the formatter instance. + * + * @param sfFormatter $formatter The formatter instance + */ + public function setFormatter(sfFormatter $formatter) { - $this->setFormatter(new sfFormatter()); + $this->formatter = $formatter; + + foreach ($this->getTasks() as $task) { + $task->setFormatter($formatter); + } } - elseif ($this->commandManager->getOptionSet()->hasOption('color') && false !== $this->commandManager->getOptionValue('color')) + + public function clearTasks() { - $this->setFormatter(new sfAnsiColorFormatter()); + $this->tasks = []; } - if ($this->commandManager->getOptionSet()->hasOption('quiet') && false !== $this->commandManager->getOptionValue('quiet')) + /** + * Registers an array of task objects. + * + * If you pass null, this method will register all available tasks. + * + * @param array $tasks An array of tasks + */ + public function registerTasks($tasks = null) { - $this->verbose = false; + if (null === $tasks) { + $tasks = $this->autodiscoverTasks(); + } + + foreach ($tasks as $task) { + $this->registerTask($task); + } } - if ($this->commandManager->getOptionSet()->hasOption('no-debug') && false !== $this->commandManager->getOptionValue('no-debug')) + /** + * Registers a task object. + * + * @param sfTask $task An sfTask object + * + * @throws sfCommandException + */ + public function registerTask(sfTask $task) { - $this->debug = false; + if (isset($this->tasks[$task->getFullName()])) { + throw new sfCommandException(sprintf('The task named "%s" in "%s" task is already registered by the "%s" task.', $task->getFullName(), get_class($task), get_class($this->tasks[$task->getFullName()]))); + } + + $this->tasks[$task->getFullName()] = $task; + + foreach ($task->getAliases() as $alias) { + if (isset($this->tasks[$alias])) { + throw new sfCommandException(sprintf('A task named "%s" is already registered.', $alias)); + } + + $this->tasks[$alias] = $task; + } } - if ($this->commandManager->getOptionSet()->hasOption('trace') && false !== $this->commandManager->getOptionValue('trace')) + /** + * Autodiscovers task classes. + * + * @return array An array of tasks instances + */ + public function autodiscoverTasks() { - $this->verbose = true; - $this->trace = true; + $tasks = []; + foreach (get_declared_classes() as $class) { + $r = new ReflectionClass($class); + + if ($r->isSubclassOf('sfTask') && !$r->isAbstract()) { + $tasks[] = new $class($this->dispatcher, $this->formatter); + } + } + + return $tasks; } - if ($this->commandManager->getOptionSet()->hasOption('help') && false !== $this->commandManager->getOptionValue('help')) + /** + * Returns all registered tasks. + * + * @return array An array of sfTask objects + */ + public function getTasks() { - $this->help(); - exit(0); + return $this->tasks; } - if ($this->commandManager->getOptionSet()->hasOption('version') && false !== $this->commandManager->getOptionValue('version')) + /** + * Returns a registered task by name or alias. + * + * @param string $name The task name or alias + * + * @return sfTask An sfTask object + * + * @throws sfCommandException + */ + public function getTask($name) { - echo $this->getLongVersion(); - exit(0); + if (!isset($this->tasks[$name])) { + throw new sfCommandException(sprintf('The task "%s" does not exist.', $name)); + } + + return $this->tasks[$name]; } - } - - /** - * Renders an exception. - * - * @param Exception $e An exception object - */ - public function renderException($e) - { - $title = sprintf(' [%s] ', get_class($e)); - $len = $this->strlen($title); - $lines = array(); - foreach (explode("\n", $e->getMessage()) as $line) + + /** + * Runs the current application. + * + * @param mixed $options The command line options + * + * @return int 0 if everything went fine, or an error code + */ + public function run($options = null) { - $lines[] = sprintf(' %s ', $line); - $len = max($this->strlen($line) + 4, $len); - } + $this->handleOptions($options); + $arguments = $this->commandManager->getArgumentValues(); - $messages = array(str_repeat(' ', $len)); + $this->currentTask = $this->getTaskToExecute($arguments['task']); - if ($this->trace) - { - $messages[] = $title.str_repeat(' ', $len - $this->strlen($title)); + $ret = $this->currentTask->runFromCLI($this->commandManager, $this->commandOptions); + + $this->currentTask = null; + + return $ret; } - foreach ($lines as $line) + /** + * Gets the name of the application. + * + * @return string The application name + */ + public function getName() { - $messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); + return $this->name; } - $messages[] = str_repeat(' ', $len); - - fwrite(STDERR, "\n"); - foreach ($messages as $message) + /** + * Sets the application name. + * + * @param string $name The application name + */ + public function setName($name) { - fwrite(STDERR, $this->formatter->format($message, 'ERROR', STDERR)."\n"); + $this->name = $name; } - fwrite(STDERR, "\n"); - if (null !== $this->currentTask && $e instanceof sfCommandArgumentsException) + /** + * Gets the application version. + * + * @return string The application version + */ + public function getVersion() { - fwrite(STDERR, $this->formatter->format(sprintf($this->currentTask->getSynopsis(), $this->getName()), 'INFO', STDERR)."\n"); - fwrite(STDERR, "\n"); + return $this->version; } - if ($this->trace) + /** + * Sets the application version. + * + * @param string $version The application version + */ + public function setVersion($version) { - fwrite(STDERR, $this->formatter->format("Exception trace:\n", 'COMMENT')); - - // exception related properties - $trace = $e->getTrace(); - array_unshift($trace, array( - 'function' => '', - 'file' => $e->getFile() != null ? $e->getFile() : 'n/a', - 'line' => $e->getLine() != null ? $e->getLine() : 'n/a', - 'args' => array(), - )); - - for ($i = 0, $count = count($trace); $i < $count; $i++) - { - $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; - $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; - $function = $trace[$i]['function']; - $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; - $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; - - fwrite(STDERR, sprintf(" %s%s%s at %s:%s\n", $class, $type, $function, $this->formatter->format($file, 'INFO', STDERR), $this->formatter->format($line, 'INFO', STDERR))); - } - - fwrite(STDERR, "\n"); + $this->version = $version; } - $this->dispatcher->notify(new sfEvent($e, 'application.throw_exception')); - } - - /** - * Gets a task from a task name or a shortcut. - * - * @param string $name The task name or a task shortcut - * - * @return sfTask A sfTask object - * - * @throws sfCommandException - */ - public function getTaskToExecute($name) - { - // namespace - if (false !== $pos = strpos($name, ':')) + /** + * Returns the long version of the application. + * + * @return string The long application version + */ + public function getLongVersion() { - $namespace = substr($name, 0, $pos); - $name = substr($name, $pos + 1); - - $namespaces = array(); - foreach ($this->tasks as $task) - { - if ($task->getNamespace() && !in_array($task->getNamespace(), $namespaces)) - { - $namespaces[] = $task->getNamespace(); - } - } - $abbrev = $this->getAbbreviations($namespaces); - - if (!isset($abbrev[$namespace])) - { - throw new sfCommandException(sprintf('There are no tasks defined in the "%s" namespace.', $namespace)); - } - else if (count($abbrev[$namespace]) > 1) - { - throw new sfCommandException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, implode(', ', $abbrev[$namespace]))); - } - else - { - $namespace = $abbrev[$namespace][0]; - } + return sprintf('%s version %s', $this->getName(), $this->formatter->format($this->getVersion(), 'INFO'))."\n"; } - else + + /** + * Returns whether the application must be verbose. + * + * @return bool true if the application must be verbose, false otherwise + */ + public function isVerbose() { - $namespace = ''; + return $this->verbose; } - // name - $tasks = array(); - foreach ($this->tasks as $taskName => $task) + /** + * Returns whether the application must activate the trace. + * + * @return bool true if the application must activate the trace, false otherwise + */ + public function withTrace() { - if ($taskName == $task->getFullName() && $task->getNamespace() == $namespace) - { - $tasks[] = $task->getName(); - } + return $this->trace; } - $abbrev = $this->getAbbreviations($tasks); - if (isset($abbrev[$name]) && count($abbrev[$name]) == 1) + /** + * Returns whether the application must be verbose. + * + * @return bool true if the application is in debug mode, false otherwise + */ + public function isDebug() { - return $this->getTask($namespace ? $namespace.':'.$abbrev[$name][0] : $abbrev[$name][0]); + return $this->debug; } - // aliases - $aliases = array(); - foreach ($this->tasks as $taskName => $task) + /** + * Outputs a help message for the current application. + */ + public function help() { - if ($taskName == $task->getFullName()) - { - foreach ($task->getAliases() as $alias) - { - $aliases[] = $alias; + $messages = [ + $this->formatter->format('Usage:', 'COMMENT'), + sprintf(" %s [options] task_name [arguments]\n", $this->getName()), + $this->formatter->format('Options:', 'COMMENT'), + ]; + + foreach ($this->commandManager->getOptionSet()->getOptions() as $option) { + $messages[] = sprintf( + ' %-24s %s %s', + $this->formatter->format('--'.$option->getName(), 'INFO'), + $option->getShortcut() ? $this->formatter->format('-'.$option->getShortcut(), 'INFO') : ' ', + $option->getHelp() + ); } - } - } - $abbrev = $this->getAbbreviations($aliases); - $fullName = $namespace ? $namespace.':'.$name : $name; - if (!isset($abbrev[$fullName])) - { - throw new sfCommandException(sprintf('Task "%s" is not defined.', $fullName)); + $this->dispatcher->notify(new sfEvent($this, 'command.log', $messages)); } - else if (count($abbrev[$fullName]) > 1) - { - throw new sfCommandException(sprintf('Task "%s" is ambiguous (%s).', $fullName, implode(', ', $abbrev[$fullName]))); - } - else + + /** + * Renders an exception. + * + * @param Exception $e An exception object + */ + public function renderException($e) { - return $this->getTask($abbrev[$fullName][0]); - } - } + $title = sprintf(' [%s] ', get_class($e)); + $len = $this->strlen($title); + $lines = []; + foreach (explode("\n", $e->getMessage()) as $line) { + $lines[] = sprintf(' %s ', $line); + $len = max($this->strlen($line) + 4, $len); + } - protected function strlen($string) - { - if (!function_exists('mb_strlen')) { - return strlen($string); - } + $messages = [str_repeat(' ', $len)]; - if (false === $encoding = mb_detect_encoding($string)) { - return strlen($string); - } + if ($this->trace) { + $messages[] = $title.str_repeat(' ', $len - $this->strlen($title)); + } - return mb_strlen($string, $encoding); - } - - /** - * Fixes php behavior if using cgi php. - * - * @see http://www.sitepoint.com/article/php-command-line-1/3 - */ - protected function fixCgi() - { - // handle output buffering - if (ob_get_level() > 0) - { - @ob_end_flush(); - } + foreach ($lines as $line) { + $messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); + } - ob_implicit_flush(true); + $messages[] = str_repeat(' ', $len); - // PHP ini settings - set_time_limit(0); - ini_set('track_errors', true); - ini_set('html_errors', false); - ini_set('magic_quotes_runtime', false); + fwrite(STDERR, "\n"); + foreach ($messages as $message) { + fwrite(STDERR, $this->formatter->format($message, 'ERROR', STDERR)."\n"); + } + fwrite(STDERR, "\n"); - if (false === strpos(PHP_SAPI, 'cgi')) - { - return; - } + if (null !== $this->currentTask && $e instanceof sfCommandArgumentsException) { + fwrite(STDERR, $this->formatter->format(sprintf($this->currentTask->getSynopsis(), $this->getName()), 'INFO', STDERR)."\n"); + fwrite(STDERR, "\n"); + } - // define stream constants - define('STDIN', fopen('php://stdin', 'r')); - define('STDOUT', fopen('php://stdout', 'w')); - define('STDERR', fopen('php://stderr', 'w')); + if ($this->trace) { + fwrite(STDERR, $this->formatter->format("Exception trace:\n", 'COMMENT')); + + // exception related properties + $trace = $e->getTrace(); + array_unshift($trace, [ + 'function' => '', + 'file' => null != $e->getFile() ? $e->getFile() : 'n/a', + 'line' => null != $e->getLine() ? $e->getLine() : 'n/a', + 'args' => [], + ]); + + for ($i = 0, $count = count($trace); $i < $count; ++$i) { + $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; + $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; + $function = $trace[$i]['function']; + $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; + $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; + + fwrite(STDERR, sprintf(" %s%s%s at %s:%s\n", $class, $type, $function, $this->formatter->format($file, 'INFO', STDERR), $this->formatter->format($line, 'INFO', STDERR))); + } + + fwrite(STDERR, "\n"); + } - // change directory - if (isset($_SERVER['PWD'])) - { - chdir($_SERVER['PWD']); + $this->dispatcher->notify(new sfEvent($e, 'application.throw_exception')); + } + + /** + * Gets a task from a task name or a shortcut. + * + * @param string $name The task name or a task shortcut + * + * @return sfTask A sfTask object + * + * @throws sfCommandException + */ + public function getTaskToExecute($name) + { + // namespace + if (false !== $pos = strpos($name, ':')) { + $namespace = substr($name, 0, $pos); + $name = substr($name, $pos + 1); + + $namespaces = []; + foreach ($this->tasks as $task) { + if ($task->getNamespace() && !in_array($task->getNamespace(), $namespaces)) { + $namespaces[] = $task->getNamespace(); + } + } + $abbrev = $this->getAbbreviations($namespaces); + + if (!isset($abbrev[$namespace])) { + throw new sfCommandException(sprintf('There are no tasks defined in the "%s" namespace.', $namespace)); + } + if (count($abbrev[$namespace]) > 1) { + throw new sfCommandException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, implode(', ', $abbrev[$namespace]))); + } + + $namespace = $abbrev[$namespace][0]; + } else { + $namespace = ''; + } + + // name + $tasks = []; + foreach ($this->tasks as $taskName => $task) { + if ($taskName == $task->getFullName() && $task->getNamespace() == $namespace) { + $tasks[] = $task->getName(); + } + } + + $abbrev = $this->getAbbreviations($tasks); + if (isset($abbrev[$name]) && 1 == count($abbrev[$name])) { + return $this->getTask($namespace ? $namespace.':'.$abbrev[$name][0] : $abbrev[$name][0]); + } + + // aliases + $aliases = []; + foreach ($this->tasks as $taskName => $task) { + if ($taskName == $task->getFullName()) { + foreach ($task->getAliases() as $alias) { + $aliases[] = $alias; + } + } + } + + $abbrev = $this->getAbbreviations($aliases); + $fullName = $namespace ? $namespace.':'.$name : $name; + if (!isset($abbrev[$fullName])) { + throw new sfCommandException(sprintf('Task "%s" is not defined.', $fullName)); + } + if (count($abbrev[$fullName]) > 1) { + throw new sfCommandException(sprintf('Task "%s" is ambiguous (%s).', $fullName, implode(', ', $abbrev[$fullName]))); + } + + return $this->getTask($abbrev[$fullName][0]); } - // close the streams on script termination - register_shutdown_function(function() { - fclose(STDIN); - fclose(STDOUT); - fclose(STDERR); - return true; - }); - } - - /** - * Returns an array of possible abbreviations given a set of names. - * - * @see Text::Abbrev perl module for the algorithm - * - * @param string[] $names - * - * @return string[] - */ - protected function getAbbreviations($names) - { - $abbrevs = array(); - $table = array(); - - foreach ($names as $name) + /** + * Parses and handles command line options. + * + * @param mixed $options The command line options + */ + protected function handleOptions($options = null) { - for ($len = strlen($name) - 1; $len > 0; --$len) - { - $abbrev = substr($name, 0, $len); - if (!array_key_exists($abbrev, $table)) - { - $table[$abbrev] = 1; - } - else - { - ++$table[$abbrev]; - } - - $seen = $table[$abbrev]; - if ($seen == 1) - { - // We're the first word so far to have this abbreviation. - $abbrevs[$abbrev] = array($name); - } - else if ($seen == 2) - { - // We're the second word to have this abbreviation, so we can't use it. - // unset($abbrevs[$abbrev]); - $abbrevs[$abbrev][] = $name; - } - else - { - // We're the third word to have this abbreviation, so skip to the next word. - continue; - } - } + $this->commandManager->process($options); + $this->commandOptions = $options; + + // the order of option processing matters + if ($this->commandManager->getOptionSet()->hasOption('no-color') && false !== $this->commandManager->getOptionValue('no-color')) { + $this->setFormatter(new sfFormatter()); + } elseif ($this->commandManager->getOptionSet()->hasOption('color') && false !== $this->commandManager->getOptionValue('color')) { + $this->setFormatter(new sfAnsiColorFormatter()); + } + + if ($this->commandManager->getOptionSet()->hasOption('quiet') && false !== $this->commandManager->getOptionValue('quiet')) { + $this->verbose = false; + } + + if ($this->commandManager->getOptionSet()->hasOption('no-debug') && false !== $this->commandManager->getOptionValue('no-debug')) { + $this->debug = false; + } + + if ($this->commandManager->getOptionSet()->hasOption('trace') && false !== $this->commandManager->getOptionValue('trace')) { + $this->verbose = true; + $this->trace = true; + } + + if ($this->commandManager->getOptionSet()->hasOption('help') && false !== $this->commandManager->getOptionValue('help')) { + $this->help(); + + exit(0); + } + + if ($this->commandManager->getOptionSet()->hasOption('version') && false !== $this->commandManager->getOptionValue('version')) { + echo $this->getLongVersion(); + + exit(0); + } } - // Non-abbreviations always get entered, even if they aren't unique - foreach ($names as $name) + protected function strlen($string) { - $abbrevs[$name] = array($name); + if (!function_exists('mb_strlen')) { + return strlen($string); + } + + if (false === $encoding = mb_detect_encoding($string)) { + return strlen($string); + } + + return mb_strlen($string, $encoding); } - return $abbrevs; - } - - /** - * Returns true if the stream supports colorization. - * - * Colorization is disabled if not supported by the stream: - * - * - windows without ansicon - * - non tty consoles - * - * @param mixed $stream A stream - * - * @return Boolean true if the stream supports colorization, false otherwise - */ - protected function isStreamSupportsColors($stream) - { - if (DIRECTORY_SEPARATOR == '\\') + /** + * Fixes php behavior if using cgi php. + * + * @see http://www.sitepoint.com/article/php-command-line-1/3 + */ + protected function fixCgi() { - return false !== getenv('ANSICON'); + // handle output buffering + if (ob_get_level() > 0) { + @ob_end_flush(); + } + + ob_implicit_flush(true); + + // PHP ini settings + set_time_limit(0); + ini_set('track_errors', true); + ini_set('html_errors', false); + ini_set('magic_quotes_runtime', false); + + if (false === strpos(PHP_SAPI, 'cgi')) { + return; + } + + // define stream constants + define('STDIN', fopen('php://stdin', 'r')); + define('STDOUT', fopen('php://stdout', 'w')); + define('STDERR', fopen('php://stderr', 'w')); + + // change directory + if (isset($_SERVER['PWD'])) { + chdir($_SERVER['PWD']); + } + + // close the streams on script termination + register_shutdown_function(function () { + fclose(STDIN); + fclose(STDOUT); + fclose(STDERR); + + return true; + }); + } + + /** + * Returns an array of possible abbreviations given a set of names. + * + * @see Text::Abbrev perl module for the algorithm + * + * @param string[] $names + * + * @return string[] + */ + protected function getAbbreviations($names) + { + $abbrevs = []; + $table = []; + + foreach ($names as $name) { + for ($len = strlen($name) - 1; $len > 0; --$len) { + $abbrev = substr($name, 0, $len); + if (!array_key_exists($abbrev, $table)) { + $table[$abbrev] = 1; + } else { + ++$table[$abbrev]; + } + + $seen = $table[$abbrev]; + if (1 == $seen) { + // We're the first word so far to have this abbreviation. + $abbrevs[$abbrev] = [$name]; + } elseif (2 == $seen) { + // We're the second word to have this abbreviation, so we can't use it. + // unset($abbrevs[$abbrev]); + $abbrevs[$abbrev][] = $name; + } else { + // We're the third word to have this abbreviation, so skip to the next word. + continue; + } + } + } + + // Non-abbreviations always get entered, even if they aren't unique + foreach ($names as $name) { + $abbrevs[$name] = [$name]; + } + + return $abbrevs; + } + + /** + * Returns true if the stream supports colorization. + * + * Colorization is disabled if not supported by the stream: + * + * - windows without ansicon + * - non tty consoles + * + * @param mixed $stream A stream + * + * @return bool true if the stream supports colorization, false otherwise + */ + protected function isStreamSupportsColors($stream) + { + if (DIRECTORY_SEPARATOR == '\\') { + return false !== getenv('ANSICON'); + } + + return function_exists('posix_isatty') && @posix_isatty($stream); } - else + + /** + * Guesses the best formatter for the stream. + * + * @param mixed $stream A stream + * + * @return sfFormatter A formatter instance + */ + protected function guessBestFormatter($stream) { - return function_exists('posix_isatty') && @posix_isatty($stream); + return $this->isStreamSupportsColors($stream) ? new sfAnsiColorFormatter() : new sfFormatter(); } - } - - /** - * Guesses the best formatter for the stream. - * - * @param mixed $stream A stream - * - * @return sfFormatter A formatter instance - */ - protected function guessBestFormatter($stream) - { - return $this->isStreamSupportsColors($stream) ? new sfAnsiColorFormatter() : new sfFormatter(); - } } diff --git a/lib/command/sfCommandArgument.class.php b/lib/command/sfCommandArgument.class.php index db9a9b7bd..3d6d2515c 100644 --- a/lib/command/sfCommandArgument.class.php +++ b/lib/command/sfCommandArgument.class.php @@ -11,128 +11,116 @@ /** * Represents a command line argument. * - * @package symfony - * @subpackage command * @author Fabien Potencier - * @version SVN: $Id$ */ class sfCommandArgument { - const REQUIRED = 1; - const OPTIONAL = 2; + public const REQUIRED = 1; + public const OPTIONAL = 2; - const IS_ARRAY = 4; + public const IS_ARRAY = 4; - protected - $name = null, - $mode = null, - $default = null, - $help = ''; + protected $name; + protected $mode; + protected $default; + protected $help = ''; - /** - * Constructor. - * - * @param string $name The argument name - * @param integer $mode The argument mode: self::REQUIRED or self::OPTIONAL - * @param string $help A help text - * @param mixed $default The default value (for self::OPTIONAL mode only) - * - * @throws sfCommandException - */ - public function __construct($name, $mode = null, $help = '', $default = null) - { - if (null === $mode) + /** + * Constructor. + * + * @param string $name The argument name + * @param int $mode The argument mode: self::REQUIRED or self::OPTIONAL + * @param string $help A help text + * @param mixed $default The default value (for self::OPTIONAL mode only) + * + * @throws sfCommandException + */ + public function __construct($name, $mode = null, $help = '', $default = null) { - $mode = self::OPTIONAL; + if (null === $mode) { + $mode = self::OPTIONAL; + } elseif (is_string($mode) || $mode > 7) { + throw new sfCommandException(sprintf('Argument mode "%s" is not valid.', $mode)); + } + + $this->name = $name; + $this->mode = $mode; + $this->help = $help; + + $this->setDefault($default); } - else if (is_string($mode) || $mode > 7) + + /** + * Returns the argument name. + * + * @return string The argument name + */ + public function getName() { - throw new sfCommandException(sprintf('Argument mode "%s" is not valid.', $mode)); + return $this->name; } - $this->name = $name; - $this->mode = $mode; - $this->help = $help; + /** + * Returns true if the argument is required. + * + * @return bool true if parameter mode is self::REQUIRED, false otherwise + */ + public function isRequired() + { + return self::REQUIRED === (self::REQUIRED & $this->mode); + } - $this->setDefault($default); - } + /** + * Returns true if the argument can take multiple values. + * + * @return bool true if mode is self::IS_ARRAY, false otherwise + */ + public function isArray() + { + return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); + } - /** - * Returns the argument name. - * - * @return string The argument name - */ - public function getName() - { - return $this->name; - } + /** + * Sets the default value. + * + * @param mixed $default The default value + * + * @throws sfCommandException + */ + public function setDefault($default = null) + { + if (self::REQUIRED === $this->mode && null !== $default) { + throw new sfCommandException('Cannot set a default value except for sfCommandParameter::OPTIONAL mode.'); + } - /** - * Returns true if the argument is required. - * - * @return Boolean true if parameter mode is self::REQUIRED, false otherwise - */ - public function isRequired() - { - return self::REQUIRED === (self::REQUIRED & $this->mode); - } + if ($this->isArray()) { + if (null === $default) { + $default = []; + } elseif (!is_array($default)) { + throw new sfCommandException('A default value for an array argument must be an array.'); + } + } - /** - * Returns true if the argument can take multiple values. - * - * @return Boolean true if mode is self::IS_ARRAY, false otherwise - */ - public function isArray() - { - return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); - } + $this->default = $default; + } - /** - * Sets the default value. - * - * @param mixed $default The default value - * - * @throws sfCommandException - */ - public function setDefault($default = null) - { - if (self::REQUIRED === $this->mode && null !== $default) + /** + * Returns the default value. + * + * @return mixed The default value + */ + public function getDefault() { - throw new sfCommandException('Cannot set a default value except for sfCommandParameter::OPTIONAL mode.'); + return $this->default; } - if ($this->isArray()) + /** + * Returns the help text. + * + * @return string The help text + */ + public function getHelp() { - if (null === $default) - { - $default = array(); - } - else if (!is_array($default)) - { - throw new sfCommandException('A default value for an array argument must be an array.'); - } + return $this->help; } - - $this->default = $default; - } - - /** - * Returns the default value. - * - * @return mixed The default value - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns the help text. - * - * @return string The help text - */ - public function getHelp() - { - return $this->help; - } } diff --git a/lib/command/sfCommandArgumentSet.class.php b/lib/command/sfCommandArgumentSet.class.php index d9a999c79..3e7f882d3 100644 --- a/lib/command/sfCommandArgumentSet.class.php +++ b/lib/command/sfCommandArgumentSet.class.php @@ -11,173 +11,158 @@ /** * Represent a set of command line arguments. * - * @package symfony - * @subpackage command * @author Fabien Potencier - * @version SVN: $Id$ */ class sfCommandArgumentSet { - protected - $arguments = array(), - $requiredCount = 0, - $hasAnArrayArgument = false, - $hasOptional = false; - - /** - * Constructor. - * - * @param array $arguments An array of sfCommandArgument objects - */ - public function __construct($arguments = array()) - { - $this->setArguments($arguments); - } - - /** - * Sets the sfCommandArgument objects. - * - * @param array $arguments An array of sfCommandArgument objects - */ - public function setArguments($arguments = array()) - { - $this->arguments = array(); - $this->requiredCount = 0; - $this->hasOptional = false; - $this->addArguments($arguments); - } - - /** - * Add an array of sfCommandArgument objects. - * - * @param array $arguments An array of sfCommandArgument objects - */ - public function addArguments($arguments = array()) - { - if (null !== $arguments) + protected $arguments = []; + protected $requiredCount = 0; + protected $hasAnArrayArgument = false; + protected $hasOptional = false; + + /** + * Constructor. + * + * @param array $arguments An array of sfCommandArgument objects + */ + public function __construct($arguments = []) { - foreach ($arguments as $argument) - { - $this->addArgument($argument); - } + $this->setArguments($arguments); } - } - - /** - * Add a sfCommandArgument objects. - * - * @param sfCommandArgument $argument A sfCommandArgument object - * - * @throws sfCommandException - */ - public function addArgument(sfCommandArgument $argument) - { - if (isset($this->arguments[$argument->getName()])) + + /** + * Sets the sfCommandArgument objects. + * + * @param array $arguments An array of sfCommandArgument objects + */ + public function setArguments($arguments = []) { - throw new sfCommandException(sprintf('An argument with name "%s" already exist.', $argument->getName())); + $this->arguments = []; + $this->requiredCount = 0; + $this->hasOptional = false; + $this->addArguments($arguments); } - if ($this->hasAnArrayArgument) + /** + * Add an array of sfCommandArgument objects. + * + * @param array $arguments An array of sfCommandArgument objects + */ + public function addArguments($arguments = []) { - throw new sfCommandException('Cannot add an argument after an array argument.'); + if (null !== $arguments) { + foreach ($arguments as $argument) { + $this->addArgument($argument); + } + } } - if ($argument->isRequired() && $this->hasOptional) + /** + * Add a sfCommandArgument objects. + * + * @param sfCommandArgument $argument A sfCommandArgument object + * + * @throws sfCommandException + */ + public function addArgument(sfCommandArgument $argument) { - throw new sfCommandException('Cannot add a required argument after an optional one.'); + if (isset($this->arguments[$argument->getName()])) { + throw new sfCommandException(sprintf('An argument with name "%s" already exist.', $argument->getName())); + } + + if ($this->hasAnArrayArgument) { + throw new sfCommandException('Cannot add an argument after an array argument.'); + } + + if ($argument->isRequired() && $this->hasOptional) { + throw new sfCommandException('Cannot add a required argument after an optional one.'); + } + + if ($argument->isArray()) { + $this->hasAnArrayArgument = true; + } + + if ($argument->isRequired()) { + ++$this->requiredCount; + } else { + $this->hasOptional = true; + } + + $this->arguments[$argument->getName()] = $argument; } - if ($argument->isArray()) + /** + * Returns an argument by name. + * + * @param string $name The argument name + * + * @return sfCommandArgument A sfCommandArgument object + * + * @throws sfCommandException + */ + public function getArgument($name) { - $this->hasAnArrayArgument = true; + if (!$this->hasArgument($name)) { + throw new sfCommandException(sprintf('The "%s" argument does not exist.', $name)); + } + + return $this->arguments[$name]; } - if ($argument->isRequired()) + /** + * Returns true if an argument object exists by name. + * + * @param string $name The argument name + * + * @return bool true if the argument object exists, false otherwise + */ + public function hasArgument($name) { - ++$this->requiredCount; + return isset($this->arguments[$name]); } - else + + /** + * Gets the array of sfCommandArgument objects. + * + * @return sfCommandArgument[] An array of sfCommandArgument objects + */ + public function getArguments() { - $this->hasOptional = true; + return $this->arguments; } - $this->arguments[$argument->getName()] = $argument; - } - - /** - * Returns an argument by name. - * - * @param string $name The argument name - * - * @return sfCommandArgument A sfCommandArgument object - * - * @throws sfCommandException - */ - public function getArgument($name) - { - if (!$this->hasArgument($name)) + /** + * Returns the number of arguments. + * + * @return int The number of arguments + */ + public function getArgumentCount() { - throw new sfCommandException(sprintf('The "%s" argument does not exist.', $name)); + return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments); } - return $this->arguments[$name]; - } - - /** - * Returns true if an argument object exists by name. - * - * @param string $name The argument name - * - * @return Boolean true if the argument object exists, false otherwise - */ - public function hasArgument($name) - { - return isset($this->arguments[$name]); - } - - /** - * Gets the array of sfCommandArgument objects. - * - * @return sfCommandArgument[] An array of sfCommandArgument objects - */ - public function getArguments() - { - return $this->arguments; - } - - /** - * Returns the number of arguments. - * - * @return integer The number of arguments - */ - public function getArgumentCount() - { - return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments); - } - - /** - * Returns the number of required arguments. - * - * @return integer The number of required arguments - */ - public function getArgumentRequiredCount() - { - return $this->requiredCount; - } - - /** - * Gets the default values. - * - * @return array An array of default values - */ - public function getDefaults() - { - $values = array(); - foreach ($this->arguments as $argument) + /** + * Returns the number of required arguments. + * + * @return int The number of required arguments + */ + public function getArgumentRequiredCount() { - $values[$argument->getName()] = $argument->getDefault(); + return $this->requiredCount; } - return $values; - } + /** + * Gets the default values. + * + * @return array An array of default values + */ + public function getDefaults() + { + $values = []; + foreach ($this->arguments as $argument) { + $values[$argument->getName()] = $argument->getDefault(); + } + + return $values; + } } diff --git a/lib/command/sfCommandArgumentsException.class.php b/lib/command/sfCommandArgumentsException.class.php index 9b23616d6..6147ab02b 100644 --- a/lib/command/sfCommandArgumentsException.class.php +++ b/lib/command/sfCommandArgumentsException.class.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -11,10 +11,7 @@ /** * sfCommandException is thrown when an error occurs in a task. * - * @package symfony - * @subpackage exception * @author Fabien Potencier - * @version SVN: $Id$ */ class sfCommandArgumentsException extends sfCommandException { diff --git a/lib/command/sfCommandException.class.php b/lib/command/sfCommandException.class.php index 58d9b312b..12e5cc9c6 100644 --- a/lib/command/sfCommandException.class.php +++ b/lib/command/sfCommandException.class.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) 2004-2006 Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -11,10 +11,7 @@ /** * sfCommandException is thrown when an error occurs in a task. * - * @package symfony - * @subpackage exception * @author Fabien Potencier - * @version SVN: $Id$ */ class sfCommandException extends sfException { diff --git a/lib/command/sfCommandLogger.class.php b/lib/command/sfCommandLogger.class.php index 3448f2dd6..77673b5c1 100644 --- a/lib/command/sfCommandLogger.class.php +++ b/lib/command/sfCommandLogger.class.php @@ -3,59 +3,52 @@ /* * This file is part of the symfony package. * (c) 2004-2006 Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** - * - * @package symfony - * @subpackage log * @author Fabien Potencier - * @version SVN: $Id$ */ class sfCommandLogger extends sfConsoleLogger { - /** - * Initializes this logger. - * - * @param sfEventDispatcher $dispatcher A sfEventDispatcher instance - * @param array $options An array of options. - */ - public function initialize(sfEventDispatcher $dispatcher, $options = array()) - { - $dispatcher->connect('command.log', array($this, 'listenToLogEvent')); - - return parent::initialize($dispatcher, $options); - } - - /** - * Listens to command.log events. - * - * @param sfEvent $event An sfEvent instance - */ - public function listenToLogEvent(sfEvent $event) - { - $priority = isset($event['priority']) ? $event['priority'] : self::INFO; - - $prefix = ''; - if ('application.log' == $event->getName()) + /** + * Initializes this logger. + * + * @param sfEventDispatcher $dispatcher A sfEventDispatcher instance + * @param array $options an array of options + */ + public function initialize(sfEventDispatcher $dispatcher, $options = []) { - $subject = $event->getSubject(); - $subject = is_object($subject) ? get_class($subject) : (is_string($subject) ? $subject : 'main'); + $dispatcher->connect('command.log', [$this, 'listenToLogEvent']); - $prefix = '>> '.$subject.' '; + return parent::initialize($dispatcher, $options); } - foreach ($event->getParameters() as $key => $message) + /** + * Listens to command.log events. + * + * @param sfEvent $event An sfEvent instance + */ + public function listenToLogEvent(sfEvent $event) { - if ('priority' === $key) - { - continue; - } + $priority = isset($event['priority']) ? $event['priority'] : self::INFO; + + $prefix = ''; + if ('application.log' == $event->getName()) { + $subject = $event->getSubject(); + $subject = is_object($subject) ? get_class($subject) : (is_string($subject) ? $subject : 'main'); + + $prefix = '>> '.$subject.' '; + } + + foreach ($event->getParameters() as $key => $message) { + if ('priority' === $key) { + continue; + } - $this->log(sprintf('%s%s', $prefix, $message), $priority); + $this->log(sprintf('%s%s', $prefix, $message), $priority); + } } - } } diff --git a/lib/command/sfCommandManager.class.php b/lib/command/sfCommandManager.class.php index 4858664f0..aea4b6bf3 100644 --- a/lib/command/sfCommandManager.class.php +++ b/lib/command/sfCommandManager.class.php @@ -11,383 +11,344 @@ /** * Class to manage command line arguments and options. * - * @package symfony - * @subpackage command * @author Fabien Potencier - * @version SVN: $Id$ */ class sfCommandManager { - /** @var array */ - protected $arguments = ''; - /** @var string[] */ - protected $errors = array(); - /** @var sfCommandOptionSet */ - protected $optionSet = null; - /** @var sfCommandArgumentSet */ - protected $argumentSet = array(); - /** @var array */ - protected $optionValues = array(); - /** @var array */ - protected $argumentValues = array(); - /** @var array */ - protected $parsedArgumentValues = array(); - - /** - * Constructor. - * - * @param sfCommandArgumentSet $argumentSet A sfCommandArgumentSet object - * @param sfCommandOptionSet $optionSet A setOptionSet object - */ - public function __construct(sfCommandArgumentSet $argumentSet = null, sfCommandOptionSet $optionSet = null) - { - if (null === $argumentSet) + /** @var array */ + protected $arguments = ''; + + /** @var string[] */ + protected $errors = []; + + /** @var sfCommandOptionSet */ + protected $optionSet; + + /** @var sfCommandArgumentSet */ + protected $argumentSet = []; + + /** @var array */ + protected $optionValues = []; + + /** @var array */ + protected $argumentValues = []; + + /** @var array */ + protected $parsedArgumentValues = []; + + /** + * Constructor. + * + * @param sfCommandArgumentSet $argumentSet A sfCommandArgumentSet object + * @param sfCommandOptionSet $optionSet A setOptionSet object + */ + public function __construct(?sfCommandArgumentSet $argumentSet = null, ?sfCommandOptionSet $optionSet = null) { - $argumentSet = new sfCommandArgumentSet(); + if (null === $argumentSet) { + $argumentSet = new sfCommandArgumentSet(); + } + $this->setArgumentSet($argumentSet); + + if (null === $optionSet) { + $optionSet = new sfCommandOptionSet(); + } + $this->setOptionSet($optionSet); } - $this->setArgumentSet($argumentSet); - if (null === $optionSet) + /** + * Sets the argument set. + * + * @param sfCommandArgumentSet $argumentSet A sfCommandArgumentSet object + */ + public function setArgumentSet(sfCommandArgumentSet $argumentSet) { - $optionSet = new sfCommandOptionSet(); + $this->argumentSet = $argumentSet; } - $this->setOptionSet($optionSet); - } - - /** - * Sets the argument set. - * - * @param sfCommandArgumentSet $argumentSet A sfCommandArgumentSet object - */ - public function setArgumentSet(sfCommandArgumentSet $argumentSet) - { - $this->argumentSet = $argumentSet; - } - - /** - * Gets the argument set. - * - * @return sfCommandArgumentSet A sfCommandArgumentSet object - */ - public function getArgumentSet() - { - return $this->argumentSet; - } - - /** - * Sets the option set. - * - * @param sfCommandOptionSet $optionSet A sfCommandOptionSet object - */ - public function setOptionSet(sfCommandOptionSet $optionSet) - { - $this->optionSet = $optionSet; - } - - /** - * Gets the option set. - * - * @return sfCommandOptionSet A sfCommandOptionSet object - */ - public function getOptionSet() - { - return $this->optionSet; - } - - /** - * Processes command line arguments. - * - * @param mixed $arguments A string or an array of command line parameters - */ - public function process($arguments = null) - { - if (null === $arguments) - { - $arguments = $_SERVER['argv']; - // we strip command line program - if (isset($arguments[0]) && '-' != $arguments[0][0]) - { - array_shift($arguments); - } - } - else if (!is_array($arguments)) + /** + * Gets the argument set. + * + * @return sfCommandArgumentSet A sfCommandArgumentSet object + */ + public function getArgumentSet() { - // hack to split arguments with spaces : --test="with some spaces" - $arguments = preg_replace_callback('/(\'|")(.+?)\\1/', function ($match) { - return str_replace(' ', '=PLACEHOLDER=', $match[2]); - }, $arguments); - $arguments = preg_split('/\s+/', $arguments); - $arguments = str_replace('=PLACEHOLDER=', ' ', $arguments); + return $this->argumentSet; } - $this->arguments = $arguments; - $this->optionValues = $this->optionSet->getDefaults(); - $this->argumentValues = $this->argumentSet->getDefaults(); - $this->parsedArgumentValues = array(); - $this->errors = array(); + /** + * Sets the option set. + * + * @param sfCommandOptionSet $optionSet A sfCommandOptionSet object + */ + public function setOptionSet(sfCommandOptionSet $optionSet) + { + $this->optionSet = $optionSet; + } - while (!in_array($argument = array_shift($this->arguments), array('', null))) + /** + * Gets the option set. + * + * @return sfCommandOptionSet A sfCommandOptionSet object + */ + public function getOptionSet() { - if ('--' == $argument) - { - // stop options parsing - $this->parsedArgumentValues = array_merge($this->parsedArgumentValues, $this->arguments); - break; - } - - if ('--' == substr($argument, 0, 2)) - { - $this->parseLongOption(substr($argument, 2)); - } - else if ('-' == $argument[0]) - { - $this->parseShortOption(substr($argument, 1)); - } - else - { - $this->parsedArgumentValues[] = $argument; - } + return $this->optionSet; } - $position = 0; - foreach ($this->argumentSet->getArguments() as $argument) + /** + * Processes command line arguments. + * + * @param mixed $arguments A string or an array of command line parameters + */ + public function process($arguments = null) { - if (array_key_exists($position, $this->parsedArgumentValues)) - { - if ($argument->isArray()) - { - $this->argumentValues[$argument->getName()] = array_slice($this->parsedArgumentValues, $position); - break; + if (null === $arguments) { + $arguments = $_SERVER['argv']; + + // we strip command line program + if (isset($arguments[0]) && '-' != $arguments[0][0]) { + array_shift($arguments); + } + } elseif (!is_array($arguments)) { + // hack to split arguments with spaces : --test="with some spaces" + $arguments = preg_replace_callback('/(\'|")(.+?)\\1/', function ($match) { + return str_replace(' ', '=PLACEHOLDER=', $match[2]); + }, $arguments); + $arguments = preg_split('/\s+/', $arguments); + $arguments = str_replace('=PLACEHOLDER=', ' ', $arguments); + } + + $this->arguments = $arguments; + $this->optionValues = $this->optionSet->getDefaults(); + $this->argumentValues = $this->argumentSet->getDefaults(); + $this->parsedArgumentValues = []; + $this->errors = []; + + while (!in_array($argument = array_shift($this->arguments), ['', null])) { + if ('--' == $argument) { + // stop options parsing + $this->parsedArgumentValues = array_merge($this->parsedArgumentValues, $this->arguments); + + break; + } + + if ('--' == substr($argument, 0, 2)) { + $this->parseLongOption(substr($argument, 2)); + } elseif ('-' == $argument[0]) { + $this->parseShortOption(substr($argument, 1)); + } else { + $this->parsedArgumentValues[] = $argument; + } + } + + $position = 0; + foreach ($this->argumentSet->getArguments() as $argument) { + if (array_key_exists($position, $this->parsedArgumentValues)) { + if ($argument->isArray()) { + $this->argumentValues[$argument->getName()] = array_slice($this->parsedArgumentValues, $position); + + break; + } + + $this->argumentValues[$argument->getName()] = $this->parsedArgumentValues[$position]; + } + ++$position; } - else - { - $this->argumentValues[$argument->getName()] = $this->parsedArgumentValues[$position]; + + $this->arguments = $arguments; + + if (count($this->parsedArgumentValues) < $this->argumentSet->getArgumentRequiredCount()) { + $this->errors[] = 'Not enough arguments.'; + } elseif (count($this->parsedArgumentValues) > $this->argumentSet->getArgumentCount()) { + $this->errors[] = sprintf('Too many arguments ("%s" given).', implode(' ', $this->parsedArgumentValues)); } - } - ++$position; } - $this->arguments = $arguments; + /** + * Returns true if the current command line options validate the argument and option sets. + * + * @return true if there are some validation errors, false otherwise + */ + public function isValid() + { + return count($this->errors) ? false : true; + } - if (count($this->parsedArgumentValues) < $this->argumentSet->getArgumentRequiredCount()) + /** + * Gets the current errors. + * + * @return array An array of errors + */ + public function getErrors() { - $this->errors[] = 'Not enough arguments.'; + return $this->errors; } - else if (count($this->parsedArgumentValues) > $this->argumentSet->getArgumentCount()) + + /** + * Returns the argument values. + * + * @return array An array of argument values + */ + public function getArgumentValues() { - $this->errors[] = sprintf('Too many arguments ("%s" given).', implode(' ', $this->parsedArgumentValues)); + return $this->argumentValues; } - } - - /** - * Returns true if the current command line options validate the argument and option sets. - * - * @return true if there are some validation errors, false otherwise - */ - public function isValid() - { - return count($this->errors) ? false : true; - } - - /** - * Gets the current errors. - * - * @return array An array of errors - */ - public function getErrors() - { - return $this->errors; - } - - /** - * Returns the argument values. - * - * @return array An array of argument values - */ - public function getArgumentValues() - { - return $this->argumentValues; - } - - /** - * Returns the argument value for a given argument name. - * - * @param string $name The argument name - * - * @return mixed The argument value - * - * @throws sfCommandException - */ - public function getArgumentValue($name) - { - if (!$this->argumentSet->hasArgument($name)) + + /** + * Returns the argument value for a given argument name. + * + * @param string $name The argument name + * + * @return mixed The argument value + * + * @throws sfCommandException + */ + public function getArgumentValue($name) { - throw new sfCommandException(sprintf('The "%s" argument does not exist.', $name)); + if (!$this->argumentSet->hasArgument($name)) { + throw new sfCommandException(sprintf('The "%s" argument does not exist.', $name)); + } + + return $this->argumentValues[$name]; } - return $this->argumentValues[$name]; - } - - /** - * Returns the options values. - * - * @return array An array of option values - */ - public function getOptionValues() - { - return $this->optionValues; - } - - /** - * Returns the option value for a given option name. - * - * @param string $name The option name - * - * @return mixed The option value - * - * @throws sfCommandException - */ - public function getOptionValue($name) - { - if (!$this->optionSet->hasOption($name)) + /** + * Returns the options values. + * + * @return array An array of option values + */ + public function getOptionValues() { - throw new sfCommandException(sprintf('The "%s" option does not exist.', $name)); + return $this->optionValues; } - return $this->optionValues[$name]; - } - - /** - * Parses a short option. - * - * @param string $argument The option argument - */ - protected function parseShortOption($argument) - { - // short option can be aggregated like in -vd (== -v -d) - for ($i = 0, $count = strlen($argument); $i < $count; $i++) + /** + * Returns the option value for a given option name. + * + * @param string $name The option name + * + * @return mixed The option value + * + * @throws sfCommandException + */ + public function getOptionValue($name) { - $shortcut = $argument[$i]; - $value = true; - - if (!$this->optionSet->hasShortcut($shortcut)) - { - $this->errors[] = sprintf('The option "-%s" does not exist.', $shortcut); - continue; - } - - $option = $this->optionSet->getOptionForShortcut($shortcut); - - // required argument? - if ($option->isParameterRequired()) - { - if ($i + 1 < strlen($argument)) - { - $value = substr($argument, $i + 1); - $this->setOption($option, $value); - break; + if (!$this->optionSet->hasOption($name)) { + throw new sfCommandException(sprintf('The "%s" option does not exist.', $name)); } - else - { - // take next element as argument (if it doesn't start with a -) - if (count($this->arguments) && $this->arguments[0][0] != '-') - { - $value = array_shift($this->arguments); - $this->setOption($option, $value); - break; - } - else - { - $this->errors[] = sprintf('Option "-%s" requires an argument', $shortcut); - $value = null; - } - } - } - else if ($option->isParameterOptional()) - { - if (substr($argument, $i + 1) != '') - { - $value = substr($argument, $i + 1); - } - else - { - // take next element as argument (if it doesn't start with a -) - if (count($this->arguments) && $this->arguments[0][0] != '-') - { - $value = array_shift($this->arguments); - } - else - { - $value = $option->getDefault(); - } + + return $this->optionValues[$name]; + } + + public function setOption(sfCommandOption $option, $value) + { + if ($option->isArray()) { + $this->optionValues[$option->getName()][] = $value; + } else { + $this->optionValues[$option->getName()] = $value; } + } - $this->setOption($option, $value); - break; - } + /** + * Parses a short option. + * + * @param string $argument The option argument + */ + protected function parseShortOption($argument) + { + // short option can be aggregated like in -vd (== -v -d) + for ($i = 0, $count = strlen($argument); $i < $count; ++$i) { + $shortcut = $argument[$i]; + $value = true; + + if (!$this->optionSet->hasShortcut($shortcut)) { + $this->errors[] = sprintf('The option "-%s" does not exist.', $shortcut); + + continue; + } + + $option = $this->optionSet->getOptionForShortcut($shortcut); + + // required argument? + if ($option->isParameterRequired()) { + if ($i + 1 < strlen($argument)) { + $value = substr($argument, $i + 1); + $this->setOption($option, $value); + + break; + } + + // take next element as argument (if it doesn't start with a -) + if (count($this->arguments) && '-' != $this->arguments[0][0]) { + $value = array_shift($this->arguments); + $this->setOption($option, $value); + + break; + } + + $this->errors[] = sprintf('Option "-%s" requires an argument', $shortcut); + $value = null; + } elseif ($option->isParameterOptional()) { + if ('' != substr($argument, $i + 1)) { + $value = substr($argument, $i + 1); + } else { + // take next element as argument (if it doesn't start with a -) + if (count($this->arguments) && '-' != $this->arguments[0][0]) { + $value = array_shift($this->arguments); + } else { + $value = $option->getDefault(); + } + } + + $this->setOption($option, $value); + + break; + } - $this->setOption($option, $value); + $this->setOption($option, $value); + } } - } - - /** - * Parses a long option. - * - * @param string $argument The option argument - */ - protected function parseLongOption($argument) - { - if (false !== strpos($argument, '=')) + + /** + * Parses a long option. + * + * @param string $argument The option argument + */ + protected function parseLongOption($argument) { - list($name, $value) = explode('=', $argument, 2); + if (false !== strpos($argument, '=')) { + list($name, $value) = explode('=', $argument, 2); - if (!$this->optionSet->hasOption($name)) - { - $this->errors[] = sprintf('The "--%s" option does not exist.', $name); - return; - } + if (!$this->optionSet->hasOption($name)) { + $this->errors[] = sprintf('The "--%s" option does not exist.', $name); - $option = $this->optionSet->getOption($name); + return; + } - if (!$option->acceptParameter()) - { - $this->errors[] = sprintf('Option "--%s" does not take an argument.', $name); - $value = true; - } - } - else - { - $name = $argument; + $option = $this->optionSet->getOption($name); - if (!$this->optionSet->hasOption($name)) - { - $this->errors[] = sprintf('The "--%s" option does not exist.', $name); - return; - } + if (!$option->acceptParameter()) { + $this->errors[] = sprintf('Option "--%s" does not take an argument.', $name); + $value = true; + } + } else { + $name = $argument; - $option = $this->optionSet->getOption($name); + if (!$this->optionSet->hasOption($name)) { + $this->errors[] = sprintf('The "--%s" option does not exist.', $name); - if ($option->isParameterRequired()) - { - $this->errors[] = sprintf('Option "--%s" requires an argument.', $name); - } + return; + } - $value = $option->acceptParameter() ? $option->getDefault() : true; - } + $option = $this->optionSet->getOption($name); - $this->setOption($option, $value); - } + if ($option->isParameterRequired()) { + $this->errors[] = sprintf('Option "--%s" requires an argument.', $name); + } - public function setOption(sfCommandOption $option, $value) - { - if ($option->isArray()) - { - $this->optionValues[$option->getName()][] = $value; - } - else - { - $this->optionValues[$option->getName()] = $value; + $value = $option->acceptParameter() ? $option->getDefault() : true; + } + + $this->setOption($option, $value); } - } } diff --git a/lib/command/sfCommandOption.class.php b/lib/command/sfCommandOption.class.php index 028cc6bcd..d525aa7e9 100644 --- a/lib/command/sfCommandOption.class.php +++ b/lib/command/sfCommandOption.class.php @@ -11,180 +11,164 @@ /** * Represents a command line option. * - * @package symfony - * @subpackage command * @author Fabien Potencier - * @version SVN: $Id$ */ class sfCommandOption { - const PARAMETER_NONE = 1; - const PARAMETER_REQUIRED = 2; - const PARAMETER_OPTIONAL = 4; - - const IS_ARRAY = 8; - - protected - $name = null, - $shortcut = null, - $mode = null, - $default = null, - $help = ''; - - /** - * Constructor. - * - * @param string $name The option name - * @param string $shortcut The shortcut (can be null) - * @param integer $mode The option mode: self::PARAMETER_REQUIRED, self::PARAMETER_NONE or self::PARAMETER_OPTIONAL - * @param string $help A help text - * @param mixed $default The default value (must be null for self::PARAMETER_REQUIRED or self::PARAMETER_NONE) - * - * @throws sfCommandException - */ - public function __construct($name, $shortcut = null, $mode = null, $help = '', $default = null) - { - if ('--' == substr($name, 0, 2)) + public const PARAMETER_NONE = 1; + public const PARAMETER_REQUIRED = 2; + public const PARAMETER_OPTIONAL = 4; + + public const IS_ARRAY = 8; + + protected $name; + protected $shortcut; + protected $mode; + protected $default; + protected $help = ''; + + /** + * Constructor. + * + * @param string $name The option name + * @param string $shortcut The shortcut (can be null) + * @param int $mode The option mode: self::PARAMETER_REQUIRED, self::PARAMETER_NONE or self::PARAMETER_OPTIONAL + * @param string $help A help text + * @param mixed $default The default value (must be null for self::PARAMETER_REQUIRED or self::PARAMETER_NONE) + * + * @throws sfCommandException + */ + public function __construct($name, $shortcut = null, $mode = null, $help = '', $default = null) { - $name = substr($name, 2); + if ('--' == substr($name, 0, 2)) { + $name = substr($name, 2); + } + + if (empty($shortcut)) { + $shortcut = null; + } + + if (null !== $shortcut) { + if ('-' == $shortcut[0]) { + $shortcut = substr($shortcut, 1); + } + } + + if (null === $mode) { + $mode = self::PARAMETER_NONE; + } elseif (is_string($mode) || $mode > 15) { + throw new sfCommandException(sprintf('Option mode "%s" is not valid.', $mode)); + } + + $this->name = $name; + $this->shortcut = $shortcut; + $this->mode = $mode; + $this->help = $help; + + $this->setDefault($default); } - if (empty($shortcut)) + /** + * Returns the shortcut. + * + * @return string The shortcut + */ + public function getShortcut() { - $shortcut = null; + return $this->shortcut; } - if (null !== $shortcut) + /** + * Returns the name. + * + * @return string The name + */ + public function getName() { - if ('-' == $shortcut[0]) - { - $shortcut = substr($shortcut, 1); - } + return $this->name; } - if (null === $mode) + /** + * Returns true if the option accept a parameter. + * + * @return bool true if parameter mode is not self::PARAMETER_NONE, false otherwise + */ + public function acceptParameter() { - $mode = self::PARAMETER_NONE; + return $this->isParameterRequired() || $this->isParameterOptional(); } - else if (is_string($mode) || $mode > 15) + + /** + * Returns true if the option requires a parameter. + * + * @return bool true if parameter mode is self::PARAMETER_REQUIRED, false otherwise + */ + public function isParameterRequired() { - throw new sfCommandException(sprintf('Option mode "%s" is not valid.', $mode)); + return self::PARAMETER_REQUIRED === (self::PARAMETER_REQUIRED & $this->mode); } - $this->name = $name; - $this->shortcut = $shortcut; - $this->mode = $mode; - $this->help = $help; - - $this->setDefault($default); - } - - /** - * Returns the shortcut. - * - * @return string The shortcut - */ - public function getShortcut() - { - return $this->shortcut; - } - - /** - * Returns the name. - * - * @return string The name - */ - public function getName() - { - return $this->name; - } - - /** - * Returns true if the option accept a parameter. - * - * @return Boolean true if parameter mode is not self::PARAMETER_NONE, false otherwise - */ - public function acceptParameter() - { - return $this->isParameterRequired() || $this->isParameterOptional(); - } - - /** - * Returns true if the option requires a parameter. - * - * @return Boolean true if parameter mode is self::PARAMETER_REQUIRED, false otherwise - */ - public function isParameterRequired() - { - return self::PARAMETER_REQUIRED === (self::PARAMETER_REQUIRED & $this->mode); - } - - /** - * Returns true if the option takes an optional parameter. - * - * @return Boolean true if parameter mode is self::PARAMETER_OPTIONAL, false otherwise - */ - public function isParameterOptional() - { - return self::PARAMETER_OPTIONAL === (self::PARAMETER_OPTIONAL & $this->mode); - } - - /** - * Returns true if the option can take multiple values. - * - * @return Boolean true if mode is self::IS_ARRAY, false otherwise - */ - public function isArray() - { - return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); - } - - /** - * Sets the default value. - * - * @param mixed $default The default value - * - * @throws sfCommandException - */ - public function setDefault($default = null) - { - if (self::PARAMETER_NONE === (self::PARAMETER_NONE & $this->mode) && null !== $default) + /** + * Returns true if the option takes an optional parameter. + * + * @return bool true if parameter mode is self::PARAMETER_OPTIONAL, false otherwise + */ + public function isParameterOptional() { - throw new sfCommandException('Cannot set a default value when using sfCommandOption::PARAMETER_NONE mode.'); + return self::PARAMETER_OPTIONAL === (self::PARAMETER_OPTIONAL & $this->mode); } - if ($this->isArray()) + /** + * Returns true if the option can take multiple values. + * + * @return bool true if mode is self::IS_ARRAY, false otherwise + */ + public function isArray() { - if (null === $default) - { - $default = array(); - } - else if (!is_array($default)) - { - throw new sfCommandException('A default value for an array option must be an array.'); - } + return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); } - $this->default = $this->acceptParameter() ? $default : false; - } - - /** - * Returns the default value. - * - * @return mixed The default value - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns the help text. - * - * @return string The help text - */ - public function getHelp() - { - return $this->help; - } + /** + * Sets the default value. + * + * @param mixed $default The default value + * + * @throws sfCommandException + */ + public function setDefault($default = null) + { + if (self::PARAMETER_NONE === (self::PARAMETER_NONE & $this->mode) && null !== $default) { + throw new sfCommandException('Cannot set a default value when using sfCommandOption::PARAMETER_NONE mode.'); + } + + if ($this->isArray()) { + if (null === $default) { + $default = []; + } elseif (!is_array($default)) { + throw new sfCommandException('A default value for an array option must be an array.'); + } + } + + $this->default = $this->acceptParameter() ? $default : false; + } + + /** + * Returns the default value. + * + * @return mixed The default value + */ + public function getDefault() + { + return $this->default; + } + + /** + * Returns the help text. + * + * @return string The help text + */ + public function getHelp() + { + return $this->help; + } } diff --git a/lib/command/sfCommandOptionSet.class.php b/lib/command/sfCommandOptionSet.class.php index ffa332eba..e8e00cb57 100644 --- a/lib/command/sfCommandOptionSet.class.php +++ b/lib/command/sfCommandOptionSet.class.php @@ -11,174 +11,163 @@ /** * Represent a set of command line options. * - * @package symfony - * @subpackage command * @author Fabien Potencier - * @version SVN: $Id$ */ class sfCommandOptionSet { - protected - $options = array(), - $shortcuts = array(); - - /** - * Constructor. - * - * @param array $options An array of sfCommandOption objects - */ - public function __construct($options = array()) - { - $this->setOptions($options); - } - - /** - * Sets the sfCommandOption objects. - * - * @param array $options An array of sfCommandOption objects - */ - public function setOptions($options = array()) - { - $this->options = array(); - $this->shortcuts = array(); - $this->addOptions($options); - } - - /** - * Add an array of sfCommandOption objects. - * - * @param array $options An array of sfCommandOption objects - */ - public function addOptions($options = array()) - { - foreach ($options as $option) + protected $options = []; + protected $shortcuts = []; + + /** + * Constructor. + * + * @param array $options An array of sfCommandOption objects + */ + public function __construct($options = []) { - $this->addOption($option); + $this->setOptions($options); } - } - - /** - * Add a sfCommandOption objects. - * - * @param sfCommandOption $option A sfCommandOption object - * - * @throws sfCommandException - */ - public function addOption(sfCommandOption $option) - { - if (isset($this->options[$option->getName()])) + + /** + * Sets the sfCommandOption objects. + * + * @param array $options An array of sfCommandOption objects + */ + public function setOptions($options = []) { - throw new sfCommandException(sprintf('An option named "%s" already exist.', $option->getName())); + $this->options = []; + $this->shortcuts = []; + $this->addOptions($options); } - else if (isset($this->shortcuts[$option->getShortcut()])) + + /** + * Add an array of sfCommandOption objects. + * + * @param array $options An array of sfCommandOption objects + */ + public function addOptions($options = []) { - throw new sfCommandException(sprintf('An option with shortcut "%s" already exist.', $option->getShortcut())); + foreach ($options as $option) { + $this->addOption($option); + } } - $this->options[$option->getName()] = $option; - if ($option->getShortcut()) + /** + * Add a sfCommandOption objects. + * + * @param sfCommandOption $option A sfCommandOption object + * + * @throws sfCommandException + */ + public function addOption(sfCommandOption $option) { - $this->shortcuts[$option->getShortcut()] = $option->getName(); + if (isset($this->options[$option->getName()])) { + throw new sfCommandException(sprintf('An option named "%s" already exist.', $option->getName())); + } + if (isset($this->shortcuts[$option->getShortcut()])) { + throw new sfCommandException(sprintf('An option with shortcut "%s" already exist.', $option->getShortcut())); + } + + $this->options[$option->getName()] = $option; + if ($option->getShortcut()) { + $this->shortcuts[$option->getShortcut()] = $option->getName(); + } } - } - - /** - * Returns an option by name. - * - * @param string $name The option name - * - * @return sfCommandOption A sfCommandOption object - * - * @throws sfCommandException - */ - public function getOption($name) - { - if (!$this->hasOption($name)) + + /** + * Returns an option by name. + * + * @param string $name The option name + * + * @return sfCommandOption A sfCommandOption object + * + * @throws sfCommandException + */ + public function getOption($name) { - throw new sfCommandException(sprintf('The "--%s" option does not exist.', $name)); + if (!$this->hasOption($name)) { + throw new sfCommandException(sprintf('The "--%s" option does not exist.', $name)); + } + + return $this->options[$name]; } - return $this->options[$name]; - } - - /** - * Returns true if an option object exists by name. - * - * @param string $name The option name - * - * @return Boolean true if the option object exists, false otherwise - */ - public function hasOption($name) - { - return isset($this->options[$name]); - } - - /** - * Gets the array of sfCommandOption objects. - * - * @return sfCommandOption[] An array of sfCommandOption objects - */ - public function getOptions() - { - return $this->options; - } - - /** - * Returns true if an option object exists by shortcut. - * - * @param string $name The option shortcut - * - * @return Boolean true if the option object exists, false otherwise - */ - public function hasShortcut($name) - { - return isset($this->shortcuts[$name]); - } - - /** - * Gets an option by shortcut. - * - * @param string $shortcut - * - * @return sfCommandOption A sfCommandOption object - */ - public function getOptionForShortcut($shortcut) - { - return $this->getOption($this->shortcutToName($shortcut)); - } - - /** - * Gets an array of default values. - * - * @return array An array of all default values - */ - public function getDefaults() - { - $values = array(); - foreach ($this->options as $option) + /** + * Returns true if an option object exists by name. + * + * @param string $name The option name + * + * @return bool true if the option object exists, false otherwise + */ + public function hasOption($name) { - $values[$option->getName()] = $option->getDefault(); + return isset($this->options[$name]); } - return $values; - } - - /** - * Returns the option name given a shortcut. - * - * @param string $shortcut The shortcut - * - * @return string The option name - * - * @throws sfCommandException - */ - protected function shortcutToName($shortcut) - { - if (!isset($this->shortcuts[$shortcut])) + /** + * Gets the array of sfCommandOption objects. + * + * @return sfCommandOption[] An array of sfCommandOption objects + */ + public function getOptions() { - throw new sfCommandException(sprintf('The "-%s" option does not exist.', $shortcut)); + return $this->options; } - return $this->shortcuts[$shortcut]; - } + /** + * Returns true if an option object exists by shortcut. + * + * @param string $name The option shortcut + * + * @return bool true if the option object exists, false otherwise + */ + public function hasShortcut($name) + { + return isset($this->shortcuts[$name]); + } + + /** + * Gets an option by shortcut. + * + * @param string $shortcut + * + * @return sfCommandOption A sfCommandOption object + */ + public function getOptionForShortcut($shortcut) + { + return $this->getOption($this->shortcutToName($shortcut)); + } + + /** + * Gets an array of default values. + * + * @return array An array of all default values + */ + public function getDefaults() + { + $values = []; + foreach ($this->options as $option) { + $values[$option->getName()] = $option->getDefault(); + } + + return $values; + } + + /** + * Returns the option name given a shortcut. + * + * @param string $shortcut The shortcut + * + * @return string The option name + * + * @throws sfCommandException + */ + protected function shortcutToName($shortcut) + { + if (!isset($this->shortcuts[$shortcut])) { + throw new sfCommandException(sprintf('The "-%s" option does not exist.', $shortcut)); + } + + return $this->shortcuts[$shortcut]; + } } diff --git a/lib/command/sfFormatter.class.php b/lib/command/sfFormatter.class.php index 0367bad82..d37829c87 100644 --- a/lib/command/sfFormatter.class.php +++ b/lib/command/sfFormatter.class.php @@ -11,110 +11,99 @@ /** * sfFormatter provides methods to format text to be displayed on a console. * - * @package symfony - * @subpackage command * @author Fabien Potencier - * @version SVN: $Id$ */ class sfFormatter { - protected - $size = null; + protected $size; - function __construct($maxLineSize = null) - { - if (null === $maxLineSize) + public function __construct($maxLineSize = null) { - if (function_exists('shell_exec')) - { - // this is tricky because "tput cols 2>&1" is not accurate - $maxLineSize = ctype_digit(trim(shell_exec('tput cols 2>&1'))) ? (integer) shell_exec('tput cols') : 78; - } - else - { - $maxLineSize = 78; - } - } - - $this->size = $maxLineSize; - } + if (null === $maxLineSize) { + if (function_exists('shell_exec')) { + // this is tricky because "tput cols 2>&1" is not accurate + $maxLineSize = ctype_digit(trim(shell_exec('tput cols 2>&1'))) ? (int) shell_exec('tput cols') : 78; + } else { + $maxLineSize = 78; + } + } - /** - * Sets a new style. - * - * @param string $name The style name - * @param array $options An array of options - */ - public function setStyle($name, $options = array()) - { - } + $this->size = $maxLineSize; + } - /** - * Formats a text according to the given parameters. - * - * @param string $text The test to style - * @param mixed $parameters An array of parameters - * - * @return string The formatted text - */ - public function format($text = '', $parameters = array()) - { - return $text; - } + /** + * Sets a new style. + * + * @param string $name The style name + * @param array $options An array of options + */ + public function setStyle($name, $options = []) + { + } - /** - * Formats a message within a section. - * - * @param string $section The section name - * @param string $text The text message - * @param integer $size The maximum size allowed for a line - * - * @return string - */ - public function formatSection($section, $text, $size = null) - { - if (!$size) + /** + * Formats a text according to the given parameters. + * + * @param string $text The test to style + * @param mixed $parameters An array of parameters + * + * @return string The formatted text + */ + public function format($text = '', $parameters = []) { - $size = $this->size; + return $text; } - $section = sprintf('>> %-9s ', $section); + /** + * Formats a message within a section. + * + * @param string $section The section name + * @param string $text The text message + * @param int $size The maximum size allowed for a line + * + * @return string + */ + public function formatSection($section, $text, $size = null) + { + if (!$size) { + $size = $this->size; + } - return $section.$this->excerpt($text, $size - strlen($section)); - } + $section = sprintf('>> %-9s ', $section); - /** - * Truncates a line. - * - * @param string $text The text - * @param integer $size The maximum size of the returned string - * - * @return string The truncated string - */ - public function excerpt($text, $size = null) - { - if (!$size) - { - $size = $this->size; + return $section.$this->excerpt($text, $size - strlen($section)); } - if (strlen($text) < $size) + /** + * Truncates a line. + * + * @param string $text The text + * @param int $size The maximum size of the returned string + * + * @return string The truncated string + */ + public function excerpt($text, $size = null) { - return $text; - } + if (!$size) { + $size = $this->size; + } + + if (strlen($text) < $size) { + return $text; + } - $subsize = floor(($size - 3) / 2); + $subsize = floor(($size - 3) / 2); - return substr($text, 0, $subsize).'...'.substr($text, -$subsize); - } + return substr($text, 0, $subsize).'...'.substr($text, -$subsize); + } - /** - * Sets the maximum line size. - * - * @param integer $size The maximum line size for a message - */ - public function setMaxLineSize($size) - { - $this->size = $size; - } + /** + * Sets the maximum line size. + * + * @param int $size The maximum line size for a message + */ + public function setMaxLineSize($size) + { + $this->size = $size; + } } diff --git a/lib/command/sfSymfonyCommandApplication.class.php b/lib/command/sfSymfonyCommandApplication.class.php index 2282275a5..bec81a576 100644 --- a/lib/command/sfSymfonyCommandApplication.class.php +++ b/lib/command/sfSymfonyCommandApplication.class.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) 2004-2006 Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -11,143 +11,129 @@ /** * sfSymfonyCommandApplication manages the symfony CLI. * - * @package symfony - * @subpackage command * @author Fabien Potencier - * @version SVN: $Id$ */ class sfSymfonyCommandApplication extends sfCommandApplication { - protected $taskFiles = array(); - - /** - * Configures the current symfony command application. - */ - public function configure() - { - if (!isset($this->options['symfony_lib_dir'])) - { - throw new sfInitializationException('You must pass a "symfony_lib_dir" option.'); - } - - $configurationFile = getcwd().'/config/ProjectConfiguration.class.php'; - if (is_readable($configurationFile)) - { - require_once $configurationFile; - $configuration = new ProjectConfiguration(getcwd(), $this->dispatcher); - } - else + protected $taskFiles = []; + + /** + * Configures the current symfony command application. + */ + public function configure() { - $configuration = new sfProjectConfiguration(getcwd(), $this->dispatcher); + if (!isset($this->options['symfony_lib_dir'])) { + throw new sfInitializationException('You must pass a "symfony_lib_dir" option.'); + } + + $configurationFile = getcwd().'/config/ProjectConfiguration.class.php'; + if (is_readable($configurationFile)) { + require_once $configurationFile; + $configuration = new ProjectConfiguration(getcwd(), $this->dispatcher); + } else { + $configuration = new sfProjectConfiguration(getcwd(), $this->dispatcher); + } + + // application + $this->setName('symfony'); + $this->setVersion(SYMFONY_VERSION); + + $this->loadTasks($configuration); } - // application - $this->setName('symfony'); - $this->setVersion(SYMFONY_VERSION); - - $this->loadTasks($configuration); - } - - /** - * Runs the current application. - * - * @param mixed $options The command line options - * - * @return integer 0 if everything went fine, or an error code - */ - public function run($options = null) - { - $this->handleOptions($options); - $arguments = $this->commandManager->getArgumentValues(); - - if (!isset($arguments['task'])) + /** + * Runs the current application. + * + * @param mixed $options The command line options + * + * @return int 0 if everything went fine, or an error code + */ + public function run($options = null) { - $arguments['task'] = 'list'; - $this->commandOptions .= $arguments['task']; - } + $this->handleOptions($options); + $arguments = $this->commandManager->getArgumentValues(); - $this->currentTask = $this->getTaskToExecute($arguments['task']); + if (!isset($arguments['task'])) { + $arguments['task'] = 'list'; + $this->commandOptions .= $arguments['task']; + } - if ($this->currentTask instanceof sfCommandApplicationTask) - { - $this->currentTask->setCommandApplication($this); - } + $this->currentTask = $this->getTaskToExecute($arguments['task']); - $ret = $this->currentTask->runFromCLI($this->commandManager, $this->commandOptions); + if ($this->currentTask instanceof sfCommandApplicationTask) { + $this->currentTask->setCommandApplication($this); + } - $this->currentTask = null; + $ret = $this->currentTask->runFromCLI($this->commandManager, $this->commandOptions); - return $ret; - } + $this->currentTask = null; - /** - * Loads all available tasks. - * - * Looks for tasks in the symfony core, the current project and all project plugins. - * - * @param sfProjectConfiguration $configuration The project configuration - */ - public function loadTasks(sfProjectConfiguration $configuration) - { - // Symfony core tasks - $dirs = array(sfConfig::get('sf_symfony_lib_dir').'/task'); + return $ret; + } - // Plugin tasks - foreach ($configuration->getPluginPaths() as $path) + /** + * Loads all available tasks. + * + * Looks for tasks in the symfony core, the current project and all project plugins. + * + * @param sfProjectConfiguration $configuration The project configuration + */ + public function loadTasks(sfProjectConfiguration $configuration) { - if (is_dir($taskPath = $path.'/lib/task')) - { - $dirs[] = $taskPath; - } + // Symfony core tasks + $dirs = [sfConfig::get('sf_symfony_lib_dir').'/task']; + + // Plugin tasks + foreach ($configuration->getPluginPaths() as $path) { + if (is_dir($taskPath = $path.'/lib/task')) { + $dirs[] = $taskPath; + } + } + + // project tasks + $dirs[] = sfConfig::get('sf_lib_dir').'/task'; + + $finder = sfFinder::type('file')->name('*Task.class.php'); + foreach ($finder->in($dirs) as $file) { + $this->taskFiles[basename($file, '.class.php')] = $file; + } + + // register local autoloader for tasks + spl_autoload_register([$this, 'autoloadTask']); + + // require tasks + foreach ($this->taskFiles as $task => $file) { + // forces autoloading of each task class + class_exists($task, true); + } + + // unregister local autoloader + spl_autoload_unregister([$this, 'autoloadTask']); } - // project tasks - $dirs[] = sfConfig::get('sf_lib_dir').'/task'; - - $finder = sfFinder::type('file')->name('*Task.class.php'); - foreach ($finder->in($dirs) as $file) + /** + * Autoloads a task class. + * + * @param string $class The task class name + * + * @return bool + */ + public function autoloadTask($class) { - $this->taskFiles[basename($file, '.class.php')] = $file; - } + if (isset($this->taskFiles[$class])) { + require_once $this->taskFiles[$class]; - // register local autoloader for tasks - spl_autoload_register(array($this, 'autoloadTask')); + return true; + } - // require tasks - foreach ($this->taskFiles as $task => $file) - { - // forces autoloading of each task class - class_exists($task, true); + return false; } - // unregister local autoloader - spl_autoload_unregister(array($this, 'autoloadTask')); - } - - /** - * Autoloads a task class - * - * @param string $class The task class name - * - * @return Boolean - */ - public function autoloadTask($class) - { - if (isset($this->taskFiles[$class])) + /** + * @see sfCommandApplication + */ + public function getLongVersion() { - require_once $this->taskFiles[$class]; - - return true; + return sprintf('%s version %s (%s)', $this->getName(), $this->formatter->format($this->getVersion(), 'INFO'), sfConfig::get('sf_symfony_lib_dir'))."\n"; } - - return false; - } - - /** - * @see sfCommandApplication - */ - public function getLongVersion() - { - return sprintf('%s version %s (%s)', $this->getName(), $this->formatter->format($this->getVersion(), 'INFO'), sfConfig::get('sf_symfony_lib_dir'))."\n"; - } } diff --git a/lib/config/sfApplicationConfiguration.class.php b/lib/config/sfApplicationConfiguration.class.php index 44aad4c80..be879754f 100644 --- a/lib/config/sfApplicationConfiguration.class.php +++ b/lib/config/sfApplicationConfiguration.class.php @@ -11,692 +11,646 @@ /** * sfConfiguration represents a configuration for a symfony application. * - * @package symfony - * @subpackage config * @author Fabien Potencier - * @version SVN: $Id$ */ abstract class sfApplicationConfiguration extends ProjectConfiguration { - static protected - $coreLoaded = false, - $loadedHelpers = array(); - - protected - $configCache = null, - $application = null, - $environment = null, - $debug = false, - $config = array(), - $cache = null; - - /** - * Constructor. - * - * @param string $environment The environment name - * @param Boolean $debug true to enable debug mode - * @param string $rootDir The project root directory - * @param sfEventDispatcher $dispatcher An event dispatcher - */ - public function __construct($environment, $debug, $rootDir = null, sfEventDispatcher $dispatcher = null) - { - $this->environment = $environment; - $this->debug = (boolean) $debug; - $this->application = str_replace('Configuration', '', get_class($this)); - - parent::__construct($rootDir, $dispatcher); - - $this->configure(); - - $this->initConfiguration(); - - if (sfConfig::get('sf_check_lock')) + protected static $coreLoaded = false; + protected static $loadedHelpers = []; + + protected $configCache; + protected $application; + protected $environment; + protected $debug = false; + protected $config = []; + protected $cache; + + /** + * Constructor. + * + * @param string $environment The environment name + * @param bool $debug true to enable debug mode + * @param string $rootDir The project root directory + * @param sfEventDispatcher $dispatcher An event dispatcher + */ + public function __construct($environment, $debug, $rootDir = null, ?sfEventDispatcher $dispatcher = null) { - $this->checkLock(); - } + $this->environment = $environment; + $this->debug = (bool) $debug; + $this->application = str_replace('Configuration', '', get_class($this)); - if (is_file($file = sfConfig::get('sf_app_cache_dir').'/config/configuration.php')) - { - $this->cache = require $file; + parent::__construct($rootDir, $dispatcher); + + $this->configure(); + + $this->initConfiguration(); + + if (sfConfig::get('sf_check_lock')) { + $this->checkLock(); + } + + if (is_file($file = sfConfig::get('sf_app_cache_dir').'/config/configuration.php')) { + $this->cache = require $file; + } + + $this->initialize(); + + // store current sfConfig values + $this->config = sfConfig::getAll(); } - $this->initialize(); - - // store current sfConfig values - $this->config = sfConfig::getAll(); - } - - /** - * Configures the current configuration. - * - * Override this method if you want to customize your application configuration. - */ - public function configure() - { - } - - /** - * Initialized the current configuration. - * - * Override this method if you want to customize your application initialization. - */ - public function initialize() - { - } - - public function activate() - { - sfConfig::clear(); - sfConfig::add($this->config); - } - - /** - * Various initializations. - */ - public function initConfiguration() - { - $configCache = $this->getConfigCache(); - - // in debug mode, start global timer - if ($this->isDebug() && !sfConfig::get('sf_cli') && !sfWebDebugPanelTimer::isStarted()) + /** + * Configures the current configuration. + * + * Override this method if you want to customize your application configuration. + */ + public function configure() { - sfWebDebugPanelTimer::startTime(); } - // required core classes for the framework - if (!$this->isDebug() && !sfConfig::get('sf_test') && !sfConfig::get('sf_cli') && !self::$coreLoaded) + /** + * Initialized the current configuration. + * + * Override this method if you want to customize your application initialization. + */ + public function initialize() { - $configCache->import('config/core_compile.yml', false); } - // autoloader(s) - $this->dispatcher->connect('autoload.filter_config', array($this, 'filterAutoloadConfig')); - sfAutoload::getInstance()->register(); - if ($this->isDebug()) + public function activate() { - sfAutoloadAgain::getInstance()->register(); + sfConfig::clear(); + sfConfig::add($this->config); } - // load base settings - include($configCache->checkConfig('config/settings.yml')); - if ($file = $configCache->checkConfig('config/app.yml', true)) + /** + * Various initializations. + */ + public function initConfiguration() { - include($file); + $configCache = $this->getConfigCache(); + + // in debug mode, start global timer + if ($this->isDebug() && !sfConfig::get('sf_cli') && !sfWebDebugPanelTimer::isStarted()) { + sfWebDebugPanelTimer::startTime(); + } + + // required core classes for the framework + if (!$this->isDebug() && !sfConfig::get('sf_test') && !sfConfig::get('sf_cli') && !self::$coreLoaded) { + $configCache->import('config/core_compile.yml', false); + } + + // autoloader(s) + $this->dispatcher->connect('autoload.filter_config', [$this, 'filterAutoloadConfig']); + sfAutoload::getInstance()->register(); + if ($this->isDebug()) { + sfAutoloadAgain::getInstance()->register(); + } + + // load base settings + include $configCache->checkConfig('config/settings.yml'); + if ($file = $configCache->checkConfig('config/app.yml', true)) { + include $file; + } + + if (!sfConfig::get('sf_cli') && false !== sfConfig::get('sf_csrf_secret')) { + sfForm::enableCSRFProtection(sfConfig::get('sf_csrf_secret')); + } + + sfWidget::setCharset(sfConfig::get('sf_charset')); + sfValidatorBase::setCharset(sfConfig::get('sf_charset')); + + // force setting default timezone if not set + if ($default_timezone = sfConfig::get('sf_default_timezone')) { + date_default_timezone_set($default_timezone); + } elseif (sfConfig::get('sf_force_default_timezone', true)) { + date_default_timezone_set(@date_default_timezone_get()); + } + + // error settings + // Based on the debug setting ($this->isDebug()), it controls if errors should be displayed + // (display_errors). If the application is not in the debug mode or if it's running in a + // CLI, PHPDBG, or embed server API, then errors are not displayed (display_errors is set + // to 0). However, if the application is in debug mode and errors are not already logged to + // the error log, then errors are displayed (display_errors is set to 1). + if ( + !$this->isDebug() + || !in_array(PHP_SAPI, ['cli', 'phpdbg', 'embed'], true) + ) { + ini_set('display_errors', 0); + } elseif ( + !filter_var(ini_get('log_errors'), FILTER_VALIDATE_BOOLEAN) + || ini_get('error_log') + ) { + // CLI - display errors only if they're not already logged to STDERR + ini_set('display_errors', 1); + } + error_reporting(sfConfig::get('sf_error_reporting')); + + // initialize plugin configuration objects + $this->initializePlugins(); + + // compress output + if (!self::$coreLoaded && sfConfig::get('sf_compressed')) { + ob_start('ob_gzhandler'); + } + + self::$coreLoaded = true; } - if (!sfConfig::get('sf_cli') && false !== sfConfig::get('sf_csrf_secret')) + /** + * Adds enabled plugins to autoload config. + * + * @return array + */ + public function filterAutoloadConfig(sfEvent $event, array $config) { - sfForm::enableCSRFProtection(sfConfig::get('sf_csrf_secret')); - } + foreach ($this->pluginConfigurations as $name => $configuration) { + $config = $configuration->filterAutoloadConfig($event, $config); + } - sfWidget::setCharset(sfConfig::get('sf_charset')); - sfValidatorBase::setCharset(sfConfig::get('sf_charset')); + return $config; + } - // force setting default timezone if not set - if ($default_timezone = sfConfig::get('sf_default_timezone')) + /** + * Returns a configuration cache object for the current configuration. + * + * @return sfConfigCache A sfConfigCache instance + */ + public function getConfigCache() { - date_default_timezone_set($default_timezone); + if (null === $this->configCache) { + $this->configCache = new sfConfigCache($this); + } + + return $this->configCache; } - else if (sfConfig::get('sf_force_default_timezone', true)) + + /** + * Check lock files to see if we're not in a cache cleaning process. + */ + public function checkLock() { - date_default_timezone_set(@date_default_timezone_get()); + if ( + $this->hasLockFile(sfConfig::get('sf_data_dir').DIRECTORY_SEPARATOR.$this->getApplication().'_'.$this->getEnvironment().'-cli.lck', 5) + || $this->hasLockFile(sfConfig::get('sf_data_dir').DIRECTORY_SEPARATOR.$this->getApplication().'_'.$this->getEnvironment().'.lck') + ) { + // application is not available - we'll find the most specific unavailable page... + $files = [ + sfConfig::get('sf_app_config_dir').'/unavailable.php', + sfConfig::get('sf_config_dir').'/unavailable.php', + sfConfig::get('sf_web_dir').'/errors/unavailable.php', + $this->getSymfonyLibDir().'/exception/data/unavailable.php', + ]; + + foreach ($files as $file) { + if (is_readable($file)) { + header('HTTP/1.1 503 Service Temporarily Unavailable'); + header('Status: 503 Service Temporarily Unavailable'); + + include $file; + + break; + } + } + + exit(1); + } } - // error settings - // PHP >= 5.2.4 supports stdout/stderr instead of bool here: https://www.php.net/manual/en/errorfunc.configuration.php#ini.display-errors - ini_set('display_errors', $this->isDebug() ? sfConfig::get('sf_display_errors', 'stdout') : ''); - error_reporting(sfConfig::get('sf_error_reporting')); + /** + * Sets the project root directory. + * + * @param string $rootDir The project root directory + */ + public function setRootDir($rootDir) + { + parent::setRootDir($rootDir); - // initialize plugin configuration objects - $this->initializePlugins(); + sfConfig::add([ + 'sf_app' => $this->getApplication(), + 'sf_environment' => $this->getEnvironment(), + 'sf_debug' => $this->isDebug(), + 'sf_cli' => PHP_SAPI === 'cli', + ]); - // compress output - if (!self::$coreLoaded && sfConfig::get('sf_compressed')) - { - ob_start('ob_gzhandler'); + $this->setAppDir(sfConfig::get('sf_apps_dir').DIRECTORY_SEPARATOR.$this->getApplication()); } - self::$coreLoaded = true; - } - - /** - * Initializes plugin configuration objects. - */ - protected function initializePlugins() - { - foreach ($this->pluginConfigurations as $name => $configuration) + /** + * Sets the app directory. + * + * @param string $appDir the absolute path to the app dir + */ + public function setAppDir($appDir) { - if ( - false === $configuration->initialize() - && - is_readable($config = $configuration->getRootDir().'/config/config.php') - ) - { - require $config; - } + sfConfig::add([ + 'sf_app_dir' => $appDir, + + // SF_APP_DIR directory structure + 'sf_app_config_dir' => $appDir.DIRECTORY_SEPARATOR.'config', + 'sf_app_lib_dir' => $appDir.DIRECTORY_SEPARATOR.'lib', + 'sf_app_module_dir' => $appDir.DIRECTORY_SEPARATOR.'modules', + 'sf_app_template_dir' => $appDir.DIRECTORY_SEPARATOR.'templates', + 'sf_app_i18n_dir' => $appDir.DIRECTORY_SEPARATOR.'i18n', + ]); } - } - - /** - * Adds enabled plugins to autoload config. - * - * @param sfEvent $event - * @param array $config - * - * @return array - */ - public function filterAutoloadConfig(sfEvent $event, array $config) - { - foreach ($this->pluginConfigurations as $name => $configuration) + + /** + * @see sfProjectConfiguration + */ + public function setCacheDir($cacheDir) { - $config = $configuration->filterAutoloadConfig($event, $config); + parent::setCacheDir($cacheDir); + + sfConfig::add([ + 'sf_app_base_cache_dir' => $cacheDir.DIRECTORY_SEPARATOR.$this->getApplication(), + 'sf_app_cache_dir' => $appCacheDir = $cacheDir.DIRECTORY_SEPARATOR.$this->getApplication().DIRECTORY_SEPARATOR.$this->getEnvironment(), + + // SF_CACHE_DIR directory structure + 'sf_template_cache_dir' => $appCacheDir.DIRECTORY_SEPARATOR.'template', + 'sf_i18n_cache_dir' => $appCacheDir.DIRECTORY_SEPARATOR.'i18n', + 'sf_config_cache_dir' => $appCacheDir.DIRECTORY_SEPARATOR.'config', + 'sf_test_cache_dir' => $appCacheDir.DIRECTORY_SEPARATOR.'test', + 'sf_module_cache_dir' => $appCacheDir.DIRECTORY_SEPARATOR.'modules', + ]); } - return $config; - } - - /** - * Returns a configuration cache object for the current configuration. - * - * @return sfConfigCache A sfConfigCache instance - */ - public function getConfigCache() - { - if (null === $this->configCache) + /** + * Gets directories where controller classes are stored for a given module. + * + * @param string $moduleName The module name + * + * @return array An array of directories + */ + public function getControllerDirs($moduleName) { - $this->configCache = new sfConfigCache($this); + if (!isset($this->cache['getControllerDirs'][$moduleName])) { + $dirs = []; + + $dirs[sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/actions'] = false; // application + + foreach ($this->getPluginPaths() as $path) { + if (is_dir($dir = $path.'/modules/'.$moduleName.'/actions')) { + $dirs[$dir] = true; // plugins + } + } + + if (is_dir($dir = $this->getSymfonyLibDir().'/controller/'.$moduleName.'/actions')) { + $dirs[$dir] = true; // core modules + } + + $this->cache['getControllerDirs'][$moduleName] = $dirs; + } + + return $this->cache['getControllerDirs'][$moduleName]; } - return $this->configCache; - } - - /** - * Check lock files to see if we're not in a cache cleaning process. - * - * @return void - */ - public function checkLock() - { - if ( - $this->hasLockFile(sfConfig::get('sf_data_dir').DIRECTORY_SEPARATOR.$this->getApplication().'_'.$this->getEnvironment().'-cli.lck', 5) - || - $this->hasLockFile(sfConfig::get('sf_data_dir').DIRECTORY_SEPARATOR.$this->getApplication().'_'.$this->getEnvironment().'.lck') - ) + /** + * Gets directories where lib files are stored for a given module. + * + * @param string $moduleName The module name + * + * @return array An array of directories + */ + public function getLibDirs($moduleName) { - // application is not available - we'll find the most specific unavailable page... - $files = array( - sfConfig::get('sf_app_config_dir').'/unavailable.php', - sfConfig::get('sf_config_dir').'/unavailable.php', - sfConfig::get('sf_web_dir').'/errors/unavailable.php', - $this->getSymfonyLibDir().'/exception/data/unavailable.php', - ); - - foreach ($files as $file) - { - if (is_readable($file)) - { - header("HTTP/1.1 503 Service Temporarily Unavailable"); - header("Status: 503 Service Temporarily Unavailable"); - - include $file; - break; - } - } + $dirs = []; + + $dirs[] = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/lib'; // application + $dirs = array_merge($dirs, $this->getPluginSubPaths('/modules/'.$moduleName.'/lib')); // plugins + $dirs[] = $this->getSymfonyLibDir().'/controller/'.$moduleName.'/lib'; // core modules + $dirs[] = sfConfig::get('sf_module_cache_dir').'/auto'.ucfirst($moduleName.'/lib'); // generated templates in cache - die(1); + return $dirs; } - } - - /** - * Determines if a lock file is present. - * - * @param string $lockFile Name of the lock file. - * @param integer $maxLockFileLifeTime A max amount of life time for the lock file. - * - * @return bool true, if the lock file is present, otherwise false. - */ - protected function hasLockFile($lockFile, $maxLockFileLifeTime = 0) - { - $isLocked = false; - if (is_readable($lockFile) && ($last_access = fileatime($lockFile))) + + /** + * Gets directories where template files are stored for a given module. + * + * @param string $moduleName The module name + * + * @return array An array of directories + */ + public function getTemplateDirs($moduleName) { - $now = time(); - $timeDiff = $now - $last_access; - - if (!$maxLockFileLifeTime || $timeDiff < $maxLockFileLifeTime) - { - $isLocked = true; - } - else - { - $isLocked = @unlink($lockFile) ? false : true; - } + $dirs = []; + + $dirs[] = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/templates'; // application + $dirs = array_merge($dirs, $this->getPluginSubPaths('/modules/'.$moduleName.'/templates')); // plugins + $dirs[] = $this->getSymfonyLibDir().'/controller/'.$moduleName.'/templates'; // core modules + $dirs[] = sfConfig::get('sf_module_cache_dir').'/auto'.ucfirst($moduleName.'/templates'); // generated templates in cache + + return $dirs; } - return $isLocked; - } - - /** - * Sets the project root directory. - * - * @param string $rootDir The project root directory - */ - public function setRootDir($rootDir) - { - parent::setRootDir($rootDir); - - sfConfig::add(array( - 'sf_app' => $this->getApplication(), - 'sf_environment' => $this->getEnvironment(), - 'sf_debug' => $this->isDebug(), - 'sf_cli' => PHP_SAPI === 'cli', - )); - - $this->setAppDir(sfConfig::get('sf_apps_dir').DIRECTORY_SEPARATOR.$this->getApplication()); - } - - /** - * Sets the app directory. - * - * @param string $appDir The absolute path to the app dir. - */ - public function setAppDir($appDir) - { - sfConfig::add(array( - 'sf_app_dir' => $appDir, - - // SF_APP_DIR directory structure - 'sf_app_config_dir' => $appDir.DIRECTORY_SEPARATOR.'config', - 'sf_app_lib_dir' => $appDir.DIRECTORY_SEPARATOR.'lib', - 'sf_app_module_dir' => $appDir.DIRECTORY_SEPARATOR.'modules', - 'sf_app_template_dir' => $appDir.DIRECTORY_SEPARATOR.'templates', - 'sf_app_i18n_dir' => $appDir.DIRECTORY_SEPARATOR.'i18n', - )); - } - - /** - * @see sfProjectConfiguration - */ - public function setCacheDir($cacheDir) - { - parent::setCacheDir($cacheDir); - - sfConfig::add(array( - 'sf_app_base_cache_dir' => $cacheDir.DIRECTORY_SEPARATOR.$this->getApplication(), - 'sf_app_cache_dir' => $appCacheDir = $cacheDir.DIRECTORY_SEPARATOR.$this->getApplication().DIRECTORY_SEPARATOR.$this->getEnvironment(), - - // SF_CACHE_DIR directory structure - 'sf_template_cache_dir' => $appCacheDir.DIRECTORY_SEPARATOR.'template', - 'sf_i18n_cache_dir' => $appCacheDir.DIRECTORY_SEPARATOR.'i18n', - 'sf_config_cache_dir' => $appCacheDir.DIRECTORY_SEPARATOR.'config', - 'sf_test_cache_dir' => $appCacheDir.DIRECTORY_SEPARATOR.'test', - 'sf_module_cache_dir' => $appCacheDir.DIRECTORY_SEPARATOR.'modules', - )); - } - - /** - * Gets directories where controller classes are stored for a given module. - * - * @param string $moduleName The module name - * - * @return array An array of directories - */ - public function getControllerDirs($moduleName) - { - if (!isset($this->cache['getControllerDirs'][$moduleName])) + /** + * Gets the helper directories for a given module name. + * + * @param string $moduleName The module name + * + * @return array An array of directories + */ + public function getHelperDirs($moduleName = '') { - $dirs = array(); + $dirs = []; - $dirs[sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/actions'] = false; // application + if ($moduleName) { + $dirs[] = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/lib/helper'; // module - foreach ($this->getPluginPaths() as $path) - { - if (is_dir($dir = $path.'/modules/'.$moduleName.'/actions')) - { - $dirs[$dir] = true; // plugins + $dirs = array_merge($dirs, $this->getPluginSubPaths('/modules/'.$moduleName.'/lib/helper')); } - } - if (is_dir($dir = $this->getSymfonyLibDir().'/controller/'.$moduleName.'/actions')) - { - $dirs[$dir] = true; // core modules - } + return array_merge( + $dirs, + [ + sfConfig::get('sf_app_lib_dir').'/helper', // application + sfConfig::get('sf_lib_dir').'/helper', // project + ], + $this->getPluginSubPaths('/lib/helper'), // plugins + [$this->getSymfonyLibDir().'/helper'] // symfony + ); + } - $this->cache['getControllerDirs'][$moduleName] = $dirs; + /** + * Gets the template directory to use for a given module and template file. + * + * @param string $moduleName The module name + * @param string $templateFile The template file + * + * @return string A template directory + */ + public function getTemplateDir($moduleName, $templateFile) + { + if (!isset($this->cache['getTemplateDir'][$moduleName][$templateFile])) { + $this->cache['getTemplateDir'][$moduleName][$templateFile] = null; + foreach ($this->getTemplateDirs($moduleName) as $dir) { + if (is_readable($dir.'/'.$templateFile)) { + $this->cache['getTemplateDir'][$moduleName][$templateFile] = $dir; + + break; + } + } + } + + return $this->cache['getTemplateDir'][$moduleName][$templateFile]; } - return $this->cache['getControllerDirs'][$moduleName]; - } - - /** - * Gets directories where lib files are stored for a given module. - * - * @param string $moduleName The module name - * - * @return array An array of directories - */ - public function getLibDirs($moduleName) - { - $dirs = array(); - - $dirs[] = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/lib'; // application - $dirs = array_merge($dirs, $this->getPluginSubPaths('/modules/'.$moduleName.'/lib')); // plugins - $dirs[] = $this->getSymfonyLibDir().'/controller/'.$moduleName.'/lib'; // core modules - $dirs[] = sfConfig::get('sf_module_cache_dir').'/auto'.ucfirst($moduleName.'/lib'); // generated templates in cache - - return $dirs; - } - - /** - * Gets directories where template files are stored for a given module. - * - * @param string $moduleName The module name - * - * @return array An array of directories - */ - public function getTemplateDirs($moduleName) - { - $dirs = array(); - - $dirs[] = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/templates'; // application - $dirs = array_merge($dirs, $this->getPluginSubPaths('/modules/'.$moduleName.'/templates')); // plugins - $dirs[] = $this->getSymfonyLibDir().'/controller/'.$moduleName.'/templates'; // core modules - $dirs[] = sfConfig::get('sf_module_cache_dir').'/auto'.ucfirst($moduleName.'/templates'); // generated templates in cache - - return $dirs; - } - - /** - * Gets the helper directories for a given module name. - * - * @param string $moduleName The module name - * - * @return array An array of directories - */ - public function getHelperDirs($moduleName = '') - { - $dirs = array(); - - if ($moduleName) + /** + * Gets the template to use for a given module and template file. + * + * @param string $moduleName The module name + * @param string $templateFile The template file + * + * @return string A template path + */ + public function getTemplatePath($moduleName, $templateFile) { - $dirs[] = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/lib/helper'; // module + $dir = $this->getTemplateDir($moduleName, $templateFile); - $dirs = array_merge($dirs, $this->getPluginSubPaths('/modules/'.$moduleName.'/lib/helper')); + return $dir ? $dir.'/'.$templateFile : null; } - return array_merge( - $dirs, - array( - sfConfig::get('sf_app_lib_dir').'/helper', // application - sfConfig::get('sf_lib_dir').'/helper', // project - ), - $this->getPluginSubPaths('/lib/helper'), // plugins - array($this->getSymfonyLibDir().'/helper') // symfony - ); - } - - /** - * Gets the template directory to use for a given module and template file. - * - * @param string $moduleName The module name - * @param string $templateFile The template file - * - * @return string A template directory - */ - public function getTemplateDir($moduleName, $templateFile) - { - if (!isset($this->cache['getTemplateDir'][$moduleName][$templateFile])) + /** + * @see sfProjectConfiguration + */ + public function getPluginPaths() { - $this->cache['getTemplateDir'][$moduleName][$templateFile] = null; - foreach ($this->getTemplateDirs($moduleName) as $dir) - { - if (is_readable($dir.'/'.$templateFile)) - { - $this->cache['getTemplateDir'][$moduleName][$templateFile] = $dir; - break; + if (!isset($this->cache['getPluginPaths'])) { + $this->cache['getPluginPaths'] = parent::getPluginPaths(); } - } + + return $this->cache['getPluginPaths']; } - return $this->cache['getTemplateDir'][$moduleName][$templateFile]; - } - - /** - * Gets the template to use for a given module and template file. - * - * @param string $moduleName The module name - * @param string $templateFile The template file - * - * @return string A template path - */ - public function getTemplatePath($moduleName, $templateFile) - { - $dir = $this->getTemplateDir($moduleName, $templateFile); - - return $dir ? $dir.'/'.$templateFile : null; - } - /** - * @see sfProjectConfiguration - */ - public function getPluginPaths() - { - if (!isset($this->cache['getPluginPaths'])) + /** + * Gets the decorator directories. + * + * @return array An array of the decorator directories + */ + public function getDecoratorDirs() { - $this->cache['getPluginPaths'] = parent::getPluginPaths(); + return [sfConfig::get('sf_app_template_dir')]; } - return $this->cache['getPluginPaths']; - } - - /** - * Gets the decorator directories. - * - * @return array An array of the decorator directories - */ - public function getDecoratorDirs() - { - return array(sfConfig::get('sf_app_template_dir')); - } - - /** - * Gets the decorator directory for a given template. - * - * @param string $template The template file - * - * @return string A template directory - */ - public function getDecoratorDir($template) - { - foreach ($this->getDecoratorDirs() as $dir) + /** + * Gets the decorator directory for a given template. + * + * @param string $template The template file + * + * @return string A template directory + */ + public function getDecoratorDir($template) { - if (is_readable($dir.'/'.$template)) - { - return $dir; - } + foreach ($this->getDecoratorDirs() as $dir) { + if (is_readable($dir.'/'.$template)) { + return $dir; + } + } } - } - - /** - * Gets the i18n directories to use globally. - * - * @return array An array of i18n directories - */ - public function getI18NGlobalDirs() - { - $dirs = array(); - - // application - if (is_dir($dir = sfConfig::get('sf_app_i18n_dir'))) + + /** + * Gets the i18n directories to use globally. + * + * @return array An array of i18n directories + */ + public function getI18NGlobalDirs() { - $dirs[] = $dir; + $dirs = []; + + // application + if (is_dir($dir = sfConfig::get('sf_app_i18n_dir'))) { + $dirs[] = $dir; + } + + // plugins + return array_merge($dirs, $this->getPluginSubPaths('/i18n')); } - // plugins - return array_merge($dirs, $this->getPluginSubPaths('/i18n')); - } - - /** - * Gets the i18n directories to use for a given module. - * - * @param string $moduleName The module name - * - * @return array An array of i18n directories - */ - public function getI18NDirs($moduleName) - { - $dirs = array(); - - // module - if (is_dir($dir = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/i18n')) + /** + * Gets the i18n directories to use for a given module. + * + * @param string $moduleName The module name + * + * @return array An array of i18n directories + */ + public function getI18NDirs($moduleName) { - $dirs[] = $dir; + $dirs = []; + + // module + if (is_dir($dir = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/i18n')) { + $dirs[] = $dir; + } + + // application + if (is_dir($dir = sfConfig::get('sf_app_i18n_dir'))) { + $dirs[] = $dir; + } + + return array_merge( + $dirs, + $this->getPluginSubPaths('/modules/'.$moduleName.'/i18n'), // module in plugins + $this->getPluginSubPaths('/i18n') // plugins + ); } - // application - if (is_dir($dir = sfConfig::get('sf_app_i18n_dir'))) + /** + * Gets the configuration file paths for a given relative configuration path. + * + * @param string $configPath The configuration path + * + * @return array An array of paths + */ + public function getConfigPaths($configPath) { - $dirs[] = $dir; + $globalConfigPath = basename(dirname($configPath)).'/'.basename($configPath); + + $files = [ + $this->getSymfonyLibDir().'/config/'.$globalConfigPath, // symfony + ]; + + foreach ($this->getPluginPaths() as $path) { + if (is_file($file = $path.'/'.$globalConfigPath)) { + $files[] = $file; // plugins + } + } + + $files = array_merge($files, [ + $this->getRootDir().'/'.$globalConfigPath, // project + $this->getRootDir().'/'.$configPath, // project + sfConfig::get('sf_app_dir').'/'.$globalConfigPath, // application + sfConfig::get('sf_app_cache_dir').'/'.$configPath, // generated modules + ]); + + foreach ($this->getPluginPaths() as $path) { + if (is_file($file = $path.'/'.$configPath)) { + $files[] = $file; // plugins + } + } + + $files[] = sfConfig::get('sf_app_dir').'/'.$configPath; // module + + $configs = []; + foreach (array_unique($files) as $file) { + if (is_readable($file)) { + $configs[] = $file; + } + } + + return $configs; } - return array_merge( - $dirs, - $this->getPluginSubPaths('/modules/'.$moduleName.'/i18n'), // module in plugins - $this->getPluginSubPaths('/i18n') // plugins - ); - } - - /** - * Gets the configuration file paths for a given relative configuration path. - * - * @param string $configPath The configuration path - * - * @return array An array of paths - */ - public function getConfigPaths($configPath) - { - $globalConfigPath = basename(dirname($configPath)).'/'.basename($configPath); - - $files = array( - $this->getSymfonyLibDir().'/config/'.$globalConfigPath, // symfony - ); - - foreach ($this->getPluginPaths() as $path) + /** + * Loads helpers. + * + * @param array|string $helpers An array of helpers to load + * @param string $moduleName A module name (optional) + */ + public function loadHelpers($helpers, $moduleName = '') { - if (is_file($file = $path.'/'.$globalConfigPath)) - { - $files[] = $file; // plugins - } + foreach ((array) $helpers as $helperName) { + if (isset(self::$loadedHelpers[$helperName])) { + continue; + } + + if (isset($this->cache['loadedHelpers'][$moduleName][$helperName])) { + include_once $this->cache['loadedHelpers'][$moduleName][$helperName]; + } elseif (isset($this->cache['loadedHelpers'][''][$helperName])) { + include_once $this->cache['loadedHelpers'][''][$helperName]; + } else { + $fileName = $helperName.'Helper.php'; + + if (!isset($dirs)) { + $dirs = $this->getHelperDirs($moduleName); + } + + foreach ($dirs as $dir) { + $included = false; + if (is_readable($dir.'/'.$fileName)) { + include_once $dir.'/'.$fileName; + $included = true; + + break; + } + } + + if (!$included) { + throw new InvalidArgumentException(sprintf('Unable to load "%sHelper.php" helper in: %s.', $helperName, implode(', ', array_map(['sfDebug', 'shortenFilePath'], $dirs)))); + } + } + + self::$loadedHelpers[$helperName] = true; + } } - $files = array_merge($files, array( - $this->getRootDir().'/'.$globalConfigPath, // project - $this->getRootDir().'/'.$configPath, // project - sfConfig::get('sf_app_dir').'/'.$globalConfigPath, // application - sfConfig::get('sf_app_cache_dir').'/'.$configPath, // generated modules - )); - - foreach ($this->getPluginPaths() as $path) + /** + * Returns the application name. + * + * @return string The application name + */ + public function getApplication() { - if (is_file($file = $path.'/'.$configPath)) - { - $files[] = $file; // plugins - } + return $this->application; } - $files[] = sfConfig::get('sf_app_dir').'/'.$configPath; // module - - $configs = array(); - foreach (array_unique($files) as $file) + /** + * Returns the environment name. + * + * @return string The environment name + */ + public function getEnvironment() { - if (is_readable($file)) - { - $configs[] = $file; - } + return $this->environment; } - return $configs; - } - - /** - * Loads helpers. - * - * @param array|string $helpers An array of helpers to load - * @param string $moduleName A module name (optional) - */ - public function loadHelpers($helpers, $moduleName = '') - { - foreach ((array) $helpers as $helperName) + /** + * Returns true if this configuration has debug enabled. + * + * @return bool true if the configuration has debug enabled, false otherwise + */ + public function isDebug() { - if (isset(self::$loadedHelpers[$helperName])) - { - continue; - } - - if (isset($this->cache['loadedHelpers'][$moduleName][$helperName])) - { - include_once $this->cache['loadedHelpers'][$moduleName][$helperName]; - } - else if (isset($this->cache['loadedHelpers'][''][$helperName])) - { - include_once $this->cache['loadedHelpers'][''][$helperName]; - } - else - { - $fileName = $helperName.'Helper.php'; - - if (!isset($dirs)) - { - $dirs = $this->getHelperDirs($moduleName); - } + return $this->debug; + } - foreach ($dirs as $dir) - { - $included = false; - if (is_readable($dir.'/'.$fileName)) - { - include_once $dir.'/'.$fileName; - $included = true; - break; - } + /** + * Initializes plugin configuration objects. + */ + protected function initializePlugins() + { + foreach ($this->pluginConfigurations as $name => $configuration) { + if ( + false === $configuration->initialize() + && is_readable($config = $configuration->getRootDir().'/config/config.php') + ) { + require $config; + } } + } - if (!$included) - { - throw new InvalidArgumentException(sprintf('Unable to load "%sHelper.php" helper in: %s.', $helperName, implode(', ', array_map(array('sfDebug', 'shortenFilePath'), $dirs)))); + /** + * Determines if a lock file is present. + * + * @param string $lockFile name of the lock file + * @param int $maxLockFileLifeTime a max amount of life time for the lock file + * + * @return bool true, if the lock file is present, otherwise false + */ + protected function hasLockFile($lockFile, $maxLockFileLifeTime = 0) + { + $isLocked = false; + if (is_readable($lockFile) && ($last_access = fileatime($lockFile))) { + $now = time(); + $timeDiff = $now - $last_access; + + if (!$maxLockFileLifeTime || $timeDiff < $maxLockFileLifeTime) { + $isLocked = true; + } else { + $isLocked = @unlink($lockFile) ? false : true; + } } - } - self::$loadedHelpers[$helperName] = true; + return $isLocked; } - } - - /** - * Returns the application name. - * - * @return string The application name - */ - public function getApplication() - { - return $this->application; - } - - /** - * Returns the environment name. - * - * @return string The environment name - */ - public function getEnvironment() - { - return $this->environment; - } - - /** - * Returns true if this configuration has debug enabled. - * - * @return Boolean true if the configuration has debug enabled, false otherwise - */ - public function isDebug() - { - return $this->debug; - } } diff --git a/lib/config/sfAutoloadConfigHandler.class.php b/lib/config/sfAutoloadConfigHandler.class.php index 9132e5ce1..2b7cb7a5c 100755 --- a/lib/config/sfAutoloadConfigHandler.class.php +++ b/lib/config/sfAutoloadConfigHandler.class.php @@ -10,180 +10,158 @@ */ /** - * - * @package symfony - * @subpackage config * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ class sfAutoloadConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler. - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - */ - public function execute($configFiles) - { - // set our required categories list and initialize our handler - $this->initialize(array('required_categories' => array('autoload'))); - - $data = array(); - foreach ($this->parse($configFiles) as $name => $mapping) + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + */ + public function execute($configFiles) { - $data[] = sprintf("\n // %s", $name); - - foreach ($mapping as $class => $file) - { - $data[] = sprintf(" '%s' => '%s',", $class, str_replace('\\', '\\\\', $file)); - } - } + // set our required categories list and initialize our handler + $this->initialize(['required_categories' => ['autoload']]); - // compile data - return sprintf("parse($configFiles) as $mapping) - { - foreach ($mapping as $class => $file) - { - $mappings[$class] = $file; - } - } + $data = []; + foreach ($this->parse($configFiles) as $name => $mapping) { + $data[] = sprintf("\n // %s", $name); - return $mappings; - } + foreach ($mapping as $class => $file) { + $data[] = sprintf(" '%s' => '%s',", $class, str_replace('\\', '\\\\', $file)); + } + } - protected function parse(array $configFiles) - { - // parse the yaml - $config = static::getConfiguration($configFiles); + // compile data + return sprintf( + " $entry) + public function evaluate($configFiles) { - $mapping = array(); - - // file mapping or directory mapping? - if (isset($entry['files'])) - { - // file mapping - foreach ($entry['files'] as $class => $file) - { - $mapping[strtolower($class)] = $file; - } - } - else - { - // directory mapping - $ext = isset($entry['ext']) ? $entry['ext'] : '.php'; - $path = $entry['path']; - - // we automatically add our php classes - require_once(sfConfig::get('sf_symfony_lib_dir').'/util/sfFinder.class.php'); - $finder = sfFinder::type('file')->name('*'.$ext)->follow_link(); - - // recursive mapping? - $recursive = isset($entry['recursive']) ? $entry['recursive'] : false; - if (!$recursive) - { - $finder->maxdepth(0); + $mappings = []; + foreach ($this->parse($configFiles) as $mapping) { + foreach ($mapping as $class => $file) { + $mappings[$class] = $file; + } } - // exclude files or directories? - if (isset($entry['exclude']) && is_array($entry['exclude'])) - { - $finder->prune($entry['exclude'])->discard($entry['exclude']); - } + return $mappings; + } - if ($matches = glob($path)) - { - foreach ($finder->in($matches) as $file) - { - $mapping = array_merge($mapping, $this->parseFile($path, $file, isset($entry['prefix']) ? $entry['prefix'] : '')); - } + public static function parseFile($path, $file, $prefix) + { + $mapping = []; + preg_match_all('~^\s*(?:abstract\s+|final\s+)?(?:class|interface|trait)\s+(\w+)~mi', file_get_contents($file), $classes); + foreach ($classes[1] as $class) { + $localPrefix = ''; + if ($prefix) { + // FIXME: does not work for plugins installed with a symlink + preg_match('~^'.str_replace('\*', '(.+?)', preg_quote(str_replace('/', DIRECTORY_SEPARATOR, $path), '~')).'~', str_replace('/', DIRECTORY_SEPARATOR, $file), $match); + if (isset($match[$prefix])) { + $localPrefix = $match[$prefix].'/'; + } + } + + $mapping[$localPrefix.strtolower($class)] = $file; } - } - $mappings[$name] = $mapping; + return $mapping; } - return $mappings; - } - - static public function parseFile($path, $file, $prefix) - { - $mapping = array(); - preg_match_all('~^\s*(?:abstract\s+|final\s+)?(?:class|interface|trait)\s+(\w+)~mi', file_get_contents($file), $classes); - foreach ($classes[1] as $class) + /** + * @see sfConfigHandler + */ + public static function getConfiguration(array $configFiles) { - $localPrefix = ''; - if ($prefix) - { - // FIXME: does not work for plugins installed with a symlink - preg_match('~^'.str_replace('\*', '(.+?)', preg_quote(str_replace('/', DIRECTORY_SEPARATOR, $path), '~')).'~', str_replace('/', DIRECTORY_SEPARATOR, $file), $match); - if (isset($match[$prefix])) - { - $localPrefix = $match[$prefix].'/'; + $configuration = sfProjectConfiguration::getActive(); + + $pluginPaths = $configuration->getPluginPaths(); + $pluginConfigFiles = []; + + // move plugin files to front + foreach ($configFiles as $i => $configFile) { + $configFilePath = str_replace(DIRECTORY_SEPARATOR, '/', $configFile); + $path = str_replace(DIRECTORY_SEPARATOR, '/', realpath(implode('/', array_slice(explode('/', $configFilePath), 0, -2)))); + if (in_array($path, $pluginPaths)) { + $pluginConfigFiles[] = $configFile; + unset($configFiles[$i]); + } } - } - $mapping[$localPrefix.strtolower($class)] = $file; - } + $configFiles = array_merge($pluginConfigFiles, $configFiles); - return $mapping; - } + $config = static::replaceConstants(static::parseYamls($configFiles)); - /** - * @see sfConfigHandler - * @inheritdoc - */ - static public function getConfiguration(array $configFiles) - { - $configuration = sfProjectConfiguration::getActive(); + foreach ($config['autoload'] as $name => $values) { + if (isset($values['path'])) { + $config['autoload'][$name]['path'] = static::replacePath($values['path']); + } + } - $pluginPaths = $configuration->getPluginPaths(); - $pluginConfigFiles = array(); + $event = $configuration->getEventDispatcher()->filter(new sfEvent(__CLASS__, 'autoload.filter_config'), $config); + $config = $event->getReturnValue(); - // move plugin files to front - foreach ($configFiles as $i => $configFile) - { - $configFilePath = str_replace(DIRECTORY_SEPARATOR, '/', $configFile); - $path = str_replace(DIRECTORY_SEPARATOR, '/', realpath(implode('/', array_slice(explode('/', $configFilePath), 0, -2)))); - if (in_array($path, $pluginPaths)) - { - $pluginConfigFiles[] = $configFile; - unset($configFiles[$i]); - } + return $config; } - $configFiles = array_merge($pluginConfigFiles, $configFiles); - - $config = static::replaceConstants(static::parseYamls($configFiles)); - - foreach ($config['autoload'] as $name => $values) + protected function parse(array $configFiles) { - if (isset($values['path'])) - { - $config['autoload'][$name]['path'] = static::replacePath($values['path']); - } - } - - $event = $configuration->getEventDispatcher()->filter(new sfEvent(__CLASS__, 'autoload.filter_config'), $config); - $config = $event->getReturnValue(); + // parse the yaml + $config = static::getConfiguration($configFiles); + + $mappings = []; + foreach ($config['autoload'] as $name => $entry) { + $mapping = []; + + // file mapping or directory mapping? + if (isset($entry['files'])) { + // file mapping + foreach ($entry['files'] as $class => $file) { + $mapping[strtolower($class)] = $file; + } + } else { + // directory mapping + $ext = isset($entry['ext']) ? $entry['ext'] : '.php'; + $path = $entry['path']; + + // we automatically add our php classes + require_once sfConfig::get('sf_symfony_lib_dir').'/util/sfFinder.class.php'; + $finder = sfFinder::type('file')->name('*'.$ext)->follow_link(); + + // recursive mapping? + $recursive = isset($entry['recursive']) ? $entry['recursive'] : false; + if (!$recursive) { + $finder->maxdepth(0); + } + + // exclude files or directories? + if (isset($entry['exclude']) && is_array($entry['exclude'])) { + $finder->prune($entry['exclude'])->discard($entry['exclude']); + } + + if ($matches = glob($path)) { + foreach ($finder->in($matches) as $file) { + $mapping = array_merge($mapping, $this->parseFile($path, $file, isset($entry['prefix']) ? $entry['prefix'] : '')); + } + } + } + + $mappings[$name] = $mapping; + } - return $config; - } + return $mappings; + } } diff --git a/lib/config/sfCacheConfigHandler.class.php b/lib/config/sfCacheConfigHandler.class.php index ae826c8d0..b531d9555 100644 --- a/lib/config/sfCacheConfigHandler.class.php +++ b/lib/config/sfCacheConfigHandler.class.php @@ -11,105 +11,107 @@ /** * sfCacheConfigHandler allows you to configure cache. * - * @package symfony - * @subpackage config * @author Fabien Potencier - * @version SVN: $Id$ */ class sfCacheConfigHandler extends sfYamlConfigHandler { - protected - $cacheConfig = array(); - - /** - * Executes this configuration handler. - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - * @throws sfInitializationException If a cache.yml key check fails - */ - public function execute($configFiles) - { - // parse the yaml - $this->yamlConfig = static::getConfiguration($configFiles); - - // iterate through all action names - $data = array(); - $first = true; - foreach ($this->yamlConfig as $actionName => $values) + protected $cacheConfig = []; + + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + * @throws sfInitializationException If a cache.yml key check fails + */ + public function execute($configFiles) { - if ($actionName == 'all') - { - continue; - } - - $data[] = $this->addCache($actionName); - - $first = false; + // parse the yaml + $this->yamlConfig = static::getConfiguration($configFiles); + + // iterate through all action names + $data = []; + $first = true; + foreach ($this->yamlConfig as $actionName => $values) { + if ('all' == $actionName) { + continue; + } + + $data[] = $this->addCache($actionName); + + $first = false; + } + + // general cache configuration + $data[] = $this->addCache('DEFAULT'); + + // compile data + $retval = sprintf( + "addCache('DEFAULT'); + /** + * @see sfConfigHandler + */ + public static function getConfiguration(array $configFiles) + { + return static::flattenConfiguration(static::parseYamls($configFiles)); + } - // compile data - $retval = sprintf("getConfigValue('enabled', $actionName); - /** - * Returns a single addCache statement. - * - * @param string $actionName The action name - * - * @return string PHP code for the addCache statement - */ - protected function addCache($actionName = '') - { - $data = array(); + // cache with or without loayout + $withLayout = $this->getConfigValue('with_layout', $actionName) ? 'true' : 'false'; - // enabled? - $enabled = $this->getConfigValue('enabled', $actionName); + // lifetime + $lifeTime = !$enabled ? '0' : $this->getConfigValue('lifetime', $actionName, '0'); - // cache with or without loayout - $withLayout = $this->getConfigValue('with_layout', $actionName) ? 'true' : 'false'; + // client_lifetime + $clientLifetime = !$enabled ? '0' : $this->getConfigValue('client_lifetime', $actionName, $lifeTime); - // lifetime - $lifeTime = !$enabled ? '0' : $this->getConfigValue('lifetime', $actionName, '0'); + // contextual + $contextual = $this->getConfigValue('contextual', $actionName) ? 'true' : 'false'; - // client_lifetime - $clientLifetime = !$enabled ? '0' : $this->getConfigValue('client_lifetime', $actionName, $lifeTime, '0'); + // vary + $vary = $this->getConfigValue('vary', $actionName, []); + if (!is_array($vary)) { + $vary = [$vary]; + } - // contextual - $contextual = $this->getConfigValue('contextual', $actionName) ? 'true' : 'false'; + // add cache information to cache manager + $data[] = sprintf( + "\$this->addCache(\$moduleName, '%s', array('withLayout' => %s, 'lifeTime' => %s, 'clientLifeTime' => %s, 'contextual' => %s, 'vary' => %s));\n", + $actionName, + $withLayout, + $lifeTime, + $clientLifetime, + $contextual, + str_replace("\n", '', var_export($vary, true)) + ); - // vary - $vary = $this->getConfigValue('vary', $actionName, array()); - if (!is_array($vary)) - { - $vary = array($vary); + return implode("\n", $data); } - - // add cache information to cache manager - $data[] = sprintf("\$this->addCache(\$moduleName, '%s', array('withLayout' => %s, 'lifeTime' => %s, 'clientLifeTime' => %s, 'contextual' => %s, 'vary' => %s));\n", - $actionName, $withLayout, $lifeTime, $clientLifetime, $contextual, str_replace("\n", '', var_export($vary, true))); - - return implode("\n", $data); - } - - /** - * @see sfConfigHandler - * @inheritdoc - */ - static public function getConfiguration(array $configFiles) - { - return static::flattenConfiguration(static::parseYamls($configFiles)); - } } diff --git a/lib/config/sfCompileConfigHandler.class.php b/lib/config/sfCompileConfigHandler.class.php index bac091ef4..7bbd8cffb 100644 --- a/lib/config/sfCompileConfigHandler.class.php +++ b/lib/config/sfCompileConfigHandler.class.php @@ -13,82 +13,77 @@ * sfCompileConfigHandler gathers multiple files and puts them into a single file. * Upon creation of the new file, all comments and blank lines are removed. * - * @package symfony - * @subpackage config * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ class sfCompileConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler. - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - */ - public function execute($configFiles) - { - // parse the yaml - $config = static::getConfiguration($configFiles); + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + */ + public function execute($configFiles) + { + // parse the yaml + $config = static::getConfiguration($configFiles); - // init our data - $data = ''; + // init our data + $data = ''; - // let's do our fancy work - foreach ($config as $file) - { - if (!is_readable($file)) - { - // file doesn't exist - throw new sfParseException(sprintf('Configuration file "%s" specifies nonexistent or unreadable file "%s".', $configFiles[0], $file)); - } + // let's do our fancy work + foreach ($config as $file) { + if (!is_readable($file)) { + // file doesn't exist + throw new sfParseException(sprintf('Configuration file "%s" specifies nonexistent or unreadable file "%s".', $configFiles[0], $file)); + } - $contents = file_get_contents($file); + $contents = file_get_contents($file); - // strip comments (not in debug mode) - if (!sfConfig::get('sf_debug')) - { - $contents = sfToolkit::stripComments($contents); - } + // strip comments (not in debug mode) + if (!sfConfig::get('sf_debug')) { + $contents = sfToolkit::stripComments($contents); + } - // strip php tags - $contents = sfToolkit::pregtr($contents, array('/^\s*<\?(php\s*)?/m' => '', '/^\s*\?>/m' => '')); + // strip php tags + $contents = sfToolkit::pregtr($contents, ['/^\s*<\?(php\s*)?/m' => '', '/^\s*\?>/m' => '']); - // replace windows and mac format with unix format - $contents = str_replace("\r", "\n", $contents); + // replace windows and mac format with unix format + $contents = str_replace("\r", "\n", $contents); - // replace multiple new lines with a single newline - $contents = preg_replace(array('/\s+$/Sm', '/\n+/S'), "\n", $contents); + // replace multiple new lines with a single newline + $contents = preg_replace(['/\s+$/Sm', '/\n+/S'], "\n", $contents); - // append file data - $data .= "\n".$contents; - } + // append file data + $data .= "\n".$contents; + } - // compile data - return sprintf(" - * @version SVN: $Id$ */ class sfConfig { - protected static - $config = array(); + protected static $config = []; - /** - * Retrieves a config parameter. - * - * @param string $name A config parameter name - * @param mixed $default A default config parameter value - * - * @return mixed A config parameter value, if the config parameter exists, otherwise null - */ - public static function get($name, $default = null) - { - return isset(self::$config[$name]) ? self::$config[$name] : $default; - } + /** + * Retrieves a config parameter. + * + * @param string $name A config parameter name + * @param mixed $default A default config parameter value + * + * @return mixed A config parameter value, if the config parameter exists, otherwise null + */ + public static function get($name, $default = null) + { + return isset(self::$config[$name]) ? self::$config[$name] : $default; + } - /** - * Indicates whether or not a config parameter exists. - * - * @param string $name A config parameter name - * - * @return bool true, if the config parameter exists, otherwise false - */ - public static function has($name) - { - return array_key_exists($name, self::$config); - } + /** + * Indicates whether or not a config parameter exists. + * + * @param string $name A config parameter name + * + * @return bool true, if the config parameter exists, otherwise false + */ + public static function has($name) + { + return array_key_exists($name, self::$config); + } - /** - * Sets a config parameter. - * - * If a config parameter with the name already exists the value will be overridden. - * - * @param string $name A config parameter name - * @param mixed $value A config parameter value - */ - public static function set($name, $value) - { - self::$config[$name] = $value; - } + /** + * Sets a config parameter. + * + * If a config parameter with the name already exists the value will be overridden. + * + * @param string $name A config parameter name + * @param mixed $value A config parameter value + */ + public static function set($name, $value) + { + self::$config[$name] = $value; + } - /** - * Sets an array of config parameters. - * - * If an existing config parameter name matches any of the keys in the supplied - * array, the associated value will be overridden. - * - * @param array $parameters An associative array of config parameters and their associated values - */ - public static function add($parameters = array()) - { - self::$config = array_merge(self::$config, $parameters); - } + /** + * Sets an array of config parameters. + * + * If an existing config parameter name matches any of the keys in the supplied + * array, the associated value will be overridden. + * + * @param array $parameters An associative array of config parameters and their associated values + */ + public static function add($parameters = []) + { + self::$config = array_merge(self::$config, $parameters); + } - /** - * Retrieves all configuration parameters. - * - * @return array An associative array of configuration parameters. - */ - public static function getAll() - { - return self::$config; - } + /** + * Retrieves all configuration parameters. + * + * @return array an associative array of configuration parameters + */ + public static function getAll() + { + return self::$config; + } - /** - * Clears all current config parameters. - */ - public static function clear() - { - self::$config = array(); - } + /** + * Clears all current config parameters. + */ + public static function clear() + { + self::$config = []; + } } diff --git a/lib/config/sfConfigCache.class.php b/lib/config/sfConfigCache.class.php index 31134a3c8..e0b5ca871 100644 --- a/lib/config/sfConfigCache.class.php +++ b/lib/config/sfConfigCache.class.php @@ -14,381 +14,341 @@ * make it easy-to-use, yet still provide a PHP formatted result for direct * inclusion into your modules. * - * @package symfony - * @subpackage config * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ class sfConfigCache { - protected - $configuration = null, - $handlers = array(), - $userHandlers = array(); - - /** - * Constructor - * - * @param sfApplicationConfiguration $configuration A sfApplicationConfiguration instance - */ - public function __construct(sfApplicationConfiguration $configuration) - { - $this->configuration = $configuration; - } - - /** - * Loads a configuration handler. - * - * @param string $handler The handler to use when parsing a configuration file - * @param array $configs An array of absolute filesystem paths to configuration files - * @param string $cache An absolute filesystem path to the cache file that will be written - * - * @throws sfConfigurationException If a requested configuration file does not have an associated configuration handler - */ - protected function callHandler($handler, $configs, $cache) - { - if (count($this->handlers) == 0) + protected $configuration; + protected $handlers = []; + protected $userHandlers = []; + + /** + * Constructor. + * + * @param sfApplicationConfiguration $configuration A sfApplicationConfiguration instance + */ + public function __construct(sfApplicationConfiguration $configuration) { - // we need to load the handlers first - $this->loadConfigHandlers(); + $this->configuration = $configuration; } - if (count($this->userHandlers) != 0) + /** + * Checks to see if a configuration file has been modified and if so + * recompile the cache file associated with it. + * + * The recompilation only occurs in a non debug environment. + * + * If the configuration file path is relative, symfony will look in directories + * defined in the sfConfiguration::getConfigPaths() method. + * + * @param string $configPath A filesystem path to a configuration file + * @param bool $optional If true, config path does not need to exist + * + * @return string An absolute filesystem path to the cache filename associated with this specified configuration file + * + * @throws sfConfigurationException If a requested configuration file does not exist + * + * @see sfConfiguration::getConfigPaths() + */ + public function checkConfig($configPath, $optional = false) { - // we load user defined handlers - $this->mergeUserConfigHandlers(); - } + if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled')) { + $timer = sfTimerManager::getTimer('Configuration'); + } - // handler instance to call for this configuration file - $handlerInstance = null; + // the cache filename we'll be using + $cache = $this->getCacheName($configPath); - $handler = str_replace(DIRECTORY_SEPARATOR, '/', $handler); + if (!sfConfig::get('sf_debug') && !sfConfig::get('sf_test') && is_readable($cache)) { + return $cache; + } - // grab the base name of the handler - $basename = basename($handler); - if (isset($this->handlers[$handler])) - { - // we have a handler associated with the full configuration path - $handlerInstance = $this->getHandler($handler); - } - else if (isset($this->handlers[$basename])) - { - // we have a handler associated with the configuration base name - $handlerInstance = $this->getHandler($basename); - } - else - { - // let's see if we have any wildcard handlers registered that match this basename - foreach (array_keys($this->handlers) as $key) - { - // replace wildcard chars in the configuration - $pattern = strtr($key, array('.' => '\.', '*' => '(.*?)')); - $matches = array(); - - // create pattern from config - if (preg_match('#'.$pattern.'$#', $handler, $matches)) - { - $handlerInstance = $this->getHandler($key); - array_shift($matches); - $handlerInstance->getParameterHolder()->set('wildcardValues', $matches); - - break; + if (!sfToolkit::isPathAbsolute($configPath)) { + $files = $this->configuration->getConfigPaths($configPath); + } else { + $files = is_readable($configPath) ? [$configPath] : []; } - } - } - if (!$handlerInstance) - { - // we do not have a registered handler for this file - throw new sfConfigurationException(sprintf('Configuration file "%s" does not have a registered handler.', implode(', ', $configs))); - } + if (!isset($files[0])) { + if ($optional) { + return null; + } - // call the handler and retrieve the cache data - $data = $handlerInstance->execute($configs); - - $this->writeCacheFile($handler, $cache, $data); - } - - /** - * Returns the config handler configured for the given name - * - * @param string $name The config handler name - * - * @return sfConfigHandler A sfConfigHandler instance - */ - protected function getHandler($name) - { - if (is_array($this->handlers[$name])) - { - $class = $this->handlers[$name][0]; - $this->handlers[$name] = new $class($this->handlers[$name][1]); - } + // configuration does not exist + throw new sfConfigurationException(sprintf('Configuration "%s" does not exist or is unreadable.', $configPath)); + } - return $this->handlers[$name]; - } - - /** - * Checks to see if a configuration file has been modified and if so - * recompile the cache file associated with it. - * - * The recompilation only occurs in a non debug environment. - * - * If the configuration file path is relative, symfony will look in directories - * defined in the sfConfiguration::getConfigPaths() method. - * - * @param string $configPath A filesystem path to a configuration file - * @param boolean $optional If true, config path does not need to exist - * - * @return string An absolute filesystem path to the cache filename associated with this specified configuration file - * - * @throws sfConfigurationException If a requested configuration file does not exist - * - * @see sfConfiguration::getConfigPaths() - */ - public function checkConfig($configPath, $optional = false) - { - if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled')) - { - $timer = sfTimerManager::getTimer('Configuration'); - } + // find the more recent configuration file last modification time + $mtime = 0; + foreach ($files as $file) { + if (filemtime($file) > $mtime) { + $mtime = filemtime($file); + } + } - // the cache filename we'll be using - $cache = $this->getCacheName($configPath); + if (!is_readable($cache) || $mtime > filemtime($cache)) { + // configuration has changed so we need to reparse it + $this->callHandler($configPath, $files, $cache); + } - if (!sfConfig::get('sf_debug') && !sfConfig::get('sf_test') && is_readable($cache)) - { - return $cache; - } + if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled')) { + // @var $timer sfTimer + $timer->addTime(); + } - if (!sfToolkit::isPathAbsolute($configPath)) - { - $files = $this->configuration->getConfigPaths($configPath); + return $cache; } - else + + /** + * Clears all configuration cache files. + */ + public function clear() { - $files = is_readable($configPath) ? array($configPath) : array(); + sfToolkit::clearDirectory(sfConfig::get('sf_config_cache_dir')); } - if (!isset($files[0])) + /** + * Converts a normal filename into a cache filename. + * + * @param string $config A normal filename + * + * @return string An absolute filesystem path to a cache filename + */ + public function getCacheName($config) { - if ($optional) - { - return null; - } + if (strlen($config) > 3 && ctype_alpha($config[0]) && ':' == $config[1] && ('\\' == $config[2] || '/' == $config[2])) { + // file is a windows absolute path, strip off the drive letter + $config = substr($config, 3); + } - // configuration does not exist - throw new sfConfigurationException(sprintf('Configuration "%s" does not exist or is unreadable.', $configPath)); - } + // replace unfriendly filename characters with an underscore + $config = str_replace(['\\', '/', ' '], '_', $config); + $config .= '.php'; - // find the more recent configuration file last modification time - $mtime = 0; - foreach ($files as $file) - { - if (filemtime($file) > $mtime) - { - $mtime = filemtime($file); - } + return sfConfig::get('sf_config_cache_dir').'/'.$config; } - if (!is_readable($cache) || $mtime > filemtime($cache)) + /** + * Imports a configuration file. + * + * @param string $config A filesystem path to a configuration file + * @param bool $once Only allow this configuration file to be included once per request? + * @param bool $optional Only include if true + * + * @see checkConfig() + */ + public function import($config, $once = true, $optional = false) { - // configuration has changed so we need to reparse it - $this->callHandler($configPath, $files, $cache); - } + $cache = $this->checkConfig($config, $optional); - if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled')) - { - /** @var $timer sfTimer */ - $timer->addTime(); + if ($optional && !$cache) { + return; + } + + // include cache file + if ($once) { + include_once $cache; + } else { + include $cache; + } } - return $cache; - } - - /** - * Clears all configuration cache files. - */ - public function clear() - { - sfToolkit::clearDirectory(sfConfig::get('sf_config_cache_dir')); - } - - /** - * Converts a normal filename into a cache filename. - * - * @param string $config A normal filename - * - * @return string An absolute filesystem path to a cache filename - */ - public function getCacheName($config) - { - if (strlen($config) > 3 && ctype_alpha($config[0]) && $config[1] == ':' && ($config[2] == '\\' || $config[2] == '/')) + /** + * Registers a configuration handler. + * + * @param string $handler The handler to use when parsing a configuration file + * @param class $class A configuration handler class + * @param string $params An array of options for the handler class initialization + */ + public function registerConfigHandler($handler, $class, $params = []) { - // file is a windows absolute path, strip off the drive letter - $config = substr($config, 3); + $this->userHandlers[$handler] = new $class($params); } - // replace unfriendly filename characters with an underscore - $config = str_replace(array('\\', '/', ' '), '_', $config); - $config .= '.php'; - - return sfConfig::get('sf_config_cache_dir').'/'.$config; - } - - /** - * Imports a configuration file. - * - * @param string $config A filesystem path to a configuration file - * @param bool $once Only allow this configuration file to be included once per request? - * @param bool $optional Only include if true - * - * @see checkConfig() - */ - public function import($config, $once = true, $optional = false) - { - $cache = $this->checkConfig($config, $optional); - - if ($optional && !$cache) + /** + * Loads a configuration handler. + * + * @param string $handler The handler to use when parsing a configuration file + * @param array $configs An array of absolute filesystem paths to configuration files + * @param string $cache An absolute filesystem path to the cache file that will be written + * + * @throws sfConfigurationException If a requested configuration file does not have an associated configuration handler + */ + protected function callHandler($handler, $configs, $cache) { - return; + if (0 == count($this->handlers)) { + // we need to load the handlers first + $this->loadConfigHandlers(); + } + + if (0 != count($this->userHandlers)) { + // we load user defined handlers + $this->mergeUserConfigHandlers(); + } + + // handler instance to call for this configuration file + $handlerInstance = null; + + $handler = str_replace(DIRECTORY_SEPARATOR, '/', $handler); + + // grab the base name of the handler + $basename = basename($handler); + if (isset($this->handlers[$handler])) { + // we have a handler associated with the full configuration path + $handlerInstance = $this->getHandler($handler); + } elseif (isset($this->handlers[$basename])) { + // we have a handler associated with the configuration base name + $handlerInstance = $this->getHandler($basename); + } else { + // let's see if we have any wildcard handlers registered that match this basename + foreach (array_keys($this->handlers) as $key) { + // replace wildcard chars in the configuration + $pattern = strtr($key, ['.' => '\.', '*' => '(.*?)']); + $matches = []; + + // create pattern from config + if (preg_match('#'.$pattern.'$#', $handler, $matches)) { + $handlerInstance = $this->getHandler($key); + array_shift($matches); + $handlerInstance->getParameterHolder()->set('wildcardValues', $matches); + + break; + } + } + } + + if (!$handlerInstance) { + // we do not have a registered handler for this file + throw new sfConfigurationException(sprintf('Configuration file "%s" does not have a registered handler.', implode(', ', $configs))); + } + + // call the handler and retrieve the cache data + $data = $handlerInstance->execute($configs); + + $this->writeCacheFile($handler, $cache, $data); } - // include cache file - if ($once) + /** + * Returns the config handler configured for the given name. + * + * @param string $name The config handler name + * + * @return sfConfigHandler A sfConfigHandler instance + */ + protected function getHandler($name) { - include_once($cache); + if (is_array($this->handlers[$name])) { + $class = $this->handlers[$name][0]; + $this->handlers[$name] = new $class($this->handlers[$name][1]); + } + + return $this->handlers[$name]; } - else + + /** + * Loads all configuration application and module level handlers. + * + * @throws sfConfigurationException If a configuration related error occurs + */ + protected function loadConfigHandlers() { - include($cache); - } - } + // manually create our config_handlers.yml handler + $this->handlers['config_handlers.yml'] = new sfRootConfigHandler(); - /** - * Loads all configuration application and module level handlers. - * - * @throws sfConfigurationException If a configuration related error occurs. - */ - protected function loadConfigHandlers() - { - // manually create our config_handlers.yml handler - $this->handlers['config_handlers.yml'] = new sfRootConfigHandler(); + // application configuration handlers - // application configuration handlers + require $this->checkConfig('config/config_handlers.yml'); - require $this->checkConfig('config/config_handlers.yml'); + // module level configuration handlers - // module level configuration handlers + // checks modules directory exists + if (!is_readable($sf_app_module_dir = sfConfig::get('sf_app_module_dir'))) { + return; + } - // checks modules directory exists - if (!is_readable($sf_app_module_dir = sfConfig::get('sf_app_module_dir'))) - { - return; - } + // ignore names + $ignore = ['.', '..', 'CVS', '.svn']; - // ignore names - $ignore = array('.', '..', 'CVS', '.svn'); + // create a file pointer to the module dir + $fp = opendir($sf_app_module_dir); - // create a file pointer to the module dir - $fp = opendir($sf_app_module_dir); + // loop through the directory and grab the modules + while (($directory = readdir($fp)) !== false) { + if (in_array($directory, $ignore)) { + continue; + } - // loop through the directory and grab the modules - while (($directory = readdir($fp)) !== false) - { - if (in_array($directory, $ignore)) - { - continue; - } + $configPath = $sf_app_module_dir.'/'.$directory.'/config/config_handlers.yml'; - $configPath = $sf_app_module_dir.'/'.$directory.'/config/config_handlers.yml'; + if (is_readable($configPath)) { + // initialize the root configuration handler with this module name + $params = ['module_level' => true, 'module_name' => $directory]; - if (is_readable($configPath)) - { - // initialize the root configuration handler with this module name - $params = array('module_level' => true, 'module_name' => $directory); + $this->handlers['config_handlers.yml']->initialize($params); - $this->handlers['config_handlers.yml']->initialize($params); + // replace module dir path with a special keyword that + // checkConfig knows how to use + $configPath = 'modules/'.$directory.'/config/config_handlers.yml'; - // replace module dir path with a special keyword that - // checkConfig knows how to use - $configPath = 'modules/'.$directory.'/config/config_handlers.yml'; + require $this->checkConfig($configPath); + } + } - require $this->checkConfig($configPath); - } + // close file pointer + closedir($fp); } - // close file pointer - closedir($fp); - } - - /** - * Writes a cache file. - * - * @param string $config An absolute filesystem path to a configuration file - * @param string $cache An absolute filesystem path to the cache file that will be written - * @param string $data Data to be written to the cache file - * - * @throws sfCacheException If the cache file cannot be written - */ - protected function writeCacheFile($config, $cache, $data) - { - $current_umask = umask(0000); - $cacheDir = dirname($cache); - if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) + /** + * Writes a cache file. + * + * @param string $config An absolute filesystem path to a configuration file + * @param string $cache An absolute filesystem path to the cache file that will be written + * @param string $data Data to be written to the cache file + * + * @throws sfCacheException If the cache file cannot be written + */ + protected function writeCacheFile($config, $cache, $data) { - throw new \sfCacheException(sprintf('Failed to make cache directory "%s" while generating cache for configuration file "%s".', $cacheDir, $config)); - } + $current_umask = umask(0000); + $cacheDir = dirname($cache); + if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) { + throw new sfCacheException(sprintf('Failed to make cache directory "%s" while generating cache for configuration file "%s".', $cacheDir, $config)); + } - $tmpFile = tempnam($cacheDir, basename($cache)); + $tmpFile = tempnam($cacheDir, basename($cache)); - if (!$fp = @fopen($tmpFile, 'wb')) - { - throw new sfCacheException(sprintf('Failed to write cache file "%s" generated from configuration file "%s".', $tmpFile, $config)); - } + if (!$fp = @fopen($tmpFile, 'wb')) { + throw new sfCacheException(sprintf('Failed to write cache file "%s" generated from configuration file "%s".', $tmpFile, $config)); + } - @fwrite($fp, $data); - @fclose($fp); + @fwrite($fp, $data); + @fclose($fp); - // Hack from Agavi (http://trac.agavi.org/changeset/3979) - // With php < 5.2.6 on win32, renaming to an already existing file doesn't work, but copy does, - // so we simply assume that when rename() fails that we are on win32 and try to use copy() - if (!@rename($tmpFile, $cache)) - { - if (copy($tmpFile, $cache)) - { - unlink($tmpFile); - } + // Hack from Agavi (http://trac.agavi.org/changeset/3979) + // With php < 5.2.6 on win32, renaming to an already existing file doesn't work, but copy does, + // so we simply assume that when rename() fails that we are on win32 and try to use copy() + if (!@rename($tmpFile, $cache)) { + if (copy($tmpFile, $cache)) { + unlink($tmpFile); + } + } + + if (file_exists($cache) && is_writeable($cache)) { + chmod($cache, 0666); + } + umask($current_umask); } - if (file_exists($cache) && is_writeable($cache)) { - chmod($cache, 0666); + /** + * Merges configuration handlers from the config_handlers.yml + * and the ones defined with registerConfigHandler(). + */ + protected function mergeUserConfigHandlers() + { + // user defined configuration handlers + $this->handlers = array_merge($this->handlers, $this->userHandlers); + + $this->userHandlers = []; } - umask($current_umask); - } - - /** - * Registers a configuration handler. - * - * @param string $handler The handler to use when parsing a configuration file - * @param class $class A configuration handler class - * @param string $params An array of options for the handler class initialization - */ - public function registerConfigHandler($handler, $class, $params = array()) - { - $this->userHandlers[$handler] = new $class($params); - } - - /** - * Merges configuration handlers from the config_handlers.yml - * and the ones defined with registerConfigHandler() - * - */ - protected function mergeUserConfigHandlers() - { - // user defined configuration handlers - $this->handlers = array_merge($this->handlers, $this->userHandlers); - - $this->userHandlers = array(); - } } diff --git a/lib/config/sfConfigHandler.class.php b/lib/config/sfConfigHandler.class.php index 40b650759..1c402f540 100644 --- a/lib/config/sfConfigHandler.class.php +++ b/lib/config/sfConfigHandler.class.php @@ -14,122 +14,111 @@ * file pertaining to any information they like and still have it auto-generate * PHP code. * - * @package symfony - * @subpackage config * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ abstract class sfConfigHandler { - /** @var sfParameterHolder */ - protected - $parameterHolder = null; + /** @var sfParameterHolder */ + protected $parameterHolder; - /** - * Class constructor. - * - * @see initialize() - * @param array|null $parameters - */ - public function __construct($parameters = null) - { - $this->initialize($parameters); - } - - /** - * Initializes this configuration handler. - * - * @param array $parameters An associative array of initialization parameters - * - * @return void - * - * @throws sfInitializationException If an error occurs while initializing this ConfigHandler - */ - public function initialize($parameters = null) - { - $this->parameterHolder = new sfParameterHolder(); - $this->parameterHolder->add($parameters); - } - - /** - * Executes this configuration handler - * - * @param array $configFiles An array of filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - */ - abstract public function execute($configFiles); - - /** - * Replaces constant identifiers in a value. - * - * If the value is an array replacements are made recursively. - * - * @param mixed $value The value on which to run the replacement procedure - * - * @return string|mixed|array The new value - */ - static public function replaceConstants($value) - { - if (is_array($value)) + /** + * Class constructor. + * + * @see initialize() + * + * @param array|null $parameters + */ + public function __construct($parameters = null) { - array_walk_recursive($value, function(& $value) { $value = sfToolkit::replaceConstants($value); }); + $this->initialize($parameters); } - else + + /** + * Initializes this configuration handler. + * + * @param array $parameters An associative array of initialization parameters + * + * @throws sfInitializationException If an error occurs while initializing this ConfigHandler + */ + public function initialize($parameters = null) { - $value = sfToolkit::replaceConstants($value); + $this->parameterHolder = new sfParameterHolder(); + $this->parameterHolder->add($parameters); } - return $value; - } + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + */ + abstract public function execute($configFiles); - /** - * Replaces a relative filesystem path with an absolute one. - * - * @param string $path A relative filesystem path - * - * @return string The new path - */ - static public function replacePath($path) - { - if (is_array($path)) + /** + * Replaces constant identifiers in a value. + * + * If the value is an array replacements are made recursively. + * + * @param mixed $value The value on which to run the replacement procedure + * + * @return array|mixed|string The new value + */ + public static function replaceConstants($value) { - array_walk_recursive($path, function(&$path) { $path = sfConfigHandler::replacePath($path); }); + if (is_array($value)) { + array_walk_recursive($value, function (&$value) { $value = sfToolkit::replaceConstants($value); }); + } else { + $value = sfToolkit::replaceConstants($value); + } + + return $value; } - else + + /** + * Replaces a relative filesystem path with an absolute one. + * + * @param string $path A relative filesystem path + * + * @return string The new path + */ + public static function replacePath($path) { - if (!sfToolkit::isPathAbsolute($path)) - { - // not an absolute path so we'll prepend to it - $path = sfConfig::get('sf_app_dir').'/'.$path; - } - } + if (is_array($path)) { + array_walk_recursive($path, function (&$path) { $path = sfConfigHandler::replacePath($path); }); + } else { + if (!sfToolkit::isPathAbsolute($path)) { + // not an absolute path so we'll prepend to it + $path = sfConfig::get('sf_app_dir').'/'.$path; + } + } - return $path; - } + return $path; + } - /** - * Gets the parameter holder for this configuration handler. - * - * @return sfParameterHolder A sfParameterHolder instance - */ - public function getParameterHolder() - { - return $this->parameterHolder; - } + /** + * Gets the parameter holder for this configuration handler. + * + * @return sfParameterHolder A sfParameterHolder instance + */ + public function getParameterHolder() + { + return $this->parameterHolder; + } - /** - * Returns the configuration for the current config handler. - * - * @param array $configFiles An array of ordered configuration files - * @throws LogicException no matter what - */ - static public function getConfiguration(array $configFiles) - { - throw new LogicException('You must call the ::getConfiguration() method on a concrete config handler class'); - } + /** + * Returns the configuration for the current config handler. + * + * @param array $configFiles An array of ordered configuration files + * + * @throws LogicException no matter what + */ + public static function getConfiguration(array $configFiles) + { + throw new LogicException('You must call the ::getConfiguration() method on a concrete config handler class'); + } } diff --git a/lib/config/sfDatabaseConfigHandler.class.php b/lib/config/sfDatabaseConfigHandler.class.php index 224f8cdb0..c1ed33ac6 100644 --- a/lib/config/sfDatabaseConfigHandler.class.php +++ b/lib/config/sfDatabaseConfigHandler.class.php @@ -14,137 +14,125 @@ * configuration file that will be created for you automatically upon first * request. * - * @package symfony - * @subpackage config * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ class sfDatabaseConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler. - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - */ - public function execute($configFiles) - { - list($includes, $data) = $this->parse($configFiles); - - foreach ($includes as $i => $include) + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + */ + public function execute($configFiles) { - $includes[$i] = sprintf("require_once('%s');", $include); - } + list($includes, $data) = $this->parse($configFiles); - foreach ($data as $name => $database) - { - $data[$name] = sprintf("\n'%s' => new %s(%s),", $name, $database[0], var_export($database[1], true)); - } - - // compile data - return sprintf(" $include) { + $includes[$i] = sprintf("require_once('%s');", $include); + } - public function evaluate($configFiles) - { - list($includes, $data) = $this->parse($configFiles); + foreach ($data as $name => $database) { + $data[$name] = sprintf("\n'%s' => new %s(%s),", $name, $database[0], var_export($database[1], true)); + } - foreach ($includes as $i => $include) - { - require_once($include); + // compile data + return sprintf( + " $database) + public function evaluate($configFiles) { - $databases[$name] = new $database[0]($database[1]); - } + list($includes, $data) = $this->parse($configFiles); - return $databases; - } + foreach ($includes as $i => $include) { + require_once $include; + } - protected function parse($configFiles) - { - // parse the yaml - $config = static::getConfiguration($configFiles); + $databases = []; + foreach ($data as $name => $database) { + $databases[$name] = new $database[0]($database[1]); + } - // init our data and includes arrays - $data = array(); - $databases = array(); - $includes = array(); + return $databases; + } - // get a list of database connections - foreach ($config as $name => $dbConfig) + /** + * @see sfConfigHandler + */ + public static function getConfiguration(array $configFiles) { - // is this category already registered? - if (in_array($name, $databases)) - { - // this category is already registered - throw new sfParseException(sprintf('Configuration file "%s" specifies previously registered category "%s".', $configFiles[0], $name)); - } - - // add this database - $databases[] = $name; - - // let's do our fancy work - if (!isset($dbConfig['class'])) - { - // missing class key - throw new sfParseException(sprintf('Configuration file "%s" specifies category "%s" with missing class key.', $configFiles[0], $name)); - } - - if (isset($dbConfig['file'])) - { - // we have a file to include - if (!is_readable($dbConfig['file'])) - { - // database file doesn't exist - throw new sfParseException(sprintf('Configuration file "%s" specifies class "%s" with nonexistent or unreadable file "%s".', $configFiles[0], $dbConfig['class'], $dbConfig['file'])); - } - - // append our data - $includes[] = $dbConfig['file']; - } + $config = static::replaceConstants(static::flattenConfigurationWithEnvironment(static::parseYamls($configFiles))); - // parse parameters - $parameters = array(); - if (isset($dbConfig['param'])) - { - $parameters = $dbConfig['param']; - } - $parameters['name'] = $name; + foreach ($config as $name => $dbConfig) { + if (isset($dbConfig['file'])) { + $config[$name]['file'] = static::replacePath($dbConfig['file']); + } + } - // append new data - $data[$name] = array($dbConfig['class'], $parameters); + return $config; } - return array($includes, $data); - } - - /** - * @see sfConfigHandler - * @inheritdoc - */ - static public function getConfiguration(array $configFiles) - { - $config = static::replaceConstants(static::flattenConfigurationWithEnvironment(static::parseYamls($configFiles))); - - foreach ($config as $name => $dbConfig) + protected function parse($configFiles) { - if (isset($dbConfig['file'])) - { - $config[$name]['file'] = static::replacePath($dbConfig['file']); - } - } + // parse the yaml + $config = static::getConfiguration($configFiles); + + // init our data and includes arrays + $data = []; + $databases = []; + $includes = []; + + // get a list of database connections + foreach ($config as $name => $dbConfig) { + // is this category already registered? + if (in_array($name, $databases)) { + // this category is already registered + throw new sfParseException(sprintf('Configuration file "%s" specifies previously registered category "%s".', $configFiles[0], $name)); + } + + // add this database + $databases[] = $name; + + // let's do our fancy work + if (!isset($dbConfig['class'])) { + // missing class key + throw new sfParseException(sprintf('Configuration file "%s" specifies category "%s" with missing class key.', $configFiles[0], $name)); + } + + if (isset($dbConfig['file'])) { + // we have a file to include + if (!is_readable($dbConfig['file'])) { + // database file doesn't exist + throw new sfParseException(sprintf('Configuration file "%s" specifies class "%s" with nonexistent or unreadable file "%s".', $configFiles[0], $dbConfig['class'], $dbConfig['file'])); + } + + // append our data + $includes[] = $dbConfig['file']; + } + + // parse parameters + $parameters = []; + if (isset($dbConfig['param'])) { + $parameters = $dbConfig['param']; + } + $parameters['name'] = $name; + + // append new data + $data[$name] = [$dbConfig['class'], $parameters]; + } - return $config; - } + return [$includes, $data]; + } } diff --git a/lib/config/sfDefineEnvironmentConfigHandler.class.php b/lib/config/sfDefineEnvironmentConfigHandler.class.php index 224dc2525..b43dd0b1a 100644 --- a/lib/config/sfDefineEnvironmentConfigHandler.class.php +++ b/lib/config/sfDefineEnvironmentConfigHandler.class.php @@ -9,141 +9,127 @@ */ /** - * - * @package symfony - * @subpackage config * @author Fabien Potencier - * @version SVN: $Id$ */ class sfDefineEnvironmentConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler. - * - * @param string $configFiles An absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - */ - public function execute($configFiles) - { - // get our prefix - $prefix = strtolower($this->getParameterHolder()->get('prefix', '')); - - // add module prefix if needed - if ($this->getParameterHolder()->get('module', false)) + /** + * Executes this configuration handler. + * + * @param string $configFiles An absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + */ + public function execute($configFiles) { - $wildcardValues = $this->getParameterHolder()->get('wildcardValues'); - // either the module name is in wildcard values, or it needs to be inserted on runtime - $moduleName = $wildcardValues ? strtolower($wildcardValues[0]) : "'.strtolower(\$moduleName).'"; - $prefix .= $moduleName."_"; + // get our prefix + $prefix = strtolower($this->getParameterHolder()->get('prefix', '')); + + // add module prefix if needed + if ($this->getParameterHolder()->get('module', false)) { + $wildcardValues = $this->getParameterHolder()->get('wildcardValues'); + // either the module name is in wildcard values, or it needs to be inserted on runtime + $moduleName = $wildcardValues ? strtolower($wildcardValues[0]) : "'.strtolower(\$moduleName).'"; + $prefix .= $moduleName.'_'; + } + + // parse the yaml + $config = static::getConfiguration($configFiles); + + $values = []; + foreach ($config as $category => $keys) { + $values = array_merge($values, $this->getValues($prefix, $category, $keys)); + } + + $data = ''; + foreach ($values as $key => $value) { + $data .= sprintf(" '%s' => %s,\n", $key, var_export($value, true)); + } + + // compile data + $retval = ''; + if ($values) { + $retval = " $keys) + /** + * @see sfConfigHandler + */ + public static function getConfiguration(array $configFiles) { - $values = array_merge($values, $this->getValues($prefix, $category, $keys)); + return static::replaceConstants(static::flattenConfigurationWithEnvironment(static::parseYamls($configFiles))); } - $data = ''; - foreach ($values as $key => $value) + /** + * Gets values from the configuration array. + * + * @param string $prefix The prefix name + * @param string $category The category name + * @param mixed $keys The key/value array + * + * @return array The new key/value array + */ + protected function getValues($prefix, $category, $keys) { - $data .= sprintf(" '%s' => %s,\n", $key, var_export($value, true)); - } + if (!is_array($keys)) { + list($key, $value) = $this->fixCategoryValue($prefix.strtolower($category), '', $keys); - // compile data - $retval = ''; - if ($values) - { - $retval = " $value]; + } - return $retval; - } - - /** - * Gets values from the configuration array. - * - * @param string $prefix The prefix name - * @param string $category The category name - * @param mixed $keys The key/value array - * - * @return array The new key/value array - */ - protected function getValues($prefix, $category, $keys) - { - if (!is_array($keys)) - { - list($key, $value) = $this->fixCategoryValue($prefix.strtolower($category), '', $keys); + $values = []; - return array($key => $value); - } - - $values = array(); + $category = $this->fixCategoryName($category, $prefix); - $category = $this->fixCategoryName($category, $prefix); + // loop through all key/value pairs + foreach ($keys as $key => $value) { + list($key, $value) = $this->fixCategoryValue($category, $key, $value); + $values[$key] = $value; + } - // loop through all key/value pairs - foreach ($keys as $key => $value) - { - list($key, $value) = $this->fixCategoryValue($category, $key, $value); - $values[$key] = $value; + return $values; } - return $values; - } - - /** - * Fixes the category name and replaces constants in the value. - * - * @param string $category The category name - * @param string $key The key name - * @param string $value The value - * - * @return string Return the new key and value - */ - protected function fixCategoryValue($category, $key, $value) - { - return array($category.$key, $value); - } - - /** - * Fixes the category name. - * - * @param string $category The category name - * @param string $prefix The prefix - * - * @return string The fixed category name - */ - protected function fixCategoryName($category, $prefix) - { - // categories starting without a period will be prepended to the key - if ($category[0] != '.') + /** + * Fixes the category name and replaces constants in the value. + * + * @param string $category The category name + * @param string $key The key name + * @param string $value The value + * + * @return string Return the new key and value + */ + protected function fixCategoryValue($category, $key, $value) { - $category = $prefix.$category.'_'; + return [$category.$key, $value]; } - else + + /** + * Fixes the category name. + * + * @param string $category The category name + * @param string $prefix The prefix + * + * @return string The fixed category name + */ + protected function fixCategoryName($category, $prefix) { - $category = $prefix; + // categories starting without a period will be prepended to the key + if ('.' != $category[0]) { + $category = $prefix.$category.'_'; + } else { + $category = $prefix; + } + + return $category; } - - return $category; - } - - /** - * @see sfConfigHandler - * @inheritdoc - */ - static public function getConfiguration(array $configFiles) - { - return static::replaceConstants(static::flattenConfigurationWithEnvironment(static::parseYamls($configFiles))); - } } diff --git a/lib/config/sfFactoryConfigHandler.class.php b/lib/config/sfFactoryConfigHandler.class.php index c42b0e992..95e067f7b 100644 --- a/lib/config/sfFactoryConfigHandler.class.php +++ b/lib/config/sfFactoryConfigHandler.class.php @@ -13,257 +13,262 @@ * sfFactoryConfigHandler allows you to specify which factory implementation the * system will use. * - * @package symfony - * @subpackage config * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ class sfFactoryConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler. - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - */ - public function execute($configFiles) - { - // parse the yaml - $config = static::getConfiguration($configFiles); - - // init our data and includes arrays - $includes = array(); - $instances = array(); - - // available list of factories - $factories = array('view_cache_manager', 'logger', 'i18n', 'controller', 'request', 'response', 'routing', 'storage', 'user', 'view_cache', 'mailer', 'service_container'); - - // let's do our fancy work - foreach ($factories as $factory) + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + */ + public function execute($configFiles) { - // see if the factory exists for this controller - $keys = $config[$factory]; - - if (!isset($keys['class'])) - { - // missing class key - throw new sfParseException(sprintf('Configuration file "%s" specifies category "%s" with missing class key.', $configFiles[0], $factory)); - } - - $class = $keys['class']; - - if (isset($keys['file'])) - { - // we have a file to include - if (!is_readable($keys['file'])) - { - // factory file doesn't exist - throw new sfParseException(sprintf('Configuration file "%s" specifies class "%s" with nonexistent or unreadable file "%s".', $configFiles[0], $class, $keys['file'])); - } + // parse the yaml + $config = static::getConfiguration($configFiles); - // append our data - $includes[] = sprintf("require_once('%s');", $keys['file']); - } - - // parse parameters - $parameters = array(); - if (isset($keys['param'])) - { - if (!is_array($keys['param'])) - { - throw new InvalidArgumentException(sprintf('The "param" key for the "%s" factory must be an array (in %s).', $class, $configFiles[0])); - } + // init our data and includes arrays + $includes = []; + $instances = []; + + // available list of factories + $factories = ['view_cache_manager', 'logger', 'i18n', 'controller', 'request', 'response', 'routing', 'storage', 'user', 'view_cache', 'mailer', 'service_container']; - $parameters = $keys['param']; - } - - // append new data - switch ($factory) - { - case 'controller': - $instances[] = sprintf(" \$class = sfConfig::get('sf_factory_controller', '%s');\n \$this->factories['controller'] = new \$class(\$this);", $class); - break; - - case 'request': - $parameters['no_script_name'] = sfConfig::get('sf_no_script_name'); - $instances[] = sprintf(" \$class = sfConfig::get('sf_factory_request', '%s');\n \$this->factories['request'] = new \$class(\$this->dispatcher, array(), array(), sfConfig::get('sf_factory_request_parameters', %s), sfConfig::get('sf_factory_request_attributes', array()));", $class, var_export($parameters, true)); - break; - - case 'response': - $instances[] = sprintf(" \$class = sfConfig::get('sf_factory_response', '%s');\n \$this->factories['response'] = new \$class(\$this->dispatcher, sfConfig::get('sf_factory_response_parameters', array_merge(array('http_protocol' => isset(\$_SERVER['SERVER_PROTOCOL']) ? \$_SERVER['SERVER_PROTOCOL'] : null), %s)));", $class, var_export($parameters, true)); - // TODO: this is a bit ugly, as it only works for sfWebRequest & sfWebResponse combination. see #3397 - $instances[] = sprintf(" if (\$this->factories['request'] instanceof sfWebRequest \n && \$this->factories['response'] instanceof sfWebResponse \n && 'HEAD' == \$this->factories['request']->getMethod())\n { \n \$this->factories['response']->setHeaderOnly(true);\n }\n"); - break; - - case 'storage': - $defaultParameters = array(); - $defaultParameters[] = sprintf("'auto_shutdown' => false, 'session_id' => \$this->getRequest()->getParameter('%s'),", $parameters['session_name']); - if (is_subclass_of($class, 'sfDatabaseSessionStorage')) - { - $defaultParameters[] = sprintf("'database' => \$this->getDatabaseManager()->getDatabase('%s'),", isset($parameters['database']) ? $parameters['database'] : 'default'); - unset($parameters['database']); - } - - if (isset($config['user']['param']['timeout'])) { - $defaultParameters[] = sprintf("'gc_maxlifetime' => %d,", $config['user']['param']['timeout']); - } - - $instances[] = sprintf(" \$class = sfConfig::get('sf_factory_storage', '%s');\n \$this->factories['storage'] = new \$class(array_merge(array(\n%s\n), sfConfig::get('sf_factory_storage_parameters', %s)));", $class, implode("\n", $defaultParameters), var_export($parameters, true)); - break; - - case 'user': - $instances[] = sprintf(" \$class = sfConfig::get('sf_factory_user', '%s');\n \$this->factories['user'] = new \$class(\$this->dispatcher, \$this->factories['storage'], array_merge(array('auto_shutdown' => false, 'culture' => \$this->factories['request']->getParameter('sf_culture')), sfConfig::get('sf_factory_user_parameters', %s)));", $class, var_export($parameters, true)); - break; - - case 'view_cache': - $instances[] = sprintf("\n if (sfConfig::get('sf_cache'))\n {\n". - " \$class = sfConfig::get('sf_factory_view_cache', '%s');\n". - " \$cache = new \$class(sfConfig::get('sf_factory_view_cache_parameters', %s));\n". - " \$this->factories['viewCacheManager'] = new %s(\$this, \$cache, %s);\n". - " }\n". - " else\n". - " {\n". - " \$this->factories['viewCacheManager'] = null;\n". - " }\n", - $class, var_export($parameters, true), $config['view_cache_manager']['class'], var_export($config['view_cache_manager']['param'], true)); - break; - - case 'i18n': - if (isset($parameters['cache'])) - { - $cache = sprintf(" \$cache = new %s(%s);\n", $parameters['cache']['class'], var_export($parameters['cache']['param'], true)); - unset($parameters['cache']); - } - else - { - $cache = " \$cache = null;\n"; - } - - $instances[] = sprintf("\n if (sfConfig::get('sf_i18n'))\n {\n". - " \$class = sfConfig::get('sf_factory_i18n', '%s');\n". - "%s". - " \$this->factories['i18n'] = new \$class(\$this->configuration, \$cache, %s);\n". - " sfWidgetFormSchemaFormatter::setTranslationCallable(array(\$this->factories['i18n'], '__'));\n". - " }\n" - , $class, $cache, var_export($parameters, true) - ); - break; - - case 'routing': - if (isset($parameters['cache'])) - { - $cache = sprintf(" \$cache = new %s(%s);\n", $parameters['cache']['class'], var_export($parameters['cache']['param'], true)); - unset($parameters['cache']); - } - else - { - $cache = " \$cache = null;\n"; - } - - $instances[] = sprintf(" \$class = sfConfig::get('sf_factory_routing', '%s');\n". - " %s\n". - "\$this->factories['routing'] = new \$class(\$this->dispatcher, \$cache, array_merge(array('auto_shutdown' => false, 'context' => \$this->factories['request']->getRequestContext()), sfConfig::get('sf_factory_routing_parameters', %s)));\n". - "if (\$parameters = \$this->factories['routing']->parse(\$this->factories['request']->getPathInfo()))\n". - "{\n". - " \$this->factories['request']->addRequestParameters(\$parameters);\n". - "}\n", - $class, $cache, var_export($parameters, true) - ); - break; - - case 'logger': - $loggers = ''; - if (isset($parameters['loggers'])) - { - foreach ($parameters['loggers'] as $name => $keys) - { - if (isset($keys['enabled']) && !$keys['enabled']) - { - continue; - } - - if (!isset($keys['class'])) - { + // let's do our fancy work + foreach ($factories as $factory) { + // see if the factory exists for this controller + $keys = $config[$factory]; + + if (!isset($keys['class'])) { // missing class key - throw new sfParseException(sprintf('Configuration file "%s" specifies logger "%s" with missing class key.', $configFiles[0], $name)); - } - - $condition = true; - if (isset($keys['param']['condition'])) - { - $condition = $keys['param']['condition']; - unset($keys['param']['condition']); - } - - if ($condition) - { - // create logger instance - $loggers .= sprintf("\n\$logger = new %s(\$this->dispatcher, array_merge(array('auto_shutdown' => false), %s));\n\$this->factories['logger']->addLogger(\$logger);\n", - $keys['class'], - isset($keys['param']) ? var_export($keys['param'], true) : 'array()' - ); - } + throw new sfParseException(sprintf('Configuration file "%s" specifies category "%s" with missing class key.', $configFiles[0], $factory)); + } + + $class = $keys['class']; + + if (isset($keys['file'])) { + // we have a file to include + if (!is_readable($keys['file'])) { + // factory file doesn't exist + throw new sfParseException(sprintf('Configuration file "%s" specifies class "%s" with nonexistent or unreadable file "%s".', $configFiles[0], $class, $keys['file'])); + } + + // append our data + $includes[] = sprintf("require_once('%s');", $keys['file']); } - unset($parameters['loggers']); - } + // parse parameters + $parameters = []; + if (isset($keys['param'])) { + if (!is_array($keys['param'])) { + throw new InvalidArgumentException(sprintf('The "param" key for the "%s" factory must be an array (in %s).', $class, $configFiles[0])); + } - $instances[] = sprintf( - " \$class = sfConfig::get('sf_factory_logger', '%s');\n \$this->factories['logger'] = new \$class(\$this->dispatcher, array_merge(array('auto_shutdown' => false), sfConfig::get('sf_factory_logger_parameters', %s)));\n". - " %s" - , $class, var_export($parameters, true), $loggers); - break; + $parameters = $keys['param']; + } - case 'mailer': - $instances[] = sprintf( + // append new data + switch ($factory) { + case 'controller': + $instances[] = sprintf(" \$class = sfConfig::get('sf_factory_controller', '%s');\n \$this->factories['controller'] = new \$class(\$this);", $class); + + break; + + case 'request': + $parameters['no_script_name'] = sfConfig::get('sf_no_script_name'); + $instances[] = sprintf(" \$class = sfConfig::get('sf_factory_request', '%s');\n \$this->factories['request'] = new \$class(\$this->dispatcher, array(), array(), sfConfig::get('sf_factory_request_parameters', %s), sfConfig::get('sf_factory_request_attributes', array()));", $class, var_export($parameters, true)); + + break; + + case 'response': + $instances[] = sprintf(" \$class = sfConfig::get('sf_factory_response', '%s');\n \$this->factories['response'] = new \$class(\$this->dispatcher, sfConfig::get('sf_factory_response_parameters', array_merge(array('http_protocol' => isset(\$_SERVER['SERVER_PROTOCOL']) ? \$_SERVER['SERVER_PROTOCOL'] : null), %s)));", $class, var_export($parameters, true)); + // TODO: this is a bit ugly, as it only works for sfWebRequest & sfWebResponse combination. see #3397 + $instances[] = sprintf(" if (\$this->factories['request'] instanceof sfWebRequest \n && \$this->factories['response'] instanceof sfWebResponse \n && 'HEAD' == \$this->factories['request']->getMethod())\n { \n \$this->factories['response']->setHeaderOnly(true);\n }\n"); + + break; + + case 'storage': + $defaultParameters = []; + $defaultParameters[] = sprintf("'auto_shutdown' => false, 'session_id' => \$this->getRequest()->getParameter('%s'),", $parameters['session_name']); + if (is_subclass_of($class, 'sfDatabaseSessionStorage')) { + $defaultParameters[] = sprintf("'database' => \$this->getDatabaseManager()->getDatabase('%s'),", isset($parameters['database']) ? $parameters['database'] : 'default'); + unset($parameters['database']); + } + + if (isset($config['user']['param']['timeout'])) { + $defaultParameters[] = sprintf("'gc_maxlifetime' => %d,", $config['user']['param']['timeout']); + } + + $instances[] = sprintf(" \$class = sfConfig::get('sf_factory_storage', '%s');\n \$this->factories['storage'] = new \$class(array_merge(array(\n%s\n), sfConfig::get('sf_factory_storage_parameters', %s)));", $class, implode("\n", $defaultParameters), var_export($parameters, true)); + + break; + + case 'user': + $instances[] = sprintf(" \$class = sfConfig::get('sf_factory_user', '%s');\n \$this->factories['user'] = new \$class(\$this->dispatcher, \$this->factories['storage'], array_merge(array('auto_shutdown' => false, 'culture' => \$this->factories['request']->getParameter('sf_culture')), sfConfig::get('sf_factory_user_parameters', %s)));", $class, var_export($parameters, true)); + + break; + + case 'view_cache': + $instances[] = sprintf( + "\n if (sfConfig::get('sf_cache'))\n {\n". + " \$class = sfConfig::get('sf_factory_view_cache', '%s');\n". + " \$cache = new \$class(sfConfig::get('sf_factory_view_cache_parameters', %s));\n". + " \$this->factories['viewCacheManager'] = new %s(\$this, \$cache, %s);\n". + " }\n". + " else\n". + " {\n". + " \$this->factories['viewCacheManager'] = null;\n". + " }\n", + $class, + var_export($parameters, true), + $config['view_cache_manager']['class'], + var_export($config['view_cache_manager']['param'], true) + ); + + break; + + case 'i18n': + if (isset($parameters['cache'])) { + $cache = sprintf(" \$cache = new %s(%s);\n", $parameters['cache']['class'], var_export($parameters['cache']['param'], true)); + unset($parameters['cache']); + } else { + $cache = " \$cache = null;\n"; + } + + $instances[] = sprintf( + "\n if (sfConfig::get('sf_i18n'))\n {\n". + " \$class = sfConfig::get('sf_factory_i18n', '%s');\n". + '%s'. + " \$this->factories['i18n'] = new \$class(\$this->configuration, \$cache, %s);\n". + " sfWidgetFormSchemaFormatter::setTranslationCallable(array(\$this->factories['i18n'], '__'));\n". + " }\n", + $class, + $cache, + var_export($parameters, true) + ); + + break; + + case 'routing': + if (isset($parameters['cache'])) { + $cache = sprintf(" \$cache = new %s(%s);\n", $parameters['cache']['class'], var_export($parameters['cache']['param'], true)); + unset($parameters['cache']); + } else { + $cache = " \$cache = null;\n"; + } + + $instances[] = sprintf( + " \$class = sfConfig::get('sf_factory_routing', '%s');\n". + " %s\n". + "\$this->factories['routing'] = new \$class(\$this->dispatcher, \$cache, array_merge(array('auto_shutdown' => false, 'context' => \$this->factories['request']->getRequestContext()), sfConfig::get('sf_factory_routing_parameters', %s)));\n". + "if (\$parameters = \$this->factories['routing']->parse(\$this->factories['request']->getPathInfo()))\n". + "{\n". + " \$this->factories['request']->addRequestParameters(\$parameters);\n". + "}\n", + $class, + $cache, + var_export($parameters, true) + ); + + break; + + case 'logger': + $loggers = ''; + if (isset($parameters['loggers'])) { + foreach ($parameters['loggers'] as $name => $keys) { + if (isset($keys['enabled']) && !$keys['enabled']) { + continue; + } + + if (!isset($keys['class'])) { + // missing class key + throw new sfParseException(sprintf('Configuration file "%s" specifies logger "%s" with missing class key.', $configFiles[0], $name)); + } + + $condition = true; + if (isset($keys['param']['condition'])) { + $condition = $keys['param']['condition']; + unset($keys['param']['condition']); + } + + if ($condition) { + // create logger instance + $loggers .= sprintf( + "\n\$logger = new %s(\$this->dispatcher, array_merge(array('auto_shutdown' => false), %s));\n\$this->factories['logger']->addLogger(\$logger);\n", + $keys['class'], + isset($keys['param']) ? var_export($keys['param'], true) : 'array()' + ); + } + } + + unset($parameters['loggers']); + } + + $instances[] = sprintf( + " \$class = sfConfig::get('sf_factory_logger', '%s');\n \$this->factories['logger'] = new \$class(\$this->dispatcher, array_merge(array('auto_shutdown' => false), sfConfig::get('sf_factory_logger_parameters', %s)));\n". + ' %s', + $class, + var_export($parameters, true), + $loggers + ); + + break; + + case 'mailer': + $instances[] = sprintf( "if (!class_exists('Swift')) {\n". " \$swift_dir = sfConfig::get('sf_swiftmailer_dir', sfConfig::get('sf_symfony_lib_dir').'/vendor/swiftmailer/lib');\n". " require_once \$swift_dir.'/swift_required.php';\n". "}\n". - "\$this->setMailerConfiguration(array_merge(array('class' => sfConfig::get('sf_factory_mailer', '%s')), sfConfig::get('sf_factory_mailer_parameters', %s)));\n" - , $class, var_export($parameters, true)); - break; + "\$this->setMailerConfiguration(array_merge(array('class' => sfConfig::get('sf_factory_mailer', '%s')), sfConfig::get('sf_factory_mailer_parameters', %s)));\n", + $class, + var_export($parameters, true) + ); + + break; - case 'service_container': - $instances[] = ( + case 'service_container': + $instances[] = ( "\$class = require \$this->configuration->getConfigCache()->checkConfig('config/services.yml', true);\n". "\$this->setServiceContainerConfiguration(array('class' => \$class));\n" - ); - break; - } + ); + + break; + } + } + + // compile data + $retval = sprintf( + " $values) + /** + * @see sfConfigHandler + */ + public static function getConfiguration(array $configFiles) { - if (isset($values['file'])) - { - $config[$factory]['file'] = static::replacePath($values['file']); - } - } + $config = static::replaceConstants(static::flattenConfigurationWithEnvironment(static::parseYamls($configFiles))); - return $config; - } + foreach ($config as $factory => $values) { + if (isset($values['file'])) { + $config[$factory]['file'] = static::replacePath($values['file']); + } + } + + return $config; + } } diff --git a/lib/config/sfFilterConfigHandler.class.php b/lib/config/sfFilterConfigHandler.class.php index f0976a4ff..d9d221e27 100644 --- a/lib/config/sfFilterConfigHandler.class.php +++ b/lib/config/sfFilterConfigHandler.class.php @@ -12,149 +12,175 @@ /** * sfFilterConfigHandler allows you to register filters with the system. * - * @package symfony - * @subpackage config * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ class sfFilterConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - */ - public function execute($configFiles) - { - // parse the yaml - $config = static::getConfiguration($configFiles); - - // init our data and includes arrays - $data = array(); - $includes = array(); - - $execution = false; - $rendering = false; - - // let's do our fancy work - foreach ($config as $category => $keys) + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + */ + public function execute($configFiles) { - if (isset($keys['enabled']) && !$keys['enabled']) - { - continue; - } - - if (!isset($keys['class'])) - { - // missing class key - throw new sfParseException(sprintf('Configuration file "%s" specifies category "%s" with missing class key.', $configFiles[0], $category)); - } - - $class = $keys['class']; - - if (isset($keys['file'])) - { - if (!is_readable($keys['file'])) - { - // filter file doesn't exist - throw new sfParseException(sprintf('Configuration file "%s" specifies class "%s" with nonexistent or unreadable file "%s".', $configFiles[0], $class, $keys['file'])); + // parse the yaml + $config = static::getConfiguration($configFiles); + + // init our data and includes arrays + $data = []; + $includes = []; + + $execution = false; + $rendering = false; + + // let's do our fancy work + foreach ($config as $category => $keys) { + if (isset($keys['enabled']) && !$keys['enabled']) { + continue; + } + + if (!isset($keys['class'])) { + // missing class key + throw new sfParseException(sprintf('Configuration file "%s" specifies category "%s" with missing class key.', $configFiles[0], $category)); + } + + $class = $keys['class']; + + if (isset($keys['file'])) { + if (!is_readable($keys['file'])) { + // filter file doesn't exist + throw new sfParseException(sprintf('Configuration file "%s" specifies class "%s" with nonexistent or unreadable file "%s".', $configFiles[0], $class, $keys['file'])); + } + + // append our data + $includes[] = sprintf("require_once('%s');\n", $keys['file']); + } + + $condition = true; + if (isset($keys['param']['condition'])) { + $condition = $keys['param']['condition']; + unset($keys['param']['condition']); + } + + $type = isset($keys['param']['type']) ? $keys['param']['type'] : null; + unset($keys['param']['type']); + + if ($condition) { + // parse parameters + $parameters = isset($keys['param']) ? var_export($keys['param'], true) : 'null'; + + // append new data + if ('security' == $type) { + $data[] = $this->addSecurityFilter($category, $class, $parameters); + } else { + $data[] = $this->addFilter($category, $class, $parameters); + } + + if ('rendering' == $type) { + $rendering = true; + } + + if ('execution' == $type) { + $execution = true; + } + } } - // append our data - $includes[] = sprintf("require_once('%s');\n", $keys['file']); - } - - $condition = true; - if (isset($keys['param']['condition'])) - { - $condition = $keys['param']['condition']; - unset($keys['param']['condition']); - } - - $type = isset($keys['param']['type']) ? $keys['param']['type'] : null; - unset($keys['param']['type']); - - if ($condition) - { - // parse parameters - $parameters = isset($keys['param']) ? var_export($keys['param'], true) : 'null'; - - // append new data - if ('security' == $type) - { - $data[] = $this->addSecurityFilter($category, $class, $parameters); - } - else - { - $data[] = $this->addFilter($category, $class, $parameters); + if (!$rendering) { + throw new sfParseException(sprintf('Configuration file "%s" must register a filter of type "rendering".', $configFiles[0])); } - if ('rendering' == $type) - { - $rendering = true; + if (!$execution) { + throw new sfParseException(sprintf('Configuration file "%s" must register a filter of type "execution".', $configFiles[0])); } - if ('execution' == $type) - { - $execution = true; - } - } + // compile data + $retval = sprintf( + " $configFile) { + // we get the order of the new file and merge with the previous configurations + $previous = $config; + + $config = []; + foreach (static::parseYaml($configFile) as $key => $value) { + $value = (array) $value; + $config[$key] = isset($previous[$key]) ? sfToolkit::arrayDeepMerge($previous[$key], $value) : $value; + } + + // check that every key in previous array is still present (to avoid problem when upgrading) + foreach (array_keys($previous) as $key) { + if (!isset($config[$key])) { + throw new sfConfigurationException(sprintf('The filter name "%s" is defined in "%s" but not present in "%s" file. To disable a filter, add a "enabled" key with a false value.', $key, $configFiles[$i], $configFile)); + } + } + } + + $config = static::replaceConstants($config); + + foreach ($config as $category => $keys) { + if (isset($keys['file'])) { + $config[$category]['file'] = static::replacePath($keys['file']); + } + } + + return $config; } - if (!$execution) + /** + * Adds a filter statement to the data. + * + * @param string $category The category name + * @param string $class The filter class name + * @param array $parameters Filter default parameters + * + * @return string The PHP statement + */ + protected function addFilter($category, $class, $parameters) { - throw new sfParseException(sprintf('Configuration file "%s" must register a filter of type "execution".', $configFiles[0])); + return sprintf( + "\nlist(\$class, \$parameters) = (array) sfConfig::get('sf_%s_filter', array('%s', %s));\n". + "\$filter = new \$class(sfContext::getInstance(), \$parameters);\n". + '$this->register($filter);', + $category, + $class, + $parameters + ); } - // compile data - $retval = sprintf("register(\$filter);", - $category, $class, $parameters); - } - - /** - * Adds a security filter statement to the data. - * - * @param string $category The category name - * @param string $class The filter class name - * @param array $parameters Filter default parameters - * - * @return string The PHP statement - */ - protected function addSecurityFilter($category, $class, $parameters) - { - return <<isSecure()) @@ -162,47 +188,5 @@ protected function addSecurityFilter($category, $class, $parameters) {$this->addFilter($category, $class, $parameters)} } EOF; - } - - /** - * @see sfConfigHandler - * @inheritdoc - */ - static public function getConfiguration(array $configFiles) - { - $config = static::parseYaml($configFiles[0]); - foreach (array_slice($configFiles, 1) as $i => $configFile) - { - // we get the order of the new file and merge with the previous configurations - $previous = $config; - - $config = array(); - foreach (static::parseYaml($configFile) as $key => $value) - { - $value = (array) $value; - $config[$key] = isset($previous[$key]) ? sfToolkit::arrayDeepMerge($previous[$key], $value) : $value; - } - - // check that every key in previous array is still present (to avoid problem when upgrading) - foreach (array_keys($previous) as $key) - { - if (!isset($config[$key])) - { - throw new sfConfigurationException(sprintf('The filter name "%s" is defined in "%s" but not present in "%s" file. To disable a filter, add a "enabled" key with a false value.', $key, $configFiles[$i], $configFile)); - } - } } - - $config = static::replaceConstants($config); - - foreach ($config as $category => $keys) - { - if (isset($keys['file'])) - { - $config[$category]['file'] = static::replacePath($keys['file']); - } - } - - return $config; - } } diff --git a/lib/config/sfGeneratorConfigHandler.class.php b/lib/config/sfGeneratorConfigHandler.class.php index 430658215..32279c9c1 100644 --- a/lib/config/sfGeneratorConfigHandler.class.php +++ b/lib/config/sfGeneratorConfigHandler.class.php @@ -11,83 +11,74 @@ /** * sfGeneratorConfigHandler. * - * @package symfony - * @subpackage config * @author Fabien Potencier - * @version SVN: $Id$ */ class sfGeneratorConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler. - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - * @throws sfInitializationException If a generator.yml key check fails - */ - public function execute($configFiles) - { - // parse the yaml - $config = static::getConfiguration($configFiles); - if (!$config) + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + * @throws sfInitializationException If a generator.yml key check fails + */ + public function execute($configFiles) { - return ''; - } + // parse the yaml + $config = static::getConfiguration($configFiles); + if (!$config) { + return ''; + } - if (!isset($config['generator'])) - { - throw new sfParseException(sprintf('Configuration file "%s" must specify a generator section.', isset($configFiles[1]) ? $configFiles[1] : $configFiles[0])); - } + if (!isset($config['generator'])) { + throw new sfParseException(sprintf('Configuration file "%s" must specify a generator section.', isset($configFiles[1]) ? $configFiles[1] : $configFiles[0])); + } - $config = $config['generator']; + $config = $config['generator']; - if (!isset($config['class'])) - { - throw new sfParseException(sprintf('Configuration file "%s" must specify a generator class section under the generator section.', isset($configFiles[1]) ? $configFiles[1] : $configFiles[0])); - } + if (!isset($config['class'])) { + throw new sfParseException(sprintf('Configuration file "%s" must specify a generator class section under the generator section.', isset($configFiles[1]) ? $configFiles[1] : $configFiles[0])); + } - foreach (array('fields', 'list', 'edit') as $section) - { - if (isset($config[$section])) - { - throw new sfParseException(sprintf('Configuration file "%s" can specify a "%s" section but only under the param section.', isset($configFiles[1]) ? $configFiles[1] : $configFiles[0], $section)); - } - } + foreach (['fields', 'list', 'edit'] as $section) { + if (isset($config[$section])) { + throw new sfParseException(sprintf('Configuration file "%s" can specify a "%s" section but only under the param section.', isset($configFiles[1]) ? $configFiles[1] : $configFiles[0], $section)); + } + } - // generate class and add a reference to it - $generatorManager = new sfGeneratorManager(sfContext::getInstance()->getConfiguration()); + // generate class and add a reference to it + $generatorManager = new sfGeneratorManager(sfContext::getInstance()->getConfiguration()); - // generator parameters - $generatorParam = (isset($config['param']) ? $config['param'] : array()); + // generator parameters + $generatorParam = (isset($config['param']) ? $config['param'] : []); - // hack to find the module name (look for the last /modules/ in path) - preg_match('#.*/modules/([^/]+)/#', str_replace('\\', '/', $configFiles[0]), $match); - $generatorParam['moduleName'] = $match[1]; + // hack to find the module name (look for the last /modules/ in path) + preg_match('#.*/modules/([^/]+)/#', str_replace('\\', '/', $configFiles[0]), $match); + $generatorParam['moduleName'] = $match[1]; - // compile data - $retval = "generate($class, $parameters); - } + public static function getContent(sfGeneratorManager $generatorManager, $class, $parameters) + { + return $generatorManager->generate($class, $parameters); + } - /** - * @see sfConfigHandler - * @inheritdoc - */ - static public function getConfiguration(array $configFiles) - { - return static::parseYamls($configFiles); - } + /** + * @see sfConfigHandler + */ + public static function getConfiguration(array $configFiles) + { + return static::parseYamls($configFiles); + } } diff --git a/lib/config/sfPluginConfiguration.class.php b/lib/config/sfPluginConfiguration.class.php index 028261837..aa80e077d 100644 --- a/lib/config/sfPluginConfiguration.class.php +++ b/lib/config/sfPluginConfiguration.class.php @@ -11,222 +11,202 @@ /** * sfPluginConfiguration represents a configuration for a symfony plugin. * - * @package symfony - * @subpackage config * @author Kris Wallsmith - * @version SVN: $Id$ */ abstract class sfPluginConfiguration { - protected - $configuration = null, - $dispatcher = null, - $name = null, - $rootDir = null; - - /** - * Constructor. - * - * @param sfProjectConfiguration $configuration The project configuration - * @param string $rootDir The plugin root directory - * @param string $name The plugin name - */ - public function __construct(sfProjectConfiguration $configuration, $rootDir = null, $name = null) - { - $this->configuration = $configuration; - $this->dispatcher = $configuration->getEventDispatcher(); - $this->rootDir = null === $rootDir ? $this->guessRootDir() : realpath($rootDir); - $this->name = null === $name ? $this->guessName() : $name; - - $this->setup(); - $this->configure(); - - if (!$this->configuration instanceof sfApplicationConfiguration) + protected $configuration; + protected $dispatcher; + protected $name; + protected $rootDir; + + /** + * Constructor. + * + * @param sfProjectConfiguration $configuration The project configuration + * @param string $rootDir The plugin root directory + * @param string $name The plugin name + */ + public function __construct(sfProjectConfiguration $configuration, $rootDir = null, $name = null) { - $this->initializeAutoload(); - $this->initialize(); + $this->configuration = $configuration; + $this->dispatcher = $configuration->getEventDispatcher(); + $this->rootDir = null === $rootDir ? $this->guessRootDir() : realpath($rootDir); + $this->name = null === $name ? $this->guessName() : $name; + + $this->setup(); + $this->configure(); + + if (!$this->configuration instanceof sfApplicationConfiguration) { + $this->initializeAutoload(); + $this->initialize(); + } } - } - - /** - * Sets up the plugin. - * - * This method can be used when creating a base plugin configuration class for other plugins to extend. - */ - public function setup() - { - } - - /** - * Configures the plugin. - * - * This method is called before the plugin's classes have been added to sfAutoload. - */ - public function configure() - { - } - - /** - * Initializes the plugin. - * - * This method is called after the plugin's classes have been added to sfAutoload. - * - * @return boolean|null If false sfApplicationConfiguration will look for a config.php (maintains BC with symfony < 1.2) - */ - public function initialize() - { - } - - /** - * Returns the plugin root directory. - * - * @return string - */ - public function getRootDir() - { - return $this->rootDir; - } - - /** - * Returns the plugin name. - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Initializes autoloading for the plugin. - * - * This method is called when a plugin is initialized in a project - * configuration. Otherwise, autoload is handled in - * {@link sfApplicationConfiguration} using {@link sfAutoload}. - * - * @see sfSimpleAutoload - */ - public function initializeAutoload() - { - $autoload = sfSimpleAutoload::getInstance(sfConfig::get('sf_cache_dir').'/project_autoload.cache'); - - if (is_readable($file = $this->rootDir.'/config/autoload.yml')) + + /** + * Sets up the plugin. + * + * This method can be used when creating a base plugin configuration class for other plugins to extend. + */ + public function setup() + { + } + + /** + * Configures the plugin. + * + * This method is called before the plugin's classes have been added to sfAutoload. + */ + public function configure() { - $this->configuration->getEventDispatcher()->connect('autoload.filter_config', array($this, 'filterAutoloadConfig')); - $autoload->loadConfiguration(array($file)); - $this->configuration->getEventDispatcher()->disconnect('autoload.filter_config', array($this, 'filterAutoloadConfig')); } - else + + /** + * Initializes the plugin. + * + * This method is called after the plugin's classes have been added to sfAutoload. + * + * @return bool|null If false sfApplicationConfiguration will look for a config.php (maintains BC with symfony < 1.2) + */ + public function initialize() { - $autoload->addDirectory($this->rootDir.'/lib'); } - $autoload->register(); - } - - /** - * Filters sfAutoload configuration values. - * - * @param sfEvent $event - * @param array $config - * - * @return array - */ - public function filterAutoloadConfig(sfEvent $event, array $config) - { - // use array_merge so config is added to the front of the autoload array - if (!isset($config['autoload'][$this->name.'_lib'])) + /** + * Returns the plugin root directory. + * + * @return string + */ + public function getRootDir() { - $config['autoload'] = array_merge(array( - $this->name.'_lib' => array( - 'path' => $this->rootDir.'/lib', - 'recursive' => true, - ), - ), $config['autoload']); + return $this->rootDir; } - if (!isset($config['autoload'][$this->name.'_module_libs'])) + /** + * Returns the plugin name. + * + * @return string + */ + public function getName() { - $config['autoload'] = array_merge(array( - $this->name.'_module_libs' => array( - 'path' => $this->rootDir.'/modules/*/lib', - 'recursive' => true, - 'prefix' => 1, - ), - ), $config['autoload']); + return $this->name; } - return $config; - } - - /** - * Connects the current plugin's tests to the "test:*" tasks. - */ - public function connectTests() - { - $this->dispatcher->connect('task.test.filter_test_files', array($this, 'filterTestFiles')); - } - - /** - * Listens for the "task.test.filter_test_files" event and adds tests from the current plugin. - * - * @param sfEvent $event - * @param array $files - * - * @return array An array of files with the appropriate tests from the current plugin merged in - */ - public function filterTestFiles(sfEvent $event, $files) - { - $task = $event->getSubject(); - - if ($task instanceof sfTestAllTask) + /** + * Initializes autoloading for the plugin. + * + * This method is called when a plugin is initialized in a project + * configuration. Otherwise, autoload is handled in + * {@link sfApplicationConfiguration} using {@link sfAutoload}. + * + * @see sfSimpleAutoload + */ + public function initializeAutoload() { - $directory = $this->rootDir.'/test'; - $names = array(); + $autoload = sfSimpleAutoload::getInstance(sfConfig::get('sf_cache_dir').'/project_autoload.cache'); + + if (is_readable($file = $this->rootDir.'/config/autoload.yml')) { + $this->configuration->getEventDispatcher()->connect('autoload.filter_config', [$this, 'filterAutoloadConfig']); + $autoload->loadConfiguration([$file]); + $this->configuration->getEventDispatcher()->disconnect('autoload.filter_config', [$this, 'filterAutoloadConfig']); + } else { + $autoload->addDirectory($this->rootDir.'/lib'); + } + + $autoload->register(); } - else if ($task instanceof sfTestFunctionalTask) + + /** + * Filters sfAutoload configuration values. + * + * @return array + */ + public function filterAutoloadConfig(sfEvent $event, array $config) { - $directory = $this->rootDir.'/test/functional'; - $names = $event['arguments']['controller']; + // use array_merge so config is added to the front of the autoload array + if (!isset($config['autoload'][$this->name.'_lib'])) { + $config['autoload'] = array_merge([ + $this->name.'_lib' => [ + 'path' => $this->rootDir.'/lib', + 'recursive' => true, + ], + ], $config['autoload']); + } + + if (!isset($config['autoload'][$this->name.'_module_libs'])) { + $config['autoload'] = array_merge([ + $this->name.'_module_libs' => [ + 'path' => $this->rootDir.'/modules/*/lib', + 'recursive' => true, + 'prefix' => 1, + ], + ], $config['autoload']); + } + + return $config; } - else if ($task instanceof sfTestUnitTask) + + /** + * Connects the current plugin's tests to the "test:*" tasks. + */ + public function connectTests() { - $directory = $this->rootDir.'/test/unit'; - $names = $event['arguments']['name']; + $this->dispatcher->connect('task.test.filter_test_files', [$this, 'filterTestFiles']); } - if (!count($names)) + /** + * Listens for the "task.test.filter_test_files" event and adds tests from the current plugin. + * + * @param array $files + * + * @return array An array of files with the appropriate tests from the current plugin merged in + */ + public function filterTestFiles(sfEvent $event, $files) { - $names = array('*'); + $task = $event->getSubject(); + + if ($task instanceof sfTestAllTask) { + $directory = $this->rootDir.'/test'; + $names = []; + } elseif ($task instanceof sfTestFunctionalTask) { + $directory = $this->rootDir.'/test/functional'; + $names = $event['arguments']['controller']; + } elseif ($task instanceof sfTestUnitTask) { + $directory = $this->rootDir.'/test/unit'; + $names = $event['arguments']['name']; + } + + if (!count($names)) { + $names = ['*']; + } + + foreach ($names as $name) { + $finder = sfFinder::type('file')->follow_link()->name(basename($name).'Test.php'); + $files = array_merge($files, $finder->in($directory.'/'.dirname($name))); + } + + return array_unique($files); } - foreach ($names as $name) + /** + * Guesses the plugin root directory. + * + * @return string + */ + protected function guessRootDir() { - $finder = sfFinder::type('file')->follow_link()->name(basename($name).'Test.php'); - $files = array_merge($files, $finder->in($directory.'/'.dirname($name))); + $r = new ReflectionClass(get_class($this)); + + return realpath(dirname($r->getFileName()).'/..'); } - return array_unique($files); - } - - /** - * Guesses the plugin root directory. - * - * @return string - */ - protected function guessRootDir() - { - $r = new ReflectionClass(get_class($this)); - return realpath(dirname($r->getFileName()).'/..'); - } - - /** - * Guesses the plugin name. - * - * @return string - */ - protected function guessName() - { - return substr(get_class($this), 0, -13); - } + /** + * Guesses the plugin name. + * + * @return string + */ + protected function guessName() + { + return substr(get_class($this), 0, -13); + } } diff --git a/lib/config/sfPluginConfigurationGeneric.class.php b/lib/config/sfPluginConfigurationGeneric.class.php index 127210c13..a24661728 100644 --- a/lib/config/sfPluginConfigurationGeneric.class.php +++ b/lib/config/sfPluginConfigurationGeneric.class.php @@ -11,18 +11,15 @@ /** * sfPluginConfigurationGeneric represents a configuration for a plugin with no configuration class. * - * @package symfony - * @subpackage config * @author Kris Wallsmith - * @version SVN: $Id$ */ class sfPluginConfigurationGeneric extends sfPluginConfiguration { - /** - * @see sfPluginConfiguration - */ - public function initialize() - { - return false; - } + /** + * @see sfPluginConfiguration + */ + public function initialize() + { + return false; + } } diff --git a/lib/config/sfProjectConfiguration.class.php b/lib/config/sfProjectConfiguration.class.php index 93a4baeb6..a523babbd 100644 --- a/lib/config/sfProjectConfiguration.class.php +++ b/lib/config/sfProjectConfiguration.class.php @@ -11,635 +11,598 @@ /** * sfProjectConfiguration represents a configuration for a symfony project. * - * @package symfony - * @subpackage config * @author Fabien Potencier - * @version SVN: $Id$ */ class sfProjectConfiguration { - /** @var string */ - protected $rootDir = null; - /** @var string */ - protected $symfonyLibDir = null; - /** @var sfEventDispatcher */ - protected $dispatcher = null; - /** @var array */ - protected $plugins = array(); - /** @var array */ - protected $pluginPaths = array(); - /** @var array */ - protected $overriddenPluginPaths = array(); - /** @var sfPluginConfiguration[] */ - protected $pluginConfigurations = array(); - /** @var bool */ - protected $pluginsLoaded = false; - - /** @var sfApplicationConfiguration */ - static protected $active = null; - - /** - * Constructor. - * - * @param string $rootDir The project root directory - * @param sfEventDispatcher $dispatcher The event dispatcher - */ - public function __construct($rootDir = null, sfEventDispatcher $dispatcher = null) - { - if (null === self::$active || $this instanceof sfApplicationConfiguration) + /** @var string */ + protected $rootDir; + + /** @var string */ + protected $symfonyLibDir; + + /** @var sfEventDispatcher */ + protected $dispatcher; + + /** @var array */ + protected $plugins = []; + + /** @var array */ + protected $pluginPaths = []; + + /** @var array */ + protected $overriddenPluginPaths = []; + + /** @var sfPluginConfiguration[] */ + protected $pluginConfigurations = []; + + /** @var bool */ + protected $pluginsLoaded = false; + + /** @var sfApplicationConfiguration */ + protected static $active; + + /** + * Constructor. + * + * @param string $rootDir The project root directory + * @param sfEventDispatcher $dispatcher The event dispatcher + */ + public function __construct($rootDir = null, ?sfEventDispatcher $dispatcher = null) { - self::$active = $this; + if (null === self::$active || $this instanceof sfApplicationConfiguration) { + self::$active = $this; + } + + $this->rootDir = null === $rootDir ? static::guessRootDir() : realpath($rootDir); + $this->symfonyLibDir = realpath(__DIR__.'/..'); + $this->dispatcher = null === $dispatcher ? new sfEventDispatcher() : $dispatcher; + + ini_set('magic_quotes_runtime', 'off'); + + sfConfig::set('sf_symfony_lib_dir', $this->symfonyLibDir); + + $this->setRootDir($this->rootDir); + + // provide forms the dispatcher + sfFormSymfony::setEventDispatcher($this->dispatcher); + + $this->setup(); + + $this->loadPlugins(); + $this->setupPlugins(); } - $this->rootDir = null === $rootDir ? static::guessRootDir() : realpath($rootDir); - $this->symfonyLibDir = realpath(__DIR__.'/..'); - $this->dispatcher = null === $dispatcher ? new sfEventDispatcher() : $dispatcher; + /** + * Calls methods defined via sfEventDispatcher. + * + * @param string $method The method name + * @param array $arguments The method arguments + * + * @return mixed The returned value of the called method + * + * @throws sfException + */ + public function __call($method, $arguments) + { + $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'configuration.method_not_found', ['method' => $method, 'arguments' => $arguments])); + if (!$event->isProcessed()) { + throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method)); + } - ini_set('magic_quotes_runtime', 'off'); + return $event->getReturnValue(); + } - sfConfig::set('sf_symfony_lib_dir', $this->symfonyLibDir); + /** + * Setups the current configuration. + * + * Override this method if you want to customize your project configuration. + */ + public function setup() + { + } - $this->setRootDir($this->rootDir); + /** + * Loads the project's plugin configurations. + */ + public function loadPlugins() + { + foreach ($this->getPluginPaths() as $path) { + if (false === $plugin = array_search($path, $this->overriddenPluginPaths)) { + $plugin = basename($path); + } + $class = $plugin.'Configuration'; + + if (is_readable($file = sprintf('%s/config/%s.class.php', $path, $class))) { + require_once $file; + $configuration = new $class($this, $path, $plugin); + } else { + $configuration = new sfPluginConfigurationGeneric($this, $path, $plugin); + } + + $this->pluginConfigurations[$plugin] = $configuration; + } - // provide forms the dispatcher - sfFormSymfony::setEventDispatcher($this->dispatcher); + $this->pluginsLoaded = true; + } - $this->setup(); + /** + * Sets up plugin configurations. + * + * Override this method if you want to customize plugin configurations. + */ + public function setupPlugins() + { + } - $this->loadPlugins(); - $this->setupPlugins(); - } + /** + * Sets the project root directory. + * + * @param string $rootDir The project root directory + */ + public function setRootDir($rootDir) + { + $this->rootDir = $rootDir; + + sfConfig::add([ + 'sf_root_dir' => $rootDir, + + // global directory structure + 'sf_apps_dir' => $rootDir.DIRECTORY_SEPARATOR.'apps', + 'sf_lib_dir' => $rootDir.DIRECTORY_SEPARATOR.'lib', + 'sf_log_dir' => $rootDir.DIRECTORY_SEPARATOR.'log', + 'sf_data_dir' => $rootDir.DIRECTORY_SEPARATOR.'data', + 'sf_config_dir' => $rootDir.DIRECTORY_SEPARATOR.'config', + 'sf_test_dir' => $rootDir.DIRECTORY_SEPARATOR.'test', + 'sf_plugins_dir' => $rootDir.DIRECTORY_SEPARATOR.'plugins', + ]); + + $this->setWebDir($rootDir.DIRECTORY_SEPARATOR.'web'); + $this->setCacheDir($rootDir.DIRECTORY_SEPARATOR.'cache'); + } - /** - * Setups the current configuration. - * - * Override this method if you want to customize your project configuration. - */ - public function setup() - { - } + /** + * Returns the project root directory. + * + * @return string The project root directory + */ + public function getRootDir() + { + return $this->rootDir; + } - /** - * Loads the project's plugin configurations. - */ - public function loadPlugins() - { - foreach ($this->getPluginPaths() as $path) + /** + * Sets the cache root directory. + * + * @param string $cacheDir the absolute path to the cache dir + */ + public function setCacheDir($cacheDir) { - if (false === $plugin = array_search($path, $this->overriddenPluginPaths)) - { - $plugin = basename($path); - } - $class = $plugin.'Configuration'; - - if (is_readable($file = sprintf('%s/config/%s.class.php', $path, $class))) - { - require_once $file; - $configuration = new $class($this, $path, $plugin); - } - else - { - $configuration = new sfPluginConfigurationGeneric($this, $path, $plugin); - } - - $this->pluginConfigurations[$plugin] = $configuration; + sfConfig::set('sf_cache_dir', $cacheDir); } - $this->pluginsLoaded = true; - } - - /** - * Sets up plugin configurations. - * - * Override this method if you want to customize plugin configurations. - */ - public function setupPlugins() - { - } - - /** - * Sets the project root directory. - * - * @param string $rootDir The project root directory - */ - public function setRootDir($rootDir) - { - $this->rootDir = $rootDir; - - sfConfig::add(array( - 'sf_root_dir' => $rootDir, - - // global directory structure - 'sf_apps_dir' => $rootDir.DIRECTORY_SEPARATOR.'apps', - 'sf_lib_dir' => $rootDir.DIRECTORY_SEPARATOR.'lib', - 'sf_log_dir' => $rootDir.DIRECTORY_SEPARATOR.'log', - 'sf_data_dir' => $rootDir.DIRECTORY_SEPARATOR.'data', - 'sf_config_dir' => $rootDir.DIRECTORY_SEPARATOR.'config', - 'sf_test_dir' => $rootDir.DIRECTORY_SEPARATOR.'test', - 'sf_plugins_dir' => $rootDir.DIRECTORY_SEPARATOR.'plugins', - )); - - $this->setWebDir($rootDir.DIRECTORY_SEPARATOR.'web'); - $this->setCacheDir($rootDir.DIRECTORY_SEPARATOR.'cache'); - } - - /** - * Returns the project root directory. - * - * @return string The project root directory - */ - public function getRootDir() - { - return $this->rootDir; - } - - /** - * Sets the cache root directory. - * - * @param string $cacheDir The absolute path to the cache dir. - */ - public function setCacheDir($cacheDir) - { - sfConfig::set('sf_cache_dir', $cacheDir); - } - - /** - * Sets the log directory. - * - * @param string $logDir The absolute path to the log dir. - */ - public function setLogDir($logDir) - { - sfConfig::set('sf_log_dir', $logDir); - } - - /** - * Sets the web root directory. - * - * @param string $webDir The absolute path to the web dir. - */ - public function setWebDir($webDir) - { - sfConfig::add(array( - 'sf_web_dir' => $webDir, - 'sf_upload_dir_name' => $uploadDirName = 'uploads', - 'sf_upload_dir' => $webDir.DIRECTORY_SEPARATOR.$uploadDirName, - )); - } - - /** - * Gets directories where model classes are stored. The order of returned paths is lowest precedence - * to highest precedence. - * - * @return array An array of directories - */ - public function getModelDirs() - { - return array_merge( - $this->getPluginSubPaths('/lib/model'), // plugins - array(sfConfig::get('sf_lib_dir').'/model') // project - ); - } - - /** - * Gets directories where template files are stored for a generator class and a specific theme. - * - * @param string $class The generator class name - * @param string $theme The theme name - * - * @return array An array of directories - */ - public function getGeneratorTemplateDirs($class, $theme) - { - return array_merge( - array(sfConfig::get('sf_data_dir').'/generator/'.$class.'/'.$theme.'/template'), // project - $this->getPluginSubPaths('/data/generator/'.$class.'/'.$theme.'/template'), // plugins - array(sfConfig::get('sf_data_dir').'/generator/'.$class.'/default/template'), // project (default theme) - $this->getPluginSubPaths('/data/generator/'.$class.'/default/template') // plugins (default theme) - ); - } - - /** - * Gets directories where the skeleton is stored for a generator class and a specific theme. - * - * @param string $class The generator class name - * @param string $theme The theme name - * - * @return array An array of directories - */ - public function getGeneratorSkeletonDirs($class, $theme) - { - return array_merge( - array(sfConfig::get('sf_data_dir').'/generator/'.$class.'/'.$theme.'/skeleton'), // project - $this->getPluginSubPaths('/data/generator/'.$class.'/'.$theme.'/skeleton'), // plugins - array(sfConfig::get('sf_data_dir').'/generator/'.$class.'/default/skeleton'), // project (default theme) - $this->getPluginSubPaths('/data/generator/'.$class.'/default/skeleton') // plugins (default theme) - ); - } - - /** - * Gets the template to use for a generator class. - * - * @param string $class The generator class name - * @param string $theme The theme name - * @param string $path The template path - * - * @return string A template path - * - * @throws sfException - */ - public function getGeneratorTemplate($class, $theme, $path) - { - $dirs = $this->getGeneratorTemplateDirs($class, $theme); - foreach ($dirs as $dir) + /** + * Sets the log directory. + * + * @param string $logDir the absolute path to the log dir + */ + public function setLogDir($logDir) { - if (is_readable($dir.'/'.$path)) - { - return $dir.'/'.$path; - } + sfConfig::set('sf_log_dir', $logDir); } - throw new sfException(sprintf('Unable to load "%s" generator template in: %s.', $path, implode(', ', $dirs))); - } - - /** - * Gets the configuration file paths for a given relative configuration path. - * - * @param string $configPath The configuration path - * - * @return array An array of paths - */ - public function getConfigPaths($configPath) - { - $globalConfigPath = basename(dirname($configPath)).'/'.basename($configPath); - - $files = array( - $this->getSymfonyLibDir().'/config/'.$globalConfigPath, // symfony - ); - - foreach ($this->getPluginPaths() as $path) + /** + * Sets the web root directory. + * + * @param string $webDir the absolute path to the web dir + */ + public function setWebDir($webDir) { - if (is_file($file = $path.'/'.$globalConfigPath)) - { - $files[] = $file; // plugins - } + sfConfig::add([ + 'sf_web_dir' => $webDir, + 'sf_upload_dir_name' => $uploadDirName = 'uploads', + 'sf_upload_dir' => $webDir.DIRECTORY_SEPARATOR.$uploadDirName, + ]); } - $files = array_merge($files, array( - $this->getRootDir().'/'.$globalConfigPath, // project - $this->getRootDir().'/'.$configPath, // project - )); + /** + * Gets directories where model classes are stored. The order of returned paths is lowest precedence + * to highest precedence. + * + * @return array An array of directories + */ + public function getModelDirs() + { + return array_merge( + $this->getPluginSubPaths('/lib/model'), // plugins + [sfConfig::get('sf_lib_dir').'/model'] // project + ); + } - foreach ($this->getPluginPaths() as $path) + /** + * Gets directories where template files are stored for a generator class and a specific theme. + * + * @param string $class The generator class name + * @param string $theme The theme name + * + * @return array An array of directories + */ + public function getGeneratorTemplateDirs($class, $theme) { - if (is_file($file = $path.'/'.$configPath)) - { - $files[] = $file; // plugins - } + return array_merge( + [sfConfig::get('sf_data_dir').'/generator/'.$class.'/'.$theme.'/template'], // project + $this->getPluginSubPaths('/data/generator/'.$class.'/'.$theme.'/template'), // plugins + [sfConfig::get('sf_data_dir').'/generator/'.$class.'/default/template'], // project (default theme) + $this->getPluginSubPaths('/data/generator/'.$class.'/default/template') // plugins (default theme) + ); } - $configs = array(); - foreach (array_unique($files) as $file) + /** + * Gets directories where the skeleton is stored for a generator class and a specific theme. + * + * @param string $class The generator class name + * @param string $theme The theme name + * + * @return array An array of directories + */ + public function getGeneratorSkeletonDirs($class, $theme) { - if (is_readable($file)) - { - $configs[] = $file; - } + return array_merge( + [sfConfig::get('sf_data_dir').'/generator/'.$class.'/'.$theme.'/skeleton'], // project + $this->getPluginSubPaths('/data/generator/'.$class.'/'.$theme.'/skeleton'), // plugins + [sfConfig::get('sf_data_dir').'/generator/'.$class.'/default/skeleton'], // project (default theme) + $this->getPluginSubPaths('/data/generator/'.$class.'/default/skeleton') // plugins (default theme) + ); } - return $configs; - } - - /** - * Sets the enabled plugins. - * - * @param array $plugins An array of plugin names - * - * @throws LogicException If plugins have already been loaded - */ - public function setPlugins(array $plugins) - { - if ($this->pluginsLoaded) + /** + * Gets the template to use for a generator class. + * + * @param string $class The generator class name + * @param string $theme The theme name + * @param string $path The template path + * + * @return string A template path + * + * @throws sfException + */ + public function getGeneratorTemplate($class, $theme, $path) { - throw new LogicException('Plugins have already been loaded.'); + $dirs = $this->getGeneratorTemplateDirs($class, $theme); + foreach ($dirs as $dir) { + if (is_readable($dir.'/'.$path)) { + return $dir.'/'.$path; + } + } + + throw new sfException(sprintf('Unable to load "%s" generator template in: %s.', $path, implode(', ', $dirs))); } - $this->plugins = $plugins; + /** + * Gets the configuration file paths for a given relative configuration path. + * + * @param string $configPath The configuration path + * + * @return array An array of paths + */ + public function getConfigPaths($configPath) + { + $globalConfigPath = basename(dirname($configPath)).'/'.basename($configPath); + + $files = [ + $this->getSymfonyLibDir().'/config/'.$globalConfigPath, // symfony + ]; + + foreach ($this->getPluginPaths() as $path) { + if (is_file($file = $path.'/'.$globalConfigPath)) { + $files[] = $file; // plugins + } + } - $this->pluginPaths = array(); - } + $files = array_merge($files, [ + $this->getRootDir().'/'.$globalConfigPath, // project + $this->getRootDir().'/'.$configPath, // project + ]); + + foreach ($this->getPluginPaths() as $path) { + if (is_file($file = $path.'/'.$configPath)) { + $files[] = $file; // plugins + } + } - /** - * Enables a plugin or a list of plugins. - * - * @param array|string $plugins A plugin name or a plugin list - */ - public function enablePlugins($plugins) - { - if (!is_array($plugins)) + $configs = []; + foreach (array_unique($files) as $file) { + if (is_readable($file)) { + $configs[] = $file; + } + } + + return $configs; + } + + /** + * Sets the enabled plugins. + * + * @param array $plugins An array of plugin names + * + * @throws LogicException If plugins have already been loaded + */ + public function setPlugins(array $plugins) { - if (func_num_args() > 1) - { - $plugins = func_get_args(); - } - else - { - $plugins = array($plugins); - } + if ($this->pluginsLoaded) { + throw new LogicException('Plugins have already been loaded.'); + } + + $this->plugins = $plugins; + + $this->pluginPaths = []; } - $this->setPlugins(array_merge($this->plugins, $plugins)); - } - - /** - * Disables a plugin. - * - * @param array|string $plugins A plugin name or a plugin list - * - * @throws LogicException If plugins have already been loaded - */ - public function disablePlugins($plugins) - { - if ($this->pluginsLoaded) + /** + * Enables a plugin or a list of plugins. + * + * @param array|string $plugins A plugin name or a plugin list + */ + public function enablePlugins($plugins) { - throw new LogicException('Plugins have already been loaded.'); + if (!is_array($plugins)) { + if (func_num_args() > 1) { + $plugins = func_get_args(); + } else { + $plugins = [$plugins]; + } + } + + $this->setPlugins(array_merge($this->plugins, $plugins)); } - if (!is_array($plugins)) + /** + * Disables a plugin. + * + * @param array|string $plugins A plugin name or a plugin list + * + * @throws LogicException If plugins have already been loaded + */ + public function disablePlugins($plugins) { - $plugins = array($plugins); + if ($this->pluginsLoaded) { + throw new LogicException('Plugins have already been loaded.'); + } + + if (!is_array($plugins)) { + $plugins = [$plugins]; + } + + foreach ($plugins as $plugin) { + if (false !== $pos = array_search($plugin, $this->plugins)) { + unset($this->plugins[$pos]); + } else { + throw new InvalidArgumentException(sprintf('The plugin "%s" does not exist.', $plugin)); + } + } + + $this->pluginPaths = []; } - foreach ($plugins as $plugin) + /** + * Enabled all installed plugins except the one given as argument. + * + * @param array|string $plugins A plugin name or a plugin list + * + * @throws LogicException If plugins have already been loaded + */ + public function enableAllPluginsExcept($plugins = []) { - if (false !== $pos = array_search($plugin, $this->plugins)) - { - unset($this->plugins[$pos]); - } - else - { - throw new InvalidArgumentException(sprintf('The plugin "%s" does not exist.', $plugin)); - } + if ($this->pluginsLoaded) { + throw new LogicException('Plugins have already been loaded.'); + } + + $this->plugins = array_keys($this->getAllPluginPaths()); + + sort($this->plugins); + + $this->disablePlugins($plugins); } - $this->pluginPaths = array(); - } - - /** - * Enabled all installed plugins except the one given as argument. - * - * @param array|string $plugins A plugin name or a plugin list - * - * @throws LogicException If plugins have already been loaded - */ - public function enableAllPluginsExcept($plugins = array()) - { - if ($this->pluginsLoaded) + /** + * Gets the list of enabled plugins. + * + * @return array An array of enabled plugins + */ + public function getPlugins() { - throw new LogicException('Plugins have already been loaded.'); + return $this->plugins; } - $this->plugins = array_keys($this->getAllPluginPaths()); - - sort($this->plugins); - - $this->disablePlugins($plugins); - } - - /** - * Gets the list of enabled plugins. - * - * @return array An array of enabled plugins - */ - public function getPlugins() - { - return $this->plugins; - } - - /** - * Gets the paths plugin sub-directories, minding overloaded plugins. - * - * @param string $subPath The subdirectory to look for - * - * @return array The plugin paths. - */ - public function getPluginSubPaths($subPath = '') - { - if (array_key_exists($subPath, $this->pluginPaths)) + /** + * Gets the paths plugin sub-directories, minding overloaded plugins. + * + * @param string $subPath The subdirectory to look for + * + * @return array the plugin paths + */ + public function getPluginSubPaths($subPath = '') { - return $this->pluginPaths[$subPath]; + if (array_key_exists($subPath, $this->pluginPaths)) { + return $this->pluginPaths[$subPath]; + } + + $this->pluginPaths[$subPath] = []; + $pluginPaths = $this->getPluginPaths(); + foreach ($pluginPaths as $pluginPath) { + if (is_dir($pluginPath.$subPath)) { + $this->pluginPaths[$subPath][] = $pluginPath.$subPath; + } + } + + return $this->pluginPaths[$subPath]; } - $this->pluginPaths[$subPath] = array(); - $pluginPaths = $this->getPluginPaths(); - foreach ($pluginPaths as $pluginPath) + /** + * Gets the paths to plugins root directories, minding overloaded plugins. + * + * @return array the plugin root paths + * + * @throws InvalidArgumentException If an enabled plugin does not exist + */ + public function getPluginPaths() { - if (is_dir($pluginPath.$subPath)) - { - $this->pluginPaths[$subPath][] = $pluginPath.$subPath; - } + if (!isset($this->pluginPaths[''])) { + $pluginPaths = $this->getAllPluginPaths(); + + $this->pluginPaths[''] = []; + foreach ($this->getPlugins() as $plugin) { + if (isset($pluginPaths[$plugin])) { + $this->pluginPaths[''][] = $pluginPaths[$plugin]; + } else { + throw new InvalidArgumentException(sprintf('The plugin "%s" does not exist.', $plugin)); + } + } + } + + return $this->pluginPaths['']; } - return $this->pluginPaths[$subPath]; - } - - /** - * Gets the paths to plugins root directories, minding overloaded plugins. - * - * @return array The plugin root paths. - * - * @throws InvalidArgumentException If an enabled plugin does not exist - */ - public function getPluginPaths() - { - if (!isset($this->pluginPaths[''])) + /** + * Returns an array of paths for all available plugins. + * + * @return array + */ + public function getAllPluginPaths() { - $pluginPaths = $this->getAllPluginPaths(); - - $this->pluginPaths[''] = array(); - foreach ($this->getPlugins() as $plugin) - { - if (isset($pluginPaths[$plugin])) - { - $this->pluginPaths[''][] = $pluginPaths[$plugin]; + $pluginPaths = []; + + // search for *Plugin directories representing plugins + // follow links and do not recurse. No need to exclude VC because they do not end with *Plugin + $finder = sfFinder::type('dir')->maxdepth(0)->ignore_version_control(false)->follow_link()->name('*Plugin'); + $dirs = [ + $this->getSymfonyLibDir().'/plugins', + sfConfig::get('sf_plugins_dir'), + ]; + + foreach ($finder->in($dirs) as $path) { + $pluginPaths[basename($path)] = $path; } - else - { - throw new InvalidArgumentException(sprintf('The plugin "%s" does not exist.', $plugin)); + + foreach ($this->overriddenPluginPaths as $plugin => $path) { + $pluginPaths[$plugin] = $path; } - } + + return $pluginPaths; } - return $this->pluginPaths['']; - } - - /** - * Returns an array of paths for all available plugins. - * - * @return array - */ - public function getAllPluginPaths() - { - $pluginPaths = array(); - - // search for *Plugin directories representing plugins - // follow links and do not recurse. No need to exclude VC because they do not end with *Plugin - $finder = sfFinder::type('dir')->maxdepth(0)->ignore_version_control(false)->follow_link()->name('*Plugin'); - $dirs = array( - $this->getSymfonyLibDir().'/plugins', - sfConfig::get('sf_plugins_dir'), - ); - - foreach ($finder->in($dirs) as $path) + /** + * Manually sets the location of a particular plugin. + * + * This method can be used to ease functional testing of plugins. It is not + * intended to support sharing plugins between projects, as many plugins + * save project specific code (to /lib/form/base, for example). + * + * @param string $plugin + * @param string $path + */ + public function setPluginPath($plugin, $path) { - $pluginPaths[basename($path)] = $path; + $this->overriddenPluginPaths[$plugin] = realpath($path); } - foreach ($this->overriddenPluginPaths as $plugin => $path) + /** + * Returns the configuration for the requested plugin. + * + * @param string $name + * + * @return sfPluginConfiguration + */ + public function getPluginConfiguration($name) { - $pluginPaths[$plugin] = $path; + if (!isset($this->pluginConfigurations[$name])) { + throw new InvalidArgumentException(sprintf('There is no configuration object for the "%s" object.', $name)); + } + + return $this->pluginConfigurations[$name]; } - return $pluginPaths; - } - - /** - * Manually sets the location of a particular plugin. - * - * This method can be used to ease functional testing of plugins. It is not - * intended to support sharing plugins between projects, as many plugins - * save project specific code (to /lib/form/base, for example). - * - * @param string $plugin - * @param string $path - */ - public function setPluginPath($plugin, $path) - { - $this->overriddenPluginPaths[$plugin] = realpath($path); - } - - /** - * Returns the configuration for the requested plugin. - * - * @param string $name - * - * @return sfPluginConfiguration - */ - public function getPluginConfiguration($name) - { - if (!isset($this->pluginConfigurations[$name])) + /** + * Returns the event dispatcher. + * + * @return sfEventDispatcher A sfEventDispatcher instance + */ + public function getEventDispatcher() { - throw new InvalidArgumentException(sprintf('There is no configuration object for the "%s" object.', $name)); + return $this->dispatcher; } - return $this->pluginConfigurations[$name]; - } - - /** - * Returns the event dispatcher. - * - * @return sfEventDispatcher A sfEventDispatcher instance - */ - public function getEventDispatcher() - { - return $this->dispatcher; - } - - /** - * Returns the symfony lib directory. - * - * @return string The symfony lib directory - */ - public function getSymfonyLibDir() - { - return $this->symfonyLibDir; - } - - /** - * Returns the active configuration. - * - * @return sfApplicationConfiguration The current sfProjectConfiguration instance - */ - static public function getActive() - { - if (!static::hasActive()) + /** + * Returns the symfony lib directory. + * + * @return string The symfony lib directory + */ + public function getSymfonyLibDir() { - throw new RuntimeException('There is no active configuration.'); + return $this->symfonyLibDir; } - return self::$active; - } - - /** - * Returns true if these is an active configuration. - * - * @return boolean - */ - static public function hasActive() - { - return null !== self::$active; - } - - /** - * Guesses the project root directory. - * - * @return string The project root directory - */ - static public function guessRootDir() - { - $r = new ReflectionClass('ProjectConfiguration'); - - return realpath(dirname($r->getFileName()).'/..'); - } - - /** - * Returns a sfApplicationConfiguration configuration for a given application. - * - * @param string $application An application name - * @param string $environment The environment name - * @param Boolean $debug true to enable debug mode - * @param string $rootDir The project root directory - * @param sfEventDispatcher $dispatcher An event dispatcher - * - * @return sfApplicationConfiguration A sfApplicationConfiguration instance - */ - static public function getApplicationConfiguration($application, $environment, $debug, $rootDir = null, sfEventDispatcher $dispatcher = null) - { - $class = $application.'Configuration'; - - if (null === $rootDir) + /** + * Returns the active configuration. + * + * @return sfApplicationConfiguration The current sfProjectConfiguration instance + */ + public static function getActive() { - $rootDir = static::guessRootDir(); + if (!static::hasActive()) { + throw new RuntimeException('There is no active configuration.'); + } + + return self::$active; } - if (!is_file($file = $rootDir.'/apps/'.$application.'/config/'.$class.'.class.php')) + /** + * Returns true if these is an active configuration. + * + * @return bool + */ + public static function hasActive() { - throw new InvalidArgumentException(sprintf('The application "%s" does not exist.', $application)); + return null !== self::$active; } - require_once $file; - - return new $class($environment, $debug, $rootDir, $dispatcher); - } - - /** - * Calls methods defined via sfEventDispatcher. - * - * @param string $method The method name - * @param array $arguments The method arguments - * - * @return mixed The returned value of the called method - * - * @throws sfException - */ - public function __call($method, $arguments) - { - $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'configuration.method_not_found', array('method' => $method, 'arguments' => $arguments))); - if (!$event->isProcessed()) + /** + * Guesses the project root directory. + * + * @return string The project root directory + */ + public static function guessRootDir() { - throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method)); + $r = new ReflectionClass('ProjectConfiguration'); + + return realpath(dirname($r->getFileName()).'/..'); } - return $event->getReturnValue(); - } + /** + * Returns a sfApplicationConfiguration configuration for a given application. + * + * @param string $application An application name + * @param string $environment The environment name + * @param bool $debug true to enable debug mode + * @param string $rootDir The project root directory + * @param sfEventDispatcher $dispatcher An event dispatcher + * + * @return sfApplicationConfiguration A sfApplicationConfiguration instance + */ + public static function getApplicationConfiguration($application, $environment, $debug, $rootDir = null, ?sfEventDispatcher $dispatcher = null) + { + $class = $application.'Configuration'; + + if (null === $rootDir) { + $rootDir = static::guessRootDir(); + } + + if (!is_file($file = $rootDir.'/apps/'.$application.'/config/'.$class.'.class.php')) { + throw new InvalidArgumentException(sprintf('The application "%s" does not exist.', $application)); + } + + require_once $file; + + return new $class($environment, $debug, $rootDir, $dispatcher); + } } diff --git a/lib/config/sfRootConfigHandler.class.php b/lib/config/sfRootConfigHandler.class.php index c48102988..d7dfcbf9d 100644 --- a/lib/config/sfRootConfigHandler.class.php +++ b/lib/config/sfRootConfigHandler.class.php @@ -12,102 +12,95 @@ * sfRootConfigHandler allows you to specify configuration handlers for the * application or on a module level. * - * @package symfony - * @subpackage config * @author Fabien Potencier - * @version SVN: $Id$ */ class sfRootConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - */ - public function execute($configFiles) - { - // parse the yaml - $config = static::getConfiguration($configFiles); - - // determine if we're loading the system config_handlers.yml or a module config_handlers.yml - $moduleLevel = ($this->getParameterHolder()->get('module_level') === true); - - if ($moduleLevel) + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + */ + public function execute($configFiles) { - // get the current module name - $moduleName = $this->getParameterHolder()->get('module_name'); - } + // parse the yaml + $config = static::getConfiguration($configFiles); - // init our data and includes arrays - $data = array(); - $includes = array(); + // determine if we're loading the system config_handlers.yml or a module config_handlers.yml + $moduleLevel = (true === $this->getParameterHolder()->get('module_level')); - // let's do our fancy work - foreach ($config as $category => $keys) - { - if ($moduleLevel) - { - // module-level registration, so we must prepend the module - // root to the category - $category = 'modules/'.$moduleName.'/'.$category; - } - - if (!isset($keys['class'])) - { - // missing class key - throw new sfParseException(sprintf('Configuration file "%s" specifies category "%s" with missing class key.', $configFiles[0], $category)); - } - - $class = $keys['class']; - - if (isset($keys['file'])) - { - if (!is_readable($keys['file'])) - { - // handler file doesn't exist - throw new sfParseException(sprintf('Configuration file "%s" specifies class "%s" with nonexistent or unreadable file "%s".', $configFiles[0], $class, $keys['file'])); + if ($moduleLevel) { + // get the current module name + $moduleName = $this->getParameterHolder()->get('module_name'); } - // append our data - $includes[] = sprintf("require_once('%s');", $keys['file']); - } + // init our data and includes arrays + $data = []; + $includes = []; - // parse parameters - $parameters = (isset($keys['param']) ? var_export($keys['param'], true) : null); + // let's do our fancy work + foreach ($config as $category => $keys) { + if ($moduleLevel) { + // module-level registration, so we must prepend the module + // root to the category + $category = 'modules/'.$moduleName.'/'.$category; + } - // append new data - $data[] = sprintf("\$this->handlers['%s'] = new %s(%s);", $category, $class, $parameters); - } + if (!isset($keys['class'])) { + // missing class key + throw new sfParseException(sprintf('Configuration file "%s" specifies category "%s" with missing class key.', $configFiles[0], $category)); + } - // compile data - $retval = sprintf(" $keys) - { - if (isset($keys['file'])) - { - $config[$category]['file'] = static::replacePath($keys['file']); - } + // parse parameters + $parameters = (isset($keys['param']) ? var_export($keys['param'], true) : null); + + // append new data + $data[] = sprintf("\$this->handlers['%s'] = new %s(%s);", $category, $class, $parameters); + } + + // compile data + $retval = sprintf( + " $keys) { + if (isset($keys['file'])) { + $config[$category]['file'] = static::replacePath($keys['file']); + } + } + + return $config; + } } diff --git a/lib/config/sfRoutingConfigHandler.class.php b/lib/config/sfRoutingConfigHandler.class.php index 9e75fa955..f917bd4ab 100644 --- a/lib/config/sfRoutingConfigHandler.class.php +++ b/lib/config/sfRoutingConfigHandler.class.php @@ -9,109 +9,103 @@ */ /** - * @package symfony - * @subpackage config * @author Fabien Potencier - * @version SVN: $Id$ */ class sfRoutingConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler. - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - */ - public function execute($configFiles) - { - $options = $this->getOptions(); - unset($options['cache']); - - $data = array(); - foreach ($this->parse($configFiles) as $name => $routeConfig) + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + */ + public function execute($configFiles) { - $r = new ReflectionClass($routeConfig[0]); - /** @var sfRoute $route */ - $route = $r->newInstanceArgs($routeConfig[1]); - - $routes = $route instanceof sfRouteCollection ? $route : array($name => $route); - foreach (sfPatternRouting::flattenRoutes($routes) as $name => $route) - { - $route->setDefaultOptions($options); - $data[] = sprintf('$this->routes[\'%s\'] = %s;', $name, var_export(serialize($route), true)); - } + $options = $this->getOptions(); + unset($options['cache']); + + $data = []; + foreach ($this->parse($configFiles) as $name => $routeConfig) { + $r = new ReflectionClass($routeConfig[0]); + + /** @var sfRoute $route */ + $route = $r->newInstanceArgs($routeConfig[1]); + + $routes = $route instanceof sfRouteCollection ? $route : [$name => $route]; + foreach (sfPatternRouting::flattenRoutes($routes) as $name => $route) { + $route->setDefaultOptions($options); + $data[] = sprintf('$this->routes[\'%s\'] = %s;', $name, var_export(serialize($route), true)); + } + } + + return sprintf( + "parse($configFiles); - protected function getOptions() - { - $config = sfFactoryConfigHandler::getConfiguration(sfContext::getInstance()->getConfiguration()->getConfigPaths('config/factories.yml')); - return $config['routing']['param']; - } + $routes = []; + foreach ($routeDefinitions as $name => $route) { + $r = new ReflectionClass($route[0]); + $routes[$name] = $r->newInstanceArgs($route[1]); + } - public function evaluate($configFiles) - { - $routeDefinitions = $this->parse($configFiles); + return $routes; + } - $routes = array(); - foreach ($routeDefinitions as $name => $route) + /** + * @see sfConfigHandler + */ + public static function getConfiguration(array $configFiles) { - $r = new ReflectionClass($route[0]); - $routes[$name] = $r->newInstanceArgs($route[1]); + return static::parseYamls($configFiles); } - return $routes; - } + protected function getOptions() + { + $config = sfFactoryConfigHandler::getConfiguration(sfContext::getInstance()->getConfiguration()->getConfigPaths('config/factories.yml')); - protected function parse($configFiles) - { - // parse the yaml - $config = static::getConfiguration($configFiles); + return $config['routing']['param']; + } - // collect routes - $routes = array(); - foreach ($config as $name => $params) + protected function parse($configFiles) { - if ( - (isset($params['type']) && 'collection' == $params['type']) - || - (isset($params['class']) && false !== strpos($params['class'], 'Collection')) - ) - { - $options = isset($params['options']) ? $params['options'] : array(); - $options['name'] = $name; - $options['requirements'] = isset($params['requirements']) ? $params['requirements'] : array(); - - $routes[$name] = array(isset($params['class']) ? $params['class'] : 'sfRouteCollection', array($options)); - } - else - { - $routes[$name] = array(isset($params['class']) ? $params['class'] : 'sfRoute', array( - $params['url'] ?: '/', - isset($params['params']) ? $params['params'] : (isset($params['param']) ? $params['param'] : array()), - isset($params['requirements']) ? $params['requirements'] : array(), - isset($params['options']) ? $params['options'] : array(), - )); - } - } + // parse the yaml + $config = static::getConfiguration($configFiles); - return $routes; - } + // collect routes + $routes = []; + foreach ($config as $name => $params) { + if ( + (isset($params['type']) && 'collection' == $params['type']) + || (isset($params['class']) && false !== strpos($params['class'], 'Collection')) + ) { + $options = isset($params['options']) ? $params['options'] : []; + $options['name'] = $name; + $options['requirements'] = isset($params['requirements']) ? $params['requirements'] : []; - /** - * @see sfConfigHandler - */ - static public function getConfiguration(array $configFiles) - { - return static::parseYamls($configFiles); - } + $routes[$name] = [isset($params['class']) ? $params['class'] : 'sfRouteCollection', [$options]]; + } else { + $routes[$name] = [isset($params['class']) ? $params['class'] : 'sfRoute', [ + $params['url'] ?: '/', + isset($params['params']) ? $params['params'] : (isset($params['param']) ? $params['param'] : []), + isset($params['requirements']) ? $params['requirements'] : [], + isset($params['options']) ? $params['options'] : [], + ]]; + } + } + + return $routes; + } } diff --git a/lib/config/sfSecurityConfigHandler.class.php b/lib/config/sfSecurityConfigHandler.class.php index 57efcfb27..cf145cd9d 100644 --- a/lib/config/sfSecurityConfigHandler.class.php +++ b/lib/config/sfSecurityConfigHandler.class.php @@ -11,49 +11,48 @@ /** * sfSecurityConfigHandler allows you to configure action security. * - * @package symfony - * @subpackage config * @author Fabien Potencier - * @version SVN: $Id$ */ class sfSecurityConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler. - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - * @throws sfInitializationException If a view.yml key check fails - */ - public function execute($configFiles) - { - // parse the yaml - $config = static::getConfiguration($configFiles); + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + * @throws sfInitializationException If a view.yml key check fails + */ + public function execute($configFiles) + { + // parse the yaml + $config = static::getConfiguration($configFiles); - // compile data - $retval = sprintf("security = %s;\n", - date('Y/m/d H:i:s'), var_export($config, true)); + // compile data + $retval = sprintf( + "security = %s;\n", + date('Y/m/d H:i:s'), + var_export($config, true) + ); - return $retval; - } + return $retval; + } - /** - * @see sfConfigHandler - * @inheritdoc - */ - static public function getConfiguration(array $configFiles) - { - $config = static::flattenConfiguration(static::parseYamls($configFiles)); + /** + * @see sfConfigHandler + */ + public static function getConfiguration(array $configFiles) + { + $config = static::flattenConfiguration(static::parseYamls($configFiles)); - // change all of the keys to lowercase - $config = array_change_key_case($config); + // change all of the keys to lowercase + $config = array_change_key_case($config); - return $config; - } + return $config; + } } diff --git a/lib/config/sfServiceConfigHandler.class.php b/lib/config/sfServiceConfigHandler.class.php index f4ecc74c9..0735f5fa6 100644 --- a/lib/config/sfServiceConfigHandler.class.php +++ b/lib/config/sfServiceConfigHandler.class.php @@ -11,59 +11,58 @@ /** * sfSecurityConfigHandler allows you to configure action security. * - * @package symfony - * @subpackage config * @author Jerome Tamarelle - * @version SVN: $Id$ */ class sfServiceConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler. - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - */ - public function execute($configFiles) - { - $class = sfConfig::get('sf_app').'_'.sfConfig::get('sf_environment').'ServiceContainer'; + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + */ + public function execute($configFiles) + { + $class = sfConfig::get('sf_app').'_'.sfConfig::get('sf_environment').'ServiceContainer'; - $serviceContainerBuilder = new sfServiceContainerBuilder(); + $serviceContainerBuilder = new sfServiceContainerBuilder(); - $loader = new sfServiceContainerLoaderArray($serviceContainerBuilder); - $loader->load(static::getConfiguration($configFiles)); + $loader = new sfServiceContainerLoaderArray($serviceContainerBuilder); + $loader->load(static::getConfiguration($configFiles)); - $dumper = new sfServiceContainerDumperPhp($serviceContainerBuilder); - $code = $dumper->dump(array( - 'class' => $class, - 'base_class' => $this->parameterHolder->get('base_class'), - )); + $dumper = new sfServiceContainerDumperPhp($serviceContainerBuilder); + $code = $dumper->dump([ + 'class' => $class, + 'base_class' => $this->parameterHolder->get('base_class'), + ]); - // compile data - $retval = sprintf( - " - * @version SVN: $Id$ */ class sfSimpleYamlConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler. - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - */ - public function execute($configFiles) - { - $config = static::getConfiguration($configFiles); + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + */ + public function execute($configFiles) + { + $config = static::getConfiguration($configFiles); - // compile data - $retval = " - * @version SVN: $Id$ */ class sfViewConfigHandler extends sfYamlConfigHandler { - /** - * Executes this configuration handler. - * - * @param array $configFiles An array of absolute filesystem path to a configuration file - * - * @return string Data to be written to a cache file - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - * @throws sfInitializationException If a view.yml key check fails - */ - public function execute($configFiles) - { - // parse the yaml - $this->yamlConfig = static::getConfiguration($configFiles); + /** + * Executes this configuration handler. + * + * @param array $configFiles An array of absolute filesystem path to a configuration file + * + * @return string Data to be written to a cache file + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + * @throws sfInitializationException If a view.yml key check fails + */ + public function execute($configFiles) + { + // parse the yaml + $this->yamlConfig = static::getConfiguration($configFiles); - // init our data array - $data = array(); + // init our data array + $data = []; - $data[] = "\$response = \$this->context->getResponse();\n\n"; + $data[] = "\$response = \$this->context->getResponse();\n\n"; - // first pass: iterate through all view names to determine the real view name - $first = true; - foreach ($this->yamlConfig as $viewName => $values) - { - if ($viewName == 'all') - { - continue; - } + // first pass: iterate through all view names to determine the real view name + $first = true; + foreach ($this->yamlConfig as $viewName => $values) { + if ('all' == $viewName) { + continue; + } - $data[] = ($first ? '' : 'else ')."if (\$this->actionName.\$this->viewName == '$viewName')\n". - "{\n"; - $data[] = $this->addTemplate($viewName); - $data[] = "}\n"; + $data[] = ($first ? '' : 'else ')."if (\$this->actionName.\$this->viewName == '{$viewName}')\n". + "{\n"; + $data[] = $this->addTemplate($viewName); + $data[] = "}\n"; - $first = false; - } + $first = false; + } - // general view configuration - $data[] = ($first ? '' : "else\n{")."\n"; - $data[] = $this->addTemplate($viewName); - $data[] = ($first ? '' : "}")."\n\n"; + // general view configuration + $data[] = ($first ? '' : "else\n{")."\n"; + $data[] = $this->addTemplate($viewName); + $data[] = ($first ? '' : '}')."\n\n"; - // second pass: iterate through all real view names - $first = true; - foreach ($this->yamlConfig as $viewName => $values) - { - if ($viewName == 'all') - { - continue; - } + // second pass: iterate through all real view names + $first = true; + foreach ($this->yamlConfig as $viewName => $values) { + if ('all' == $viewName) { + continue; + } - $data[] = ($first ? '' : 'else ')."if (\$templateName.\$this->viewName == '$viewName')\n". - "{\n"; + $data[] = ($first ? '' : 'else ')."if (\$templateName.\$this->viewName == '{$viewName}')\n". + "{\n"; - $data[] = $this->addLayout($viewName); - $data[] = $this->addComponentSlots($viewName); - $data[] = $this->addHtmlHead($viewName); - $data[] = $this->addEscaping($viewName); + $data[] = $this->addLayout($viewName); + $data[] = $this->addComponentSlots($viewName); + $data[] = $this->addHtmlHead($viewName); + $data[] = $this->addEscaping($viewName); - $data[] = $this->addHtmlAsset($viewName); + $data[] = $this->addHtmlAsset($viewName); - $data[] = "}\n"; + $data[] = "}\n"; - $first = false; - } + $first = false; + } - // general view configuration - $data[] = ($first ? '' : "else\n{")."\n"; + // general view configuration + $data[] = ($first ? '' : "else\n{")."\n"; - $data[] = $this->addLayout(); - $data[] = $this->addComponentSlots(); - $data[] = $this->addHtmlHead(); - $data[] = $this->addEscaping(); + $data[] = $this->addLayout(); + $data[] = $this->addComponentSlots(); + $data[] = $this->addHtmlHead(); + $data[] = $this->addEscaping(); - $data[] = $this->addHtmlAsset(); - $data[] = ($first ? '' : "}")."\n"; + $data[] = $this->addHtmlAsset(); + $data[] = ($first ? '' : '}')."\n"; - // compile data - $retval = sprintf("mergeConfigValue('components', $viewName); - foreach ($components as $name => $component) + /** + * Adds a component slot statement to the data. + * + * @param string $viewName The view name + * + * @return string The PHP statement + */ + protected function addComponentSlots($viewName = '') { - if (!is_array($component) || count($component) < 1) - { - $component = array(null, null); - } + $data = ''; - $data .= " \$this->setComponentSlot('$name', '{$component[0]}', '{$component[1]}');\n"; - $data .= " if (sfConfig::get('sf_logging_enabled')) \$this->context->getEventDispatcher()->notify(new sfEvent(\$this, 'application.log', array(sprintf('Set component \"%s\" (%s/%s)', '$name', '{$component[0]}', '{$component[1]}'))));\n"; - } + $components = $this->mergeConfigValue('components', $viewName); + foreach ($components as $name => $component) { + if (!is_array($component) || count($component) < 1) { + $component = [null, null]; + } - return $data; - } + $data .= " \$this->setComponentSlot('{$name}', '{$component[0]}', '{$component[1]}');\n"; + $data .= " if (sfConfig::get('sf_logging_enabled')) \$this->context->getEventDispatcher()->notify(new sfEvent(\$this, 'application.log', array(sprintf('Set component \"%s\" (%s/%s)', '{$name}', '{$component[0]}', '{$component[1]}'))));\n"; + } - /** - * Adds a template setting statement to the data. - * - * @param string $viewName The view name - * - * @return string The PHP statement - */ - protected function addTemplate($viewName = '') - { - $data = ''; + return $data; + } - $templateName = $this->getConfigValue('template', $viewName); - $defaultTemplateName = $templateName ? "'$templateName'" : '$this->actionName'; + /** + * Adds a template setting statement to the data. + * + * @param string $viewName The view name + * + * @return string The PHP statement + */ + protected function addTemplate($viewName = '') + { + $data = ''; - $data .= " \$templateName = sfConfig::get('symfony.view.'.\$this->moduleName.'_'.\$this->actionName.'_template', $defaultTemplateName);\n"; - $data .= " \$this->setTemplate(\$templateName.\$this->viewName.\$this->getExtension());\n"; + $templateName = $this->getConfigValue('template', $viewName); + $defaultTemplateName = $templateName ? "'{$templateName}'" : '$this->actionName'; - return $data; - } + $data .= " \$templateName = sfConfig::get('symfony.view.'.\$this->moduleName.'_'.\$this->actionName.'_template', {$defaultTemplateName});\n"; + $data .= " \$this->setTemplate(\$templateName.\$this->viewName.\$this->getExtension());\n"; - /** - * Adds a layout statement statement to the data. - * - * @param string $viewName The view name - * - * @return string The PHP statement - */ - protected function addLayout($viewName = '') - { - // true if the user set 'has_layout' to true or set a 'layout' name for this specific action - $hasLocalLayout = isset($this->yamlConfig[$viewName]['layout']) || (isset($this->yamlConfig[$viewName]) && array_key_exists('has_layout', $this->yamlConfig[$viewName])); + return $data; + } - // the layout value - $layout = $this->getConfigValue('has_layout', $viewName) ? $this->getConfigValue('layout', $viewName) : false; + /** + * Adds a layout statement statement to the data. + * + * @param string $viewName The view name + * + * @return string The PHP statement + */ + protected function addLayout($viewName = '') + { + // true if the user set 'has_layout' to true or set a 'layout' name for this specific action + $hasLocalLayout = isset($this->yamlConfig[$viewName]['layout']) || (isset($this->yamlConfig[$viewName]) && array_key_exists('has_layout', $this->yamlConfig[$viewName])); - // the user set a decorator in the action - $data = <<moduleName.'_'.\$this->actionName.'_layout')) + // the layout value + $layout = $this->getConfigValue('has_layout', $viewName) ? $this->getConfigValue('layout', $viewName) : false; + + // the user set a decorator in the action + $data = <<<'EOF' + if (null !== $layout = sfConfig::get('symfony.view.'.$this->moduleName.'_'.$this->actionName.'_layout')) { - \$this->setDecoratorTemplate(false === \$layout ? false : \$layout.\$this->getExtension()); + $this->setDecoratorTemplate(false === $layout ? false : $layout.$this->getExtension()); } EOF; - if ($hasLocalLayout) - { - // the user set a decorator in view.yml for this action - $data .= <<setDecoratorTemplate('' == '$layout' ? false : '$layout'.\$this->getExtension()); + \$this->setDecoratorTemplate('' == '{$layout}' ? false : '{$layout}'.\$this->getExtension()); } EOF; - } - else - { - // no specific configuration - // set the layout to the 'all' view.yml value except if: - // * the decorator template has already been set by "someone" (via view.configure_format for example) - // * the request is an XMLHttpRequest request - $data .= <<getDecoratorTemplate() && !\$this->context->getRequest()->isXmlHttpRequest()) { - \$this->setDecoratorTemplate('' == '$layout' ? false : '$layout'.\$this->getExtension()); + \$this->setDecoratorTemplate('' == '{$layout}' ? false : '{$layout}'.\$this->getExtension()); } EOF; + } + + return $data; } - return $data; - } + /** + * Adds http metas and metas statements to the data. + * + * @param string $viewName The view name + * + * @return string The PHP statement + */ + protected function addHtmlHead($viewName = '') + { + $data = []; - /** - * Adds http metas and metas statements to the data. - * - * @param string $viewName The view name - * - * @return string The PHP statement - */ - protected function addHtmlHead($viewName = '') - { - $data = array(); + foreach ($this->mergeConfigValue('http_metas', $viewName) as $httpequiv => $content) { + $data[] = sprintf(" \$response->addHttpMeta('%s', '%s', false);", $httpequiv, str_replace('\'', '\\\'', $content)); + } - foreach ($this->mergeConfigValue('http_metas', $viewName) as $httpequiv => $content) - { - $data[] = sprintf(" \$response->addHttpMeta('%s', '%s', false);", $httpequiv, str_replace('\'', '\\\'', $content)); - } + foreach ($this->mergeConfigValue('metas', $viewName) as $name => $content) { + $data[] = sprintf(" \$response->addMeta('%s', '%s', false, false);", $name, str_replace('\'', '\\\'', preg_replace('/&(?=\w+;)/', '&', htmlspecialchars((string) $content, ENT_QUOTES, sfConfig::get('sf_charset'))))); + } - foreach ($this->mergeConfigValue('metas', $viewName) as $name => $content) - { - $data[] = sprintf(" \$response->addMeta('%s', '%s', false, false);", $name, str_replace('\'', '\\\'', preg_replace('/&(?=\w+;)/', '&', htmlspecialchars($content == null ? '' : $content, ENT_QUOTES, sfConfig::get('sf_charset'))))); + return implode("\n", $data)."\n"; } - return implode("\n", $data)."\n"; - } - - /** - * Adds stylesheets and javascripts statements to the data. - * - * @param string $viewName The view name - * - * @return string The PHP statement - */ - protected function addHtmlAsset($viewName = '') - { - // Merge the current view's stylesheets with the app's default stylesheets - $stylesheets = $this->mergeConfigValue('stylesheets', $viewName); - $css = $this->addAssets('Stylesheet', $stylesheets); + /** + * Adds stylesheets and javascripts statements to the data. + * + * @param string $viewName The view name + * + * @return string The PHP statement + */ + protected function addHtmlAsset($viewName = '') + { + // Merge the current view's stylesheets with the app's default stylesheets + $stylesheets = $this->mergeConfigValue('stylesheets', $viewName); + $css = $this->addAssets('Stylesheet', $stylesheets); - // Merge the current view's javascripts with the app's default javascripts - $javascripts = $this->mergeConfigValue('javascripts', $viewName); - $js = $this->addAssets('Javascript', $javascripts); + // Merge the current view's javascripts with the app's default javascripts + $javascripts = $this->mergeConfigValue('javascripts', $viewName); + $js = $this->addAssets('Javascript', $javascripts); - return implode("\n", array_merge($css, $js))."\n"; - } + return implode("\n", array_merge($css, $js))."\n"; + } - /** - * Creates a list of add$Type PHP statements for the given type and config. - * - * @param string $type of asset. Requires an sfWebResponse->add$Type(string, string, array) method - * @param array $assets - * - * @return array ist of add$Type PHP statements - */ - private function addAssets($type, $assets){ - $tmp = array(); - foreach ((array) $assets as $asset) + /** + * Adds an escaping statement to the data. + * + * @param string $viewName The view name + * + * @return string The PHP statement + */ + protected function addEscaping($viewName = '') { - $position = ''; - if (is_array($asset)) - { - reset($asset); - $key = key($asset); - $options = $asset[$key]; - if (isset($options['position'])) - { - $position = $options['position']; - unset($options['position']); - } - } - else - { - $key = $asset; - $options = array(); - } - - if ('-*' == $key) - { - $tmp = array(); - } - else if ('-' == $key[0]) - { - unset($tmp[substr($key, 1)]); - } - else - { - $tmp[$key] = sprintf(" \$response->add%s('%s', '%s', %s);", $type, $key, $position, str_replace("\n", '', var_export($options, true))); - } - } - return array_values($tmp); - } + $data = []; - /** - * Adds an escaping statement to the data. - * - * @param string $viewName The view name - * - * @return string The PHP statement - */ - protected function addEscaping($viewName = '') - { - $data = array(); + $escaping = $this->getConfigValue('escaping', $viewName); - $escaping = $this->getConfigValue('escaping', $viewName); + if (isset($escaping['method'])) { + $data[] = sprintf(' $this->getAttributeHolder()->setEscapingMethod(%s);', var_export($escaping['method'], true)); + } - if (isset($escaping['method'])) - { - $data[] = sprintf(" \$this->getAttributeHolder()->setEscapingMethod(%s);", var_export($escaping['method'], true)); + return implode("\n", $data)."\n"; } - return implode("\n", $data)."\n"; - } + protected static function mergeConfig($config) + { + // merge javascripts and stylesheets + $config['all']['stylesheets'] = array_merge(isset($config['default']['stylesheets']) && is_array($config['default']['stylesheets']) ? $config['default']['stylesheets'] : [], isset($config['all']['stylesheets']) && is_array($config['all']['stylesheets']) ? $config['all']['stylesheets'] : []); + unset($config['default']['stylesheets']); - /** - * @see sfConfigHandler - * @inheritdoc - */ - static public function getConfiguration(array $configFiles) - { - return static::mergeConfig(static::parseYamls($configFiles)); - } + $config['all']['javascripts'] = array_merge(isset($config['default']['javascripts']) && is_array($config['default']['javascripts']) ? $config['default']['javascripts'] : [], isset($config['all']['javascripts']) && is_array($config['all']['javascripts']) ? $config['all']['javascripts'] : []); + unset($config['default']['javascripts']); - static protected function mergeConfig($config) - { - // merge javascripts and stylesheets - $config['all']['stylesheets'] = array_merge(isset($config['default']['stylesheets']) && is_array($config['default']['stylesheets']) ? $config['default']['stylesheets'] : array(), isset($config['all']['stylesheets']) && is_array($config['all']['stylesheets']) ? $config['all']['stylesheets'] : array()); - unset($config['default']['stylesheets']); + // merge default and all + $config['all'] = sfToolkit::arrayDeepMerge( + isset($config['default']) && is_array($config['default']) ? $config['default'] : [], + isset($config['all']) && is_array($config['all']) ? $config['all'] : [] + ); - $config['all']['javascripts'] = array_merge(isset($config['default']['javascripts']) && is_array($config['default']['javascripts']) ? $config['default']['javascripts'] : array(), isset($config['all']['javascripts']) && is_array($config['all']['javascripts']) ? $config['all']['javascripts'] : array()); - unset($config['default']['javascripts']); + unset($config['default']); - // merge default and all - $config['all'] = sfToolkit::arrayDeepMerge( - isset($config['default']) && is_array($config['default']) ? $config['default'] : array(), - isset($config['all']) && is_array($config['all']) ? $config['all'] : array() - ); + return static::replaceConstants($config); + } - unset($config['default']); + /** + * Creates a list of add$Type PHP statements for the given type and config. + * + * @param string $type of asset. Requires an sfWebResponse->add$Type(string, string, array) method + * @param array $assets + * + * @return array ist of add$Type PHP statements + */ + private function addAssets($type, $assets) + { + $tmp = []; + foreach ((array) $assets as $asset) { + $position = ''; + if (is_array($asset)) { + reset($asset); + $key = key($asset); + $options = $asset[$key]; + if (isset($options['position'])) { + $position = $options['position']; + unset($options['position']); + } + } else { + $key = $asset; + $options = []; + } + + if ('-*' == $key) { + $tmp = []; + } elseif ('-' == $key[0]) { + unset($tmp[substr($key, 1)]); + } else { + $tmp[$key] = sprintf(" \$response->add%s('%s', '%s', %s);", $type, $key, $position, str_replace("\n", '', var_export($options, true))); + } + } - return static::replaceConstants($config); - } + return array_values($tmp); + } } diff --git a/lib/config/sfYamlConfigHandler.class.php b/lib/config/sfYamlConfigHandler.class.php index 5a41f6045..d1ea1e798 100644 --- a/lib/config/sfYamlConfigHandler.class.php +++ b/lib/config/sfYamlConfigHandler.class.php @@ -12,147 +12,135 @@ * sfYamlConfigHandler is a base class for YAML (.yml) configuration handlers. This class * provides a central location for parsing YAML files. * - * @package symfony - * @subpackage config * @author Fabien Potencier - * @version SVN: $Id$ */ abstract class sfYamlConfigHandler extends sfConfigHandler { - /** @var array */ - protected $yamlConfig = null; - - /** - * Parses an array of YAMLs files and merges them in one configuration array. - * - * @param array $configFiles An array of configuration file paths - * - * @return array A merged configuration array - */ - static public function parseYamls($configFiles) - { - $config = array(); - foreach ($configFiles as $configFile) + /** @var array */ + protected $yamlConfig; + + /** + * Parses an array of YAMLs files and merges them in one configuration array. + * + * @param array $configFiles An array of configuration file paths + * + * @return array A merged configuration array + */ + public static function parseYamls($configFiles) { - // the first level is an environment and its value must be an array - $values = array(); - foreach (static::parseYaml($configFile) as $env => $value) - { - if (null !== $value) - { - $values[$env] = $value; + $config = []; + foreach ($configFiles as $configFile) { + // the first level is an environment and its value must be an array + $values = []; + foreach (static::parseYaml($configFile) as $env => $value) { + if (null !== $value) { + $values[$env] = $value; + } + } + + $config = sfToolkit::arrayDeepMerge($config, $values); } - } - $config = sfToolkit::arrayDeepMerge($config, $values); + return $config; } - return $config; - } - - /** - * Parses a YAML (.yml) configuration file. - * - * @param string $configFile An absolute filesystem path to a configuration file - * - * @return string|array A parsed .yml configuration - * - * @throws sfConfigurationException If a requested configuration file does not exist or is not readable - * @throws sfParseException If a requested configuration file is improperly formatted - */ - static public function parseYaml($configFile) - { - if (!is_readable($configFile)) + /** + * Parses a YAML (.yml) configuration file. + * + * @param string $configFile An absolute filesystem path to a configuration file + * + * @return array|string A parsed .yml configuration + * + * @throws sfConfigurationException If a requested configuration file does not exist or is not readable + * @throws sfParseException If a requested configuration file is improperly formatted + */ + public static function parseYaml($configFile) { - // can't read the configuration - throw new sfConfigurationException(sprintf('Configuration file "%s" does not exist or is not readable.', $configFile)); - } + if (!is_readable($configFile)) { + // can't read the configuration + throw new sfConfigurationException(sprintf('Configuration file "%s" does not exist or is not readable.', $configFile)); + } - // parse our config - $config = sfYaml::load($configFile, sfConfig::get('sf_charset', 'UTF-8')); + // parse our config + $config = sfYaml::load($configFile, sfConfig::get('sf_charset', 'UTF-8')); - if ($config === false) - { - // configuration couldn't be parsed - throw new sfParseException(sprintf('Configuration file "%s" could not be parsed', $configFile)); + if (false === $config) { + // configuration couldn't be parsed + throw new sfParseException(sprintf('Configuration file "%s" could not be parsed', $configFile)); + } + + return null === $config ? [] : $config; } - return null === $config ? array() : $config; - } - - /** - * Merges configuration values for a given key and category. - * - * @param string $keyName The key name - * @param string $category The category name - * - * @return array The value associated with this key name and category - */ - protected function mergeConfigValue($keyName, $category) - { - $values = array(); - - if (isset($this->yamlConfig['all'][$keyName]) && is_array($this->yamlConfig['all'][$keyName])) + public static function flattenConfiguration($config) { - $values = $this->yamlConfig['all'][$keyName]; + $config['all'] = sfToolkit::arrayDeepMerge( + isset($config['default']) && is_array($config['default']) ? $config['default'] : [], + isset($config['all']) && is_array($config['all']) ? $config['all'] : [] + ); + + unset($config['default']); + + return $config; } - if ($category && isset($this->yamlConfig[$category][$keyName]) && is_array($this->yamlConfig[$category][$keyName])) + /** + * Merges default, all and current environment configurations. + * + * @param array $config The main configuratino array + * + * @return array The merged configuration + */ + public static function flattenConfigurationWithEnvironment($config) { - $values = array_merge($values, $this->yamlConfig[$category][$keyName]); + return sfToolkit::arrayDeepMerge( + isset($config['default']) && is_array($config['default']) ? $config['default'] : [], + isset($config['all']) && is_array($config['all']) ? $config['all'] : [], + isset($config[sfConfig::get('sf_environment')]) && is_array($config[sfConfig::get('sf_environment')]) ? $config[sfConfig::get('sf_environment')] : [] + ); } - return $values; - } - - /** - * Gets a configuration value for a given key and category. - * - * @param string $keyName The key name - * @param string $category The category name - * @param string $defaultValue The default value - * - * @return string The value associated with this key name and category - */ - protected function getConfigValue($keyName, $category, $defaultValue = null) - { - if (isset($this->yamlConfig[$category][$keyName])) + /** + * Merges configuration values for a given key and category. + * + * @param string $keyName The key name + * @param string $category The category name + * + * @return array The value associated with this key name and category + */ + protected function mergeConfigValue($keyName, $category) { - return $this->yamlConfig[$category][$keyName]; + $values = []; + + if (isset($this->yamlConfig['all'][$keyName]) && is_array($this->yamlConfig['all'][$keyName])) { + $values = $this->yamlConfig['all'][$keyName]; + } + + if ($category && isset($this->yamlConfig[$category][$keyName]) && is_array($this->yamlConfig[$category][$keyName])) { + $values = array_merge($values, $this->yamlConfig[$category][$keyName]); + } + + return $values; } - else if (isset($this->yamlConfig['all'][$keyName])) + + /** + * Gets a configuration value for a given key and category. + * + * @param string $keyName The key name + * @param string $category The category name + * @param string $defaultValue The default value + * + * @return string The value associated with this key name and category + */ + protected function getConfigValue($keyName, $category, $defaultValue = null) { - return $this->yamlConfig['all'][$keyName]; - } + if (isset($this->yamlConfig[$category][$keyName])) { + return $this->yamlConfig[$category][$keyName]; + } + if (isset($this->yamlConfig['all'][$keyName])) { + return $this->yamlConfig['all'][$keyName]; + } - return $defaultValue; - } - - static public function flattenConfiguration($config) - { - $config['all'] = sfToolkit::arrayDeepMerge( - isset($config['default']) && is_array($config['default']) ? $config['default'] : array(), - isset($config['all']) && is_array($config['all']) ? $config['all'] : array() - ); - - unset($config['default']); - - return $config; - } - - /** - * Merges default, all and current environment configurations. - * - * @param array $config The main configuratino array - * - * @return array The merged configuration - */ - static public function flattenConfigurationWithEnvironment($config) - { - return sfToolkit::arrayDeepMerge( - isset($config['default']) && is_array($config['default']) ? $config['default'] : array(), - isset($config['all']) && is_array($config['all']) ? $config['all'] : array(), - isset($config[sfConfig::get('sf_environment')]) && is_array($config[sfConfig::get('sf_environment')]) ? $config[sfConfig::get('sf_environment')] : array() - ); - } + return $defaultValue; + } } diff --git a/lib/controller/default/actions/actions.class.php b/lib/controller/default/actions/actions.class.php index 09784acdc..639ea95ed 100644 --- a/lib/controller/default/actions/actions.class.php +++ b/lib/controller/default/actions/actions.class.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) 2004-2006 Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -11,58 +11,49 @@ /** * defaultActions module. * - * @package symfony - * @subpackage action * @author Fabien Potencier - * @version SVN: $Id$ */ class defaultActions extends sfActions { - /** - * Congratulations page for creating an application - * - */ - public function executeIndex() - { - } + /** + * Congratulations page for creating an application. + */ + public function executeIndex() + { + } - /** - * Congratulations page for creating a module - * - */ - public function executeModule() - { - } + /** + * Congratulations page for creating a module. + */ + public function executeModule() + { + } - /** - * Error page for page not found (404) error - * - */ - public function executeError404() - { - } + /** + * Error page for page not found (404) error. + */ + public function executeError404() + { + } - /** - * Warning page for restricted area - requires login - * - */ - public function executeSecure() - { - } + /** + * Warning page for restricted area - requires login. + */ + public function executeSecure() + { + } - /** - * Warning page for restricted area - requires credentials - * - */ - public function executeLogin() - { - } + /** + * Warning page for restricted area - requires credentials. + */ + public function executeLogin() + { + } - /** - * Module disabled in settings.yml - * - */ - public function executeDisabled() - { - } + /** + * Module disabled in settings.yml. + */ + public function executeDisabled() + { + } } diff --git a/lib/controller/default/templates/defaultLayout.php b/lib/controller/default/templates/defaultLayout.php index 08b4eb2c9..8aa94057f 100644 --- a/lib/controller/default/templates/defaultLayout.php +++ b/lib/controller/default/templates/defaultLayout.php @@ -2,24 +2,24 @@ - - - - - - + + + + + +
- 'symfony PHP Framework', 'class' => 'sfTLogo', 'size' => '186x39')), 'http://www.symfony-project.org/') ?> - + 'symfony PHP Framework', 'class' => 'sfTLogo', 'size' => '186x39']), 'http://www.symfony-project.org/'); ?> +
diff --git a/lib/controller/default/templates/disabledSuccess.php b/lib/controller/default/templates/disabledSuccess.php index b9cb12c1b..d52ff435b 100644 --- a/lib/controller/default/templates/disabledSuccess.php +++ b/lib/controller/default/templates/disabledSuccess.php @@ -1,7 +1,7 @@ - +
- 'module disabled', 'class' => 'sfTMessageIcon', 'size' => '48x48')) ?> + 'module disabled', 'class' => 'sfTMessageIcon', 'size' => '48x48']); ?>

This Module is Unavailable

This module has been disabled.
@@ -13,7 +13,7 @@
diff --git a/lib/controller/default/templates/error404Success.php b/lib/controller/default/templates/error404Success.php index a836b757e..9a65929a1 100644 --- a/lib/controller/default/templates/error404Success.php +++ b/lib/controller/default/templates/error404Success.php @@ -1,7 +1,7 @@ - +
- 'page not found', 'class' => 'sfTMessageIcon', 'size' => '48x48')) ?> + 'page not found', 'class' => 'sfTMessageIcon', 'size' => '48x48']); ?>

Oops! Page Not Found

The server returned a 404 response.
@@ -12,16 +12,16 @@
You may have typed the address (URL) incorrectly. Check it to make sure you've got the exact right spelling, capitalization, etc.
Did you follow a link from somewhere else at this site?
-
If you reached this page from another part of this site, please email us at so we can correct our mistake.
+
If you reached this page from another part of this site, please email us at so we can correct our mistake.
Did you follow a link from another site?
-
Links from other sites can sometimes be outdated or misspelled. Email us at where you came from and we can try to contact the other site in order to fix the problem.
+
Links from other sites can sometimes be outdated or misspelled. Email us at where you came from and we can try to contact the other site in order to fix the problem.
What's next
diff --git a/lib/controller/default/templates/indexSuccess.php b/lib/controller/default/templates/indexSuccess.php index c4fcb9e8f..9d887fb63 100644 --- a/lib/controller/default/templates/indexSuccess.php +++ b/lib/controller/default/templates/indexSuccess.php @@ -1,7 +1,7 @@ - +
- 'ok', 'class' => 'sfTMessageIcon', 'size' => '48x48')) ?> + 'ok', 'class' => 'sfTMessageIcon', 'size' => '48x48']); ?>

Symfony Project Created

Congratulations! You have successfully created your symfony project.
@@ -19,7 +19,7 @@
  • Create your data model
  • Customize the layout of the generated templates
  • -
  • +
diff --git a/lib/controller/default/templates/loginSuccess.php b/lib/controller/default/templates/loginSuccess.php index 0c064b08b..ea2603779 100644 --- a/lib/controller/default/templates/loginSuccess.php +++ b/lib/controller/default/templates/loginSuccess.php @@ -1,7 +1,7 @@ - +
- 'login required', 'class' => 'sfTMessageIcon', 'size' => '48x48')) ?> + 'login required', 'class' => 'sfTMessageIcon', 'size' => '48x48']); ?>

Login Required

This page is not public.
@@ -14,7 +14,7 @@
What's Next
diff --git a/lib/controller/default/templates/moduleSuccess.php b/lib/controller/default/templates/moduleSuccess.php index cacd8cb74..f26727222 100644 --- a/lib/controller/default/templates/moduleSuccess.php +++ b/lib/controller/default/templates/moduleSuccess.php @@ -1,9 +1,9 @@ - +
- 'module created', 'class' => 'sfTMessageIcon', 'size' => '48x48')) ?> + 'module created', 'class' => 'sfTMessageIcon', 'size' => '48x48']); ?>
-

Module "get('module') ?>" created

+

Module "get('module'); ?>" created

Congratulations! You have successfully created a symfony module.
@@ -14,10 +14,10 @@
What's next
    -
  • Browse to the apps/getConfiguration()->getApplication() ?>/modules/get('module') ?>/ directory
  • +
  • Browse to the apps/getConfiguration()->getApplication(); ?>/modules/get('module'); ?>/ directory
  • In actions/actions.class.php, edit the executeIndex() method and remove the final forward
  • Customize the templates/indexSuccess.php template
  • -
  • +
diff --git a/lib/controller/default/templates/secureSuccess.php b/lib/controller/default/templates/secureSuccess.php index 19d893378..912963b26 100644 --- a/lib/controller/default/templates/secureSuccess.php +++ b/lib/controller/default/templates/secureSuccess.php @@ -1,7 +1,7 @@ - +
- 'credentials required', 'class' => 'sfTMessageIcon', 'size' => '48x48')) ?> + 'credentials required', 'class' => 'sfTMessageIcon', 'size' => '48x48']); ?>

Credentials Required

This page is in a restricted area.
diff --git a/lib/controller/sfController.class.php b/lib/controller/sfController.class.php index 6b69b857d..b420285fc 100644 --- a/lib/controller/sfController.class.php +++ b/lib/controller/sfController.class.php @@ -12,515 +12,479 @@ /** * sfController directs application flow. * - * @package symfony - * @subpackage controller * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ abstract class sfController { - /** @var sfContext */ - protected $context = null; - /** @var sfEventDispatcher */ - protected $dispatcher = null; - /** @var string[] */ - protected $controllerClasses = array(); - /** @var int */ - protected $renderMode = sfView::RENDER_CLIENT; - /** @var int */ - protected $maxForwards = 5; - - /** - * Class constructor. - * - * @see initialize() - * @param sfContext $context A sfContext implementation instance - */ - public function __construct($context) - { - $this->initialize($context); - } - - /** - * Initializes this controller. - * - * @param sfContext $context A sfContext implementation instance - */ - public function initialize($context) - { - $this->context = $context; - $this->dispatcher = $context->getEventDispatcher(); - } - - /** - * Indicates whether or not a module has a specific component. - * - * @param string $moduleName A module name - * @param string $componentName An component name - * - * @return bool true, if the component exists, otherwise false - */ - public function componentExists($moduleName, $componentName) - { - return $this->controllerExists($moduleName, $componentName, 'component', false); - } - - /** - * Indicates whether or not a module has a specific action. - * - * @param string $moduleName A module name - * @param string $actionName An action name - * - * @return bool true, if the action exists, otherwise false - */ - public function actionExists($moduleName, $actionName) - { - return $this->controllerExists($moduleName, $actionName, 'action', false); - } - - /** - * Looks for a controller and optionally throw exceptions if existence is required (i.e. - * in the case of {@link getController()}). - * - * @param string $moduleName The name of the module - * @param string $controllerName The name of the controller within the module - * @param string $extension Either 'action' or 'component' depending on the type of controller to look for - * @param boolean $throwExceptions Whether to throw exceptions if the controller doesn't exist - * - * @throws sfConfigurationException thrown if the module is not enabled - * @throws sfControllerException thrown if the controller doesn't exist and the $throwExceptions parameter is set to true - * - * @return boolean true if the controller exists, false otherwise - */ - protected function controllerExists($moduleName, $controllerName, $extension, $throwExceptions) - { - $dirs = $this->context->getConfiguration()->getControllerDirs($moduleName); - foreach ($dirs as $dir => $checkEnabled) - { - // plugin module enabled? - if ($checkEnabled && !in_array($moduleName, sfConfig::get('sf_enabled_modules')) && is_readable($dir)) - { - throw new sfConfigurationException(sprintf('The module "%s" is not enabled.', $moduleName)); - } - - // check for a module generator config file - $this->context->getConfigCache()->import('modules/'.$moduleName.'/config/generator.yml', false, true); - - // one action per file or one file for all actions - $classFile = strtolower($extension); - $classSuffix = ucfirst(strtolower($extension)); - $file = $dir.'/'.$controllerName.$classSuffix.'.class.php'; - if (is_readable($file)) - { - // action class exists - require_once($file); - - $this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix] = $controllerName.$classSuffix; - - return true; - } - - $module_file = $dir.'/'.$classFile.'s.class.php'; - if (is_readable($module_file)) - { - // module class exists - require_once($module_file); - - if (!class_exists($moduleName.$classSuffix.'s', false)) - { - if ($throwExceptions) - { - throw new sfControllerException(sprintf('There is no "%s" class in your action file "%s".', $moduleName.$classSuffix.'s', $module_file)); - } - - return false; - } + /** @var sfContext */ + protected $context; - // action is defined in this class? - if (!in_array('execute'.ucfirst($controllerName), get_class_methods($moduleName.$classSuffix.'s'))) - { - if ($throwExceptions) - { - throw new sfControllerException(sprintf('There is no "%s" method in your action class "%s".', 'execute'.ucfirst($controllerName), $moduleName.$classSuffix.'s')); - } + /** @var sfEventDispatcher */ + protected $dispatcher; - return false; - } + /** @var string[] */ + protected $controllerClasses = []; + + /** @var int */ + protected $renderMode = sfView::RENDER_CLIENT; + + /** @var int */ + protected $maxForwards = 5; - $this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix] = $moduleName.$classSuffix.'s'; - return true; - } + /** + * Class constructor. + * + * @see initialize() + * + * @param sfContext $context A sfContext implementation instance + */ + public function __construct($context) + { + $this->initialize($context); } - // send an exception if debug - if ($throwExceptions && sfConfig::get('sf_debug')) + /** + * Calls methods defined via sfEventDispatcher. + * + * @param string $method The method name + * @param array $arguments The method arguments + * + * @return mixed The returned value of the called method + * + * @throws sfException + */ + public function __call($method, $arguments) { - $dirs = array_map(array('sfDebug', 'shortenFilePath'), array_keys($dirs)); + $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'controller.method_not_found', ['method' => $method, 'arguments' => $arguments])); + if (!$event->isProcessed()) { + throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method)); + } - throw new sfControllerException(sprintf('Controller "%s/%s" does not exist in: %s.', $moduleName, $controllerName, implode(', ', $dirs))); + return $event->getReturnValue(); } - return false; - } - - /** - * Forwards the request to another action. - * - * @param string $moduleName A module name - * @param string $actionName An action name - * - * @throws sfConfigurationException If an invalid configuration setting has been found - * @throws sfForwardException If an error occurs while forwarding the request - * @throws sfError404Exception If the action not exist - * @throws sfInitializationException If the action could not be initialized - */ - public function forward($moduleName, $actionName) - { - // replace unwanted characters - $moduleName = preg_replace('/[^a-z0-9_]+/i', '', $moduleName); - $actionName = preg_replace('/[^a-z0-9_]+/i', '', $actionName); - - if ($this->getActionStack()->getSize() >= $this->maxForwards) + /** + * Initializes this controller. + * + * @param sfContext $context A sfContext implementation instance + */ + public function initialize($context) { - // let's kill this party before it turns into cpu cycle hell - throw new sfForwardException('Too many forwards have been detected for this request.'); + $this->context = $context; + $this->dispatcher = $context->getEventDispatcher(); } - // check for a module generator config file - $this->context->getConfigCache()->import('modules/'.$moduleName.'/config/generator.yml', false, true); - - if (!$this->actionExists($moduleName, $actionName)) + /** + * Indicates whether or not a module has a specific component. + * + * @param string $moduleName A module name + * @param string $componentName An component name + * + * @return bool true, if the component exists, otherwise false + */ + public function componentExists($moduleName, $componentName) { - // the requested action doesn't exist - if (sfConfig::get('sf_logging_enabled')) - { - $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Action "%s/%s" does not exist', $moduleName, $actionName)))); - } - - throw new sfError404Exception(sprintf('Action "%s/%s" does not exist.', $moduleName, $actionName)); + return $this->controllerExists($moduleName, $componentName, 'component', false); } - // create an instance of the action - $actionInstance = $this->getAction($moduleName, $actionName); - - // add a new action stack entry - $this->getActionStack()->addEntry($moduleName, $actionName, $actionInstance); - - // include module configuration - $viewClass = sfConfig::get('mod_'.strtolower($moduleName).'_view_class', false); - require($this->context->getConfigCache()->checkConfig('modules/'.$moduleName.'/config/module.yml')); - if (false !== $viewClass) + /** + * Indicates whether or not a module has a specific action. + * + * @param string $moduleName A module name + * @param string $actionName An action name + * + * @return bool true, if the action exists, otherwise false + */ + public function actionExists($moduleName, $actionName) { - sfConfig::set('mod_'.strtolower($moduleName).'_view_class', $viewClass); + return $this->controllerExists($moduleName, $actionName, 'action', false); } - // module enabled? - if (sfConfig::get('mod_'.strtolower($moduleName).'_enabled')) + /** + * Forwards the request to another action. + * + * @param string $moduleName A module name + * @param string $actionName An action name + * + * @throws sfConfigurationException If an invalid configuration setting has been found + * @throws sfForwardException If an error occurs while forwarding the request + * @throws sfError404Exception If the action not exist + * @throws sfInitializationException If the action could not be initialized + */ + public function forward($moduleName, $actionName) { - // check for a module config.php - $moduleConfig = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/config/config.php'; - if (is_readable($moduleConfig)) - { - require_once($moduleConfig); - } + // replace unwanted characters + $moduleName = preg_replace('/[^a-z0-9_]+/i', '', $moduleName); + $actionName = preg_replace('/[^a-z0-9_]+/i', '', $actionName); + + if ($this->getActionStack()->getSize() >= $this->maxForwards) { + // let's kill this party before it turns into cpu cycle hell + throw new sfForwardException('Too many forwards have been detected for this request.'); + } - // create a new filter chain - $filterChain = new sfFilterChain(); - $filterChain->loadConfiguration($actionInstance); + // check for a module generator config file + $this->context->getConfigCache()->import('modules/'.$moduleName.'/config/generator.yml', false, true); - $this->context->getEventDispatcher()->notify(new sfEvent($this, 'controller.change_action', array('module' => $moduleName, 'action' => $actionName))); + if (!$this->actionExists($moduleName, $actionName)) { + // the requested action doesn't exist + if (sfConfig::get('sf_logging_enabled')) { + $this->dispatcher->notify(new sfEvent($this, 'application.log', [sprintf('Action "%s/%s" does not exist', $moduleName, $actionName)])); + } - if ($moduleName == sfConfig::get('sf_error_404_module') && $actionName == sfConfig::get('sf_error_404_action')) - { - $this->context->getResponse()->setStatusCode(404); - $this->context->getResponse()->setHttpHeader('Status', '404 Not Found'); + throw new sfError404Exception(sprintf('Action "%s/%s" does not exist.', $moduleName, $actionName)); + } - $this->dispatcher->notify(new sfEvent($this, 'controller.page_not_found', array('module' => $moduleName, 'action' => $actionName))); - } + // create an instance of the action + $actionInstance = $this->getAction($moduleName, $actionName); - // process the filter chain - $filterChain->execute(); - } - else - { - $moduleName = sfConfig::get('sf_module_disabled_module'); - $actionName = sfConfig::get('sf_module_disabled_action'); + // add a new action stack entry + $this->getActionStack()->addEntry($moduleName, $actionName, $actionInstance); + + // include module configuration + $viewClass = sfConfig::get('mod_'.strtolower($moduleName).'_view_class', false); - if (!$this->actionExists($moduleName, $actionName)) - { - // cannot find mod disabled module/action - throw new sfConfigurationException(sprintf('Invalid configuration settings: [sf_module_disabled_module] "%s", [sf_module_disabled_action] "%s".', $moduleName, $actionName)); - } + require $this->context->getConfigCache()->checkConfig('modules/'.$moduleName.'/config/module.yml'); + if (false !== $viewClass) { + sfConfig::set('mod_'.strtolower($moduleName).'_view_class', $viewClass); + } + + // module enabled? + if (sfConfig::get('mod_'.strtolower($moduleName).'_enabled')) { + // check for a module config.php + $moduleConfig = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/config/config.php'; + if (is_readable($moduleConfig)) { + require_once $moduleConfig; + } + + // create a new filter chain + $filterChain = new sfFilterChain(); + $filterChain->loadConfiguration($actionInstance); + + $this->context->getEventDispatcher()->notify(new sfEvent($this, 'controller.change_action', ['module' => $moduleName, 'action' => $actionName])); + + if ($moduleName == sfConfig::get('sf_error_404_module') && $actionName == sfConfig::get('sf_error_404_action')) { + $this->context->getResponse()->setStatusCode(404); + $this->context->getResponse()->setHttpHeader('Status', '404 Not Found'); - $this->forward($moduleName, $actionName); + $this->dispatcher->notify(new sfEvent($this, 'controller.page_not_found', ['module' => $moduleName, 'action' => $actionName])); + } + + // process the filter chain + $filterChain->execute(); + } else { + $moduleName = sfConfig::get('sf_module_disabled_module'); + $actionName = sfConfig::get('sf_module_disabled_action'); + + if (!$this->actionExists($moduleName, $actionName)) { + // cannot find mod disabled module/action + throw new sfConfigurationException(sprintf('Invalid configuration settings: [sf_module_disabled_module] "%s", [sf_module_disabled_action] "%s".', $moduleName, $actionName)); + } + + $this->forward($moduleName, $actionName); + } } - } - - /** - * Retrieves an sfAction implementation instance. - * - * @param string $moduleName A module name - * @param string $actionName An action name - * - * @return sfAction An sfAction implementation instance, if the action exists, otherwise null - */ - public function getAction($moduleName, $actionName) - { - return $this->getController($moduleName, $actionName, 'action'); - } - - /** - * Retrieves a sfComponent implementation instance. - * - * @param string $moduleName A module name - * @param string $componentName A component name - * - * @return sfComponent A sfComponent implementation instance, if the component exists, otherwise null - */ - public function getComponent($moduleName, $componentName) - { - return $this->getController($moduleName, $componentName, 'component'); - } - - /** - * Retrieves a controller implementation instance. - * - * @param string $moduleName A module name - * @param string $controllerName A component name - * @param string $extension Either 'action' or 'component' depending on the type of controller to look for - * - * @return sfAction A controller implementation instance, if the controller exists, otherwise null - * - * @see getComponent(), getAction() - */ - protected function getController($moduleName, $controllerName, $extension) - { - $classSuffix = ucfirst(strtolower($extension)); - if (!isset($this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix])) + + /** + * Retrieves an sfAction implementation instance. + * + * @param string $moduleName A module name + * @param string $actionName An action name + * + * @return sfAction An sfAction implementation instance, if the action exists, otherwise null + */ + public function getAction($moduleName, $actionName) { - if (!$this->controllerExists($moduleName, $controllerName, $extension, true)) - { - return null; - } + return $this->getController($moduleName, $actionName, 'action'); } - $class = $this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix]; + /** + * Retrieves a sfComponent implementation instance. + * + * @param string $moduleName A module name + * @param string $componentName A component name + * + * @return sfComponent A sfComponent implementation instance, if the component exists, otherwise null + */ + public function getComponent($moduleName, $componentName) + { + return $this->getController($moduleName, $componentName, 'component'); + } - // fix for same name classes - $moduleClass = $moduleName.'_'.$class; + /** + * Retrieves the action stack. + * + * @return sfActionStack An sfActionStack instance, if the action stack is enabled, otherwise null + */ + public function getActionStack() + { + return $this->context->getActionStack(); + } - if (class_exists($moduleClass, false)) + /** + * Retrieves the presentation rendering mode. + * + * @return int One of the following: + * - sfView::RENDER_CLIENT + * - sfView::RENDER_VAR + */ + public function getRenderMode() { - $class = $moduleClass; + return $this->renderMode; } - return new $class($this->context, $moduleName, $controllerName); - } - - /** - * Retrieves the action stack. - * - * @return sfActionStack An sfActionStack instance, if the action stack is enabled, otherwise null - */ - public function getActionStack() - { - return $this->context->getActionStack(); - } - - /** - * Retrieves the presentation rendering mode. - * - * @return int One of the following: - * - sfView::RENDER_CLIENT - * - sfView::RENDER_VAR - */ - public function getRenderMode() - { - return $this->renderMode; - } - - /** - * Retrieves a sfView implementation instance. - * - * @param string $moduleName A module name - * @param string $actionName An action name - * @param string $viewName A view name - * - * @return sfView A sfView implementation instance, if the view exists, otherwise null - */ - public function getView($moduleName, $actionName, $viewName) - { - // user view exists? - $file = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/view/'.$actionName.$viewName.'View.class.php'; - - if (is_readable($file)) + /** + * Retrieves a sfView implementation instance. + * + * @param string $moduleName A module name + * @param string $actionName An action name + * @param string $viewName A view name + * + * @return sfView A sfView implementation instance, if the view exists, otherwise null + */ + public function getView($moduleName, $actionName, $viewName) { - require_once($file); + // user view exists? + $file = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/view/'.$actionName.$viewName.'View.class.php'; - $class = $actionName.$viewName.'View'; + if (is_readable($file)) { + require_once $file; - // fix for same name classes - $moduleClass = $moduleName.'_'.$class; + $class = $actionName.$viewName.'View'; - if (class_exists($moduleClass, false)) - { - $class = $moduleClass; - } - } - else - { - // view class (as configured in module.yml or defined in action) - $class = sfConfig::get('mod_'.strtolower($moduleName).'_view_class', 'sfPHP').'View'; + // fix for same name classes + $moduleClass = $moduleName.'_'.$class; + + if (class_exists($moduleClass, false)) { + $class = $moduleClass; + } + } else { + // view class (as configured in module.yml or defined in action) + $class = sfConfig::get('mod_'.strtolower($moduleName).'_view_class', 'sfPHP').'View'; + } + + return new $class($this->context, $moduleName, $actionName, $viewName); } - return new $class($this->context, $moduleName, $actionName, $viewName); - } - - /** - * Returns the rendered view presentation of a given module/action. - * - * @param string $module A module name - * @param string $action An action name - * @param string $viewName A View class name - * - * @return string The generated content - * - * @throws Exception - * @throws sfException - */ - public function getPresentationFor($module, $action, $viewName = null) - { - if (sfConfig::get('sf_logging_enabled')) + /** + * Returns the rendered view presentation of a given module/action. + * + * @param string $module A module name + * @param string $action An action name + * @param string $viewName A View class name + * + * @return string The generated content + * + * @throws Exception + * @throws sfException + */ + public function getPresentationFor($module, $action, $viewName = null) { - $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Get presentation for action "%s/%s" (view class: "%s")', $module, $action, $viewName)))); - } + if (sfConfig::get('sf_logging_enabled')) { + $this->dispatcher->notify(new sfEvent($this, 'application.log', [sprintf('Get presentation for action "%s/%s" (view class: "%s")', $module, $action, $viewName)])); + } - // get original render mode - $renderMode = $this->getRenderMode(); + // get original render mode + $renderMode = $this->getRenderMode(); - // set render mode to var - $this->setRenderMode(sfView::RENDER_VAR); + // set render mode to var + $this->setRenderMode(sfView::RENDER_VAR); - // grab the action stack - $actionStack = $this->getActionStack(); + // grab the action stack + $actionStack = $this->getActionStack(); - // grab this next forward's action stack index - $index = $actionStack->getSize(); + // grab this next forward's action stack index + $index = $actionStack->getSize(); - // set viewName if needed - if ($viewName) - { - $currentViewName = sfConfig::get('mod_'.strtolower($module).'_view_class'); - sfConfig::set('mod_'.strtolower($module).'_view_class', $viewName); - } + // set viewName if needed + if ($viewName) { + $currentViewName = sfConfig::get('mod_'.strtolower($module).'_view_class'); + sfConfig::set('mod_'.strtolower($module).'_view_class', $viewName); + } - try - { - // forward to the action - $this->forward($module, $action); - } - catch (Exception $e) - { - // put render mode back - $this->setRenderMode($renderMode); + try { + // forward to the action + $this->forward($module, $action); + } catch (Exception $e) { + // put render mode back + $this->setRenderMode($renderMode); - // remove viewName - if ($viewName) - { - sfConfig::set('mod_'.strtolower($module).'_view_class', $currentViewName); - } + // remove viewName + if ($viewName) { + sfConfig::set('mod_'.strtolower($module).'_view_class', $currentViewName); + } - throw $e; - } + throw $e; + } + + // grab the action entry from this forward + $actionEntry = $actionStack->getEntry($index); - // grab the action entry from this forward - $actionEntry = $actionStack->getEntry($index); + // get raw content + $presentation = &$actionEntry->getPresentation(); - // get raw content - $presentation =& $actionEntry->getPresentation(); + // put render mode back + $this->setRenderMode($renderMode); - // put render mode back - $this->setRenderMode($renderMode); + // remove the action entry + $nb = $actionStack->getSize() - $index; + while ($nb-- > 0) { + $actionEntry = $actionStack->popEntry(); + + if ($actionEntry->getModuleName() == sfConfig::get('sf_login_module') && $actionEntry->getActionName() == sfConfig::get('sf_login_action')) { + throw new sfException('Your action is secured, but the user is not authenticated.'); + } + if ($actionEntry->getModuleName() == sfConfig::get('sf_secure_module') && $actionEntry->getActionName() == sfConfig::get('sf_secure_action')) { + throw new sfException('Your action is secured, but the user does not have access.'); + } + } + + // remove viewName + if ($viewName) { + sfConfig::set('mod_'.strtolower($module).'_view_class', $currentViewName); + } - // remove the action entry - $nb = $actionStack->getSize() - $index; - while ($nb-- > 0) + return $presentation; + } + + /** + * Sets the presentation rendering mode. + * + * @param int $mode A rendering mode one of the following: + * - sfView::RENDER_CLIENT + * - sfView::RENDER_VAR + * - sfView::RENDER_NONE + * + * @throws sfRenderException If an invalid render mode has been set + */ + public function setRenderMode($mode) { - $actionEntry = $actionStack->popEntry(); - - if ($actionEntry->getModuleName() == sfConfig::get('sf_login_module') && $actionEntry->getActionName() == sfConfig::get('sf_login_action')) - { - throw new sfException('Your action is secured, but the user is not authenticated.'); - } - else if ($actionEntry->getModuleName() == sfConfig::get('sf_secure_module') && $actionEntry->getActionName() == sfConfig::get('sf_secure_action')) - { - throw new sfException('Your action is secured, but the user does not have access.'); - } + if (sfView::RENDER_CLIENT == $mode || sfView::RENDER_VAR == $mode || sfView::RENDER_NONE == $mode) { + $this->renderMode = $mode; + + return; + } + + // invalid rendering mode type + throw new sfRenderException(sprintf('Invalid rendering mode: %s.', $mode)); } - // remove viewName - if ($viewName) + /** + * Indicates whether or not we were called using the CLI version of PHP. + * + * @return bool true, if using cli, otherwise false + */ + public function inCLI() { - sfConfig::set('mod_'.strtolower($module).'_view_class', $currentViewName); + return 'cli' == PHP_SAPI; } - return $presentation; - } - - /** - * Sets the presentation rendering mode. - * - * @param int $mode A rendering mode one of the following: - * - sfView::RENDER_CLIENT - * - sfView::RENDER_VAR - * - sfView::RENDER_NONE - * - * @return void - * - * @throws sfRenderException If an invalid render mode has been set - */ - public function setRenderMode($mode) - { - if ($mode == sfView::RENDER_CLIENT || $mode == sfView::RENDER_VAR || $mode == sfView::RENDER_NONE) + /** + * Looks for a controller and optionally throw exceptions if existence is required (i.e. + * in the case of {@link getController()}). + * + * @param string $moduleName The name of the module + * @param string $controllerName The name of the controller within the module + * @param string $extension Either 'action' or 'component' depending on the type of controller to look for + * @param bool $throwExceptions Whether to throw exceptions if the controller doesn't exist + * + * @return bool true if the controller exists, false otherwise + * + * @throws sfConfigurationException thrown if the module is not enabled + * @throws sfControllerException thrown if the controller doesn't exist and the $throwExceptions parameter is set to true + */ + protected function controllerExists($moduleName, $controllerName, $extension, $throwExceptions) { - $this->renderMode = $mode; + $dirs = $this->context->getConfiguration()->getControllerDirs($moduleName); + foreach ($dirs as $dir => $checkEnabled) { + // plugin module enabled? + if ($checkEnabled && !in_array($moduleName, sfConfig::get('sf_enabled_modules')) && is_readable($dir)) { + throw new sfConfigurationException(sprintf('The module "%s" is not enabled.', $moduleName)); + } + + // check for a module generator config file + $this->context->getConfigCache()->import('modules/'.$moduleName.'/config/generator.yml', false, true); + + // one action per file or one file for all actions + $classFile = strtolower($extension); + $classSuffix = ucfirst(strtolower($extension)); + $file = $dir.'/'.$controllerName.$classSuffix.'.class.php'; + if (is_readable($file)) { + // action class exists + require_once $file; + + $this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix] = $controllerName.$classSuffix; + + return true; + } + + $module_file = $dir.'/'.$classFile.'s.class.php'; + if (is_readable($module_file)) { + // module class exists + require_once $module_file; + + if (!class_exists($moduleName.$classSuffix.'s', false)) { + if ($throwExceptions) { + throw new sfControllerException(sprintf('There is no "%s" class in your action file "%s".', $moduleName.$classSuffix.'s', $module_file)); + } + + return false; + } + + // action is defined in this class? + if (!in_array('execute'.ucfirst($controllerName), get_class_methods($moduleName.$classSuffix.'s'))) { + if ($throwExceptions) { + throw new sfControllerException(sprintf('There is no "%s" method in your action class "%s".', 'execute'.ucfirst($controllerName), $moduleName.$classSuffix.'s')); + } + + return false; + } + + $this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix] = $moduleName.$classSuffix.'s'; + + return true; + } + } + + // send an exception if debug + if ($throwExceptions && sfConfig::get('sf_debug')) { + $dirs = array_map(['sfDebug', 'shortenFilePath'], array_keys($dirs)); + + throw new sfControllerException(sprintf('Controller "%s/%s" does not exist in: %s.', $moduleName, $controllerName, implode(', ', $dirs))); + } - return; + return false; } - // invalid rendering mode type - throw new sfRenderException(sprintf('Invalid rendering mode: %s.', $mode)); - } - - /** - * Indicates whether or not we were called using the CLI version of PHP. - * - * @return bool true, if using cli, otherwise false. - */ - public function inCLI() - { - return 'cli' == PHP_SAPI; - } - - /** - * Calls methods defined via sfEventDispatcher. - * - * @param string $method The method name - * @param array $arguments The method arguments - * - * @return mixed The returned value of the called method - * - * @throws sfException - */ - public function __call($method, $arguments) - { - $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'controller.method_not_found', array('method' => $method, 'arguments' => $arguments))); - if (!$event->isProcessed()) + /** + * Retrieves a controller implementation instance. + * + * @param string $moduleName A module name + * @param string $controllerName A component name + * @param string $extension Either 'action' or 'component' depending on the type of controller to look for + * + * @return sfAction A controller implementation instance, if the controller exists, otherwise null + * + * @see getComponent(), getAction() + */ + protected function getController($moduleName, $controllerName, $extension) { - throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method)); - } + $classSuffix = ucfirst(strtolower($extension)); + if (!isset($this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix])) { + if (!$this->controllerExists($moduleName, $controllerName, $extension, true)) { + return null; + } + } + + $class = $this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix]; - return $event->getReturnValue(); - } + // fix for same name classes + $moduleClass = $moduleName.'_'.$class; + + if (class_exists($moduleClass, false)) { + $class = $moduleClass; + } + + return new $class($this->context, $moduleName, $controllerName); + } } diff --git a/lib/controller/sfFrontWebController.class.php b/lib/controller/sfFrontWebController.class.php index aa2b52197..073dea69c 100644 --- a/lib/controller/sfFrontWebController.class.php +++ b/lib/controller/sfFrontWebController.class.php @@ -14,47 +14,38 @@ * application, but at the same time allow for any module and action combination * to be requested. * - * @package symfony - * @subpackage controller * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ class sfFrontWebController extends sfWebController { - /** - * Dispatches a request. - * - * This will determine which module and action to use by request parameters specified by the user. - */ - public function dispatch() - { - try + /** + * Dispatches a request. + * + * This will determine which module and action to use by request parameters specified by the user. + */ + public function dispatch() { - // reinitialize filters (needed for unit and functional tests) - sfFilter::$filterCalled = array(); + try { + // reinitialize filters (needed for unit and functional tests) + sfFilter::$filterCalled = []; - // determine our module and action - /** @var sfWebRequest $request */ - $request = $this->context->getRequest(); - $moduleName = $request->getParameter('module'); - $actionName = $request->getParameter('action'); + // determine our module and action + /** @var sfWebRequest $request */ + $request = $this->context->getRequest(); + $moduleName = $request->getParameter('module'); + $actionName = $request->getParameter('action'); - if (empty($moduleName) || empty($actionName)) - { - throw new sfError404Exception(sprintf('Empty module and/or action after parsing the URL "%s" (%s/%s).', $request->getPathInfo(), $moduleName, $actionName)); - } + if (empty($moduleName) || empty($actionName)) { + throw new sfError404Exception(sprintf('Empty module and/or action after parsing the URL "%s" (%s/%s).', $request->getPathInfo(), $moduleName, $actionName)); + } - // make the first request - $this->forward($moduleName, $actionName); + // make the first request + $this->forward($moduleName, $actionName); + } catch (sfException $e) { + $e->printStackTrace(); + } catch (Exception $e) { + sfException::createFromException($e)->printStackTrace(); + } } - catch (sfException $e) - { - $e->printStackTrace(); - } - catch (Exception $e) - { - sfException::createFromException($e)->printStackTrace(); - } - } } diff --git a/lib/controller/sfWebController.class.php b/lib/controller/sfWebController.class.php index dceebab3a..a759153be 100644 --- a/lib/controller/sfWebController.class.php +++ b/lib/controller/sfWebController.class.php @@ -12,137 +12,114 @@ /** * sfWebController provides web specific methods to sfController such as, url redirection. * - * @package symfony - * @subpackage controller * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ abstract class sfWebController extends sfController { - /** - * Generates an URL from an array of parameters. - * - * @param string|array $parameters An associative array of URL parameters or an internal URI as a string. - * @param boolean $absolute Whether to generate an absolute URL - * - * @return string A URL to a symfony resource - */ - public function genUrl($parameters = array(), $absolute = false) - { - $route = ''; - $fragment = ''; - - if (is_string($parameters)) + /** + * Generates an URL from an array of parameters. + * + * @param array|string $parameters an associative array of URL parameters or an internal URI as a string + * @param bool $absolute Whether to generate an absolute URL + * + * @return string A URL to a symfony resource + */ + public function genUrl($parameters = [], $absolute = false) { - // absolute URL or symfony URL? - if (preg_match('#^[a-z][a-z0-9\+.\-]*\://#i', $parameters)) - { - return $parameters; - } - - // relative URL? - if (0 === strpos($parameters, '/')) - { - return $parameters; - } - - if ($parameters == '#') - { - return $parameters; - } - - // strip fragment - if (false !== ($pos = strpos($parameters, '#'))) - { - $fragment = substr($parameters, $pos + 1); - $parameters = substr($parameters, 0, $pos); - } - - list($route, $parameters) = $this->convertUrlStringToParameters($parameters); - } - else if (is_array($parameters)) - { - if (isset($parameters['sf_route'])) - { - $route = $parameters['sf_route']; - unset($parameters['sf_route']); - } - } - - // routing to generate path - $url = $this->context->getRouting()->generate($route, $parameters, $absolute); - - if ($fragment) - { - $url .= '#'.$fragment; - } - - return $url; - } - - /** - * Converts an internal URI string to an array of parameters. - * - * @param string $url An internal URI - * - * @return array An array of parameters - * - * @throws sfParseException - */ - public function convertUrlStringToParameters($url) - { - $givenUrl = $url; - - $params = array(); - $queryString = ''; - $route = ''; - - // empty url? - if (!$url) - { - $url = '/'; - } - - // we get the query string out of the url - if ($pos = strpos($url, '?')) - { - $queryString = substr($url, $pos + 1); - $url = substr($url, 0, $pos); - } - - // 2 url forms - // @routeName?key1=value1&key2=value2... - // module/action?key1=value1&key2=value2... - - // first slash optional - if ($url[0] == '/') - { - $url = substr($url, 1); + $route = ''; + $fragment = ''; + + if (is_string($parameters)) { + // absolute URL or symfony URL? + if (preg_match('#^[a-z][a-z0-9\+.\-]*\://#i', $parameters)) { + return $parameters; + } + + // relative URL? + if (0 === strpos($parameters, '/')) { + return $parameters; + } + + if ('#' == $parameters) { + return $parameters; + } + + // strip fragment + if (false !== ($pos = strpos($parameters, '#'))) { + $fragment = substr($parameters, $pos + 1); + $parameters = substr($parameters, 0, $pos); + } + + list($route, $parameters) = $this->convertUrlStringToParameters($parameters); + } elseif (is_array($parameters)) { + if (isset($parameters['sf_route'])) { + $route = $parameters['sf_route']; + unset($parameters['sf_route']); + } + } + + // routing to generate path + $url = $this->context->getRouting()->generate($route, $parameters, $absolute); + + if ($fragment) { + $url .= '#'.$fragment; + } + + return $url; } - // routeName? - if ($url && $url[0] == '@') + /** + * Converts an internal URI string to an array of parameters. + * + * @param string $url An internal URI + * + * @return array An array of parameters + * + * @throws sfParseException + */ + public function convertUrlStringToParameters($url) { - $route = substr($url, 1); - } - else if (false !== strpos($url, '/')) - { - list($params['module'], $params['action']) = explode('/', $url); - } - else if (!$queryString) - { - $route = $givenUrl; - } - else - { - throw new InvalidArgumentException(sprintf('An internal URI must contain a module and an action (module/action) ("%s" given).', $givenUrl)); - } - - // split the query string - if ($queryString) - { - $matched = preg_match_all('/ + $givenUrl = $url; + + $params = []; + $queryString = ''; + $route = ''; + + // empty url? + if (!$url) { + $url = '/'; + } + + // we get the query string out of the url + if ($pos = strpos($url, '?')) { + $queryString = substr($url, $pos + 1); + $url = substr($url, 0, $pos); + } + + // 2 url forms + // @routeName?key1=value1&key2=value2... + // module/action?key1=value1&key2=value2... + + // first slash optional + if ('/' == $url[0]) { + $url = substr($url, 1); + } + + // routeName? + if ($url && '@' == $url[0]) { + $route = substr($url, 1); + } elseif (false !== strpos($url, '/')) { + list($params['module'], $params['action']) = explode('/', $url); + } elseif (!$queryString) { + $route = $givenUrl; + } else { + throw new InvalidArgumentException(sprintf('An internal URI must contain a module and an action (module/action) ("%s" given).', $givenUrl)); + } + + // split the query string + if ($queryString) { + $matched = preg_match_all('/ ([^&=]+) # key = # = (.*?) # value @@ -150,67 +127,62 @@ public function convertUrlStringToParameters($url) (?=&[^&=]+=) | $ # followed by another key= or the end of the string ) /x', $queryString, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE); - foreach ($matches as $match) - { - $params[urldecode($match[1][0])] = urldecode($match[2][0]); - } - - // check that all string is matched - if (!$matched) - { - throw new sfParseException(sprintf('Unable to parse query string "%s".', $queryString)); - } - } + foreach ($matches as $match) { + $params[urldecode($match[1][0])] = urldecode($match[2][0]); + } - return array($route, $params); - } - - /** - * Redirects the request to another URL. - * - * @param string|array $url An associative array of URL parameters or an internal URI as a string - * @param int $delay A delay in seconds before redirecting. This is only needed on - * browsers that do not support HTTP headers - * @param int $statusCode The status code - * - * @throws InvalidArgumentException If the url argument is null or an empty string - */ - public function redirect($url, $delay = 0, $statusCode = 302) - { - if (empty($url)) - { - throw new InvalidArgumentException('Cannot redirect to an empty URL.'); - } + // check that all string is matched + if (!$matched) { + throw new sfParseException(sprintf('Unable to parse query string "%s".', $queryString)); + } + } - $url = $this->genUrl($url, true); - // see #8083 - $url = str_replace('&', '&', $url); - // JS Added - make commas unencoded - $url = str_replace('%2C', ',', $url); - // see http://stackoverflow.com/questions/21046623/http-build-query-functions-excessive-urlencoding - $url = preg_replace_callback('#%5[bd](?=[^&]*=)#i', function($match) { - return urldecode($match[0]); - }, $url ); - - if (sfConfig::get('sf_logging_enabled')) - { - $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Redirect to "%s"', $url)))); + return [$route, $params]; } - // redirect - /** @var sfWebResponse $response */ - $response = $this->context->getResponse(); - $response->clearHttpHeaders(); - $response->setStatusCode($statusCode); - - // The Location header should only be used for status codes 201 and 3.. - // For other code, only the refresh meta tag is used - if ($statusCode == 201 || ($statusCode >= 300 && $statusCode < 400)) + /** + * Redirects the request to another URL. + * + * @param array|string $url An associative array of URL parameters or an internal URI as a string + * @param int $delay A delay in seconds before redirecting. This is only needed on + * browsers that do not support HTTP headers + * @param int $statusCode The status code + * + * @throws InvalidArgumentException If the url argument is null or an empty string + */ + public function redirect($url, $delay = 0, $statusCode = 302) { - $response->setHttpHeader('Location', $url); + if (empty($url)) { + throw new InvalidArgumentException('Cannot redirect to an empty URL.'); + } + + $url = $this->genUrl($url, true); + // see #8083 + $url = str_replace('&', '&', $url); + // JS Added - make commas unencoded + $url = str_replace('%2C', ',', $url); + // see http://stackoverflow.com/questions/21046623/http-build-query-functions-excessive-urlencoding + $url = preg_replace_callback('#%5[bd](?=[^&]*=)#i', function ($match) { + return urldecode($match[0]); + }, $url); + + if (sfConfig::get('sf_logging_enabled')) { + $this->dispatcher->notify(new sfEvent($this, 'application.log', [sprintf('Redirect to "%s"', $url)])); + } + + // redirect + /** @var sfWebResponse $response */ + $response = $this->context->getResponse(); + $response->clearHttpHeaders(); + $response->setStatusCode($statusCode); + + // The Location header should only be used for status codes 201 and 3.. + // For other code, only the refresh meta tag is used + if (201 == $statusCode || ($statusCode >= 300 && $statusCode < 400)) { + $response->setHttpHeader('Location', $url); + } + + $response->setContent(sprintf('', $delay, htmlspecialchars($url, ENT_QUOTES, sfConfig::get('sf_charset')))); + $response->send(); } - - $response->setContent(sprintf('', $delay, htmlspecialchars($url, ENT_QUOTES, sfConfig::get('sf_charset')))); - $response->send(); - } } diff --git a/lib/database/sfDatabase.class.php b/lib/database/sfDatabase.class.php index 628ba6eff..a380050cd 100644 --- a/lib/database/sfDatabase.class.php +++ b/lib/database/sfDatabase.class.php @@ -13,162 +13,155 @@ * sfDatabase is a base abstraction class that allows you to setup any type of * database connection via a configuration file. * - * @package symfony - * @subpackage database * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ abstract class sfDatabase { - /** @var sfParameterHolder */ - protected $parameterHolder = null; - /** @var resource|PDO */ - protected $connection = null; - /** @var resource|PDO (It's interchangeable with $connection. Can be dropped at all.) */ - protected $resource = null; - - /** - * Class constructor. - * - * @see initialize() - * - * @param array $parameters An associative array of initialization parameters - */ - public function __construct($parameters = array()) - { - $this->initialize($parameters); - } - - /** - * Initializes this sfDatabase object. - * - * @param array $parameters An associative array of initialization parameters - * - * @return void - * - * @throws sfInitializationException If an error occurs while initializing this sfDatabase object - */ - public function initialize($parameters = array()) - { - $this->parameterHolder = new sfParameterHolder(); - $this->parameterHolder->add($parameters); - } - - /** - * Connects to the database. - * - * @throws sfDatabaseException If a connection could not be created - */ - abstract function connect(); - - /** - * Retrieves the database connection associated with this sfDatabase implementation. - * - * When this is executed on a Database implementation that isn't an - * abstraction layer, a copy of the resource will be returned. - * - * @return mixed A database connection - * - * @throws sfDatabaseException If a connection could not be retrieved - */ - public function getConnection() - { - if (null === $this->connection) + /** @var sfParameterHolder */ + protected $parameterHolder; + + /** @var PDO|resource */ + protected $connection; + + /** @var PDO|resource (It's interchangeable with. Can be dropped at all.) */ + protected $resource; + + /** + * Class constructor. + * + * @see initialize() + * + * @param array $parameters An associative array of initialization parameters + */ + public function __construct($parameters = []) + { + $this->initialize($parameters); + } + + /** + * Initializes this sfDatabase object. + * + * @param array $parameters An associative array of initialization parameters + * + * @throws sfInitializationException If an error occurs while initializing this sfDatabase object + */ + public function initialize($parameters = []) + { + $this->parameterHolder = new sfParameterHolder(); + $this->parameterHolder->add($parameters); + } + + /** + * Connects to the database. + * + * @throws sfDatabaseException If a connection could not be created + */ + abstract public function connect(); + + /** + * Retrieves the database connection associated with this sfDatabase implementation. + * + * When this is executed on a Database implementation that isn't an + * abstraction layer, a copy of the resource will be returned. + * + * @return mixed A database connection + * + * @throws sfDatabaseException If a connection could not be retrieved + */ + public function getConnection() + { + if (null === $this->connection) { + $this->connect(); + } + + return $this->connection; + } + + /** + * Retrieves a raw database resource associated with this sfDatabase implementation. + * + * @return mixed A database resource + * + * @throws sfDatabaseException If a resource could not be retrieved + */ + public function getResource() + { + if (null === $this->resource) { + $this->connect(); + } + + return $this->resource; + } + + /** + * Gets the parameter holder for this object. + * + * @return sfParameterHolder A sfParameterHolder instance + */ + public function getParameterHolder() + { + return $this->parameterHolder; + } + + /** + * Gets the parameter associated with the given key. + * + * This is a shortcut for: + * + * $this->getParameterHolder()->get() + * + * @param string $name The key name + * @param string $default The default value + * + * @return string The value associated with the key + * + * @see sfParameterHolder + */ + public function getParameter($name, $default = null) + { + return $this->parameterHolder->get($name, $default); + } + + /** + * Returns true if the given key exists in the parameter holder. + * + * This is a shortcut for: + * + * $this->getParameterHolder()->has() + * + * @param string $name The key name + * + * @return bool true if the given key exists, false otherwise + * + * @see sfParameterHolder + */ + public function hasParameter($name) { - $this->connect(); + return $this->parameterHolder->has($name); } - return $this->connection; - } - - /** - * Retrieves a raw database resource associated with this sfDatabase implementation. - * - * @return mixed A database resource - * - * @throws sfDatabaseException If a resource could not be retrieved - */ - public function getResource() - { - if (null === $this->resource) + /** + * Sets the value for the given key. + * + * This is a shortcut for: + * + * $this->getParameterHolder()->set() + * + * @param string $name The key name + * @param string $value The value + * + * @see sfParameterHolder + */ + public function setParameter($name, $value) { - $this->connect(); + $this->parameterHolder->set($name, $value); } - return $this->resource; - } - - /** - * Gets the parameter holder for this object. - * - * @return sfParameterHolder A sfParameterHolder instance - */ - public function getParameterHolder() - { - return $this->parameterHolder; - } - - /** - * Gets the parameter associated with the given key. - * - * This is a shortcut for: - * - * $this->getParameterHolder()->get() - * - * @param string $name The key name - * @param string $default The default value - * - * @return string The value associated with the key - * - * @see sfParameterHolder - */ - public function getParameter($name, $default = null) - { - return $this->parameterHolder->get($name, $default); - } - - /** - * Returns true if the given key exists in the parameter holder. - * - * This is a shortcut for: - * - * $this->getParameterHolder()->has() - * - * @param string $name The key name - * - * @return boolean true if the given key exists, false otherwise - * - * @see sfParameterHolder - */ - public function hasParameter($name) - { - return $this->parameterHolder->has($name); - } - - /** - * Sets the value for the given key. - * - * This is a shortcut for: - * - * $this->getParameterHolder()->set() - * - * @param string $name The key name - * @param string $value The value - * - * @see sfParameterHolder - */ - public function setParameter($name, $value) - { - $this->parameterHolder->set($name, $value); - } - - /** - * Executes the shutdown procedure. - * - * @return void - * - * @throws sfDatabaseException If an error occurs while shutting down this database - */ - abstract function shutdown(); + /** + * Executes the shutdown procedure. + * + * @throws sfDatabaseException If an error occurs while shutting down this database + */ + abstract public function shutdown(); } diff --git a/lib/database/sfDatabaseManager.class.php b/lib/database/sfDatabaseManager.class.php index ddb377db2..c293005ed 100644 --- a/lib/database/sfDatabaseManager.class.php +++ b/lib/database/sfDatabaseManager.class.php @@ -14,127 +14,112 @@ * request is handled. This eliminates the need for a filter to manage database * connections. * - * @package symfony - * @subpackage database * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ class sfDatabaseManager { - /** @var sfProjectConfiguration */ - protected $configuration = null; - protected $databases = array(); + /** @var sfProjectConfiguration */ + protected $configuration; + protected $databases = []; - /** - * Class constructor. - * - * @see initialize() - * - * @param sfProjectConfiguration $configuration - * @param array $options - */ - public function __construct(sfProjectConfiguration $configuration, $options = array()) - { - $this->initialize($configuration); - - if (!isset($options['auto_shutdown']) || $options['auto_shutdown']) + /** + * Class constructor. + * + * @see initialize() + * + * @param array $options + */ + public function __construct(sfProjectConfiguration $configuration, $options = []) { - register_shutdown_function(array($this, 'shutdown')); + $this->initialize($configuration); + + if (!isset($options['auto_shutdown']) || $options['auto_shutdown']) { + register_shutdown_function([$this, 'shutdown']); + } } - } - /** - * Initializes this sfDatabaseManager object - * - * @param sfProjectConfiguration $configuration A sfProjectConfiguration instance - * - * @return void - * - * @throws sfInitializationException If an error occurs while initializing this sfDatabaseManager object - */ - public function initialize(sfProjectConfiguration $configuration) - { - $this->configuration = $configuration; + /** + * Initializes this sfDatabaseManager object. + * + * @param sfProjectConfiguration $configuration A sfProjectConfiguration instance + * + * @throws sfInitializationException If an error occurs while initializing this sfDatabaseManager object + */ + public function initialize(sfProjectConfiguration $configuration) + { + $this->configuration = $configuration; - $this->loadConfiguration(); - } + $this->loadConfiguration(); + } - /** - * Loads database configuration. - */ - public function loadConfiguration() - { - if ($this->configuration instanceof sfApplicationConfiguration) + /** + * Loads database configuration. + */ + public function loadConfiguration() { - $databases = include($this->configuration->getConfigCache()->checkConfig('config/databases.yml')); + if ($this->configuration instanceof sfApplicationConfiguration) { + $databases = include $this->configuration->getConfigCache()->checkConfig('config/databases.yml'); + } else { + $configHandler = new sfDatabaseConfigHandler(); + $databases = $configHandler->evaluate([$this->configuration->getRootDir().'/config/databases.yml']); + } + + foreach ($databases as $name => $database) { + $this->setDatabase($name, $database); + } } - else + + /** + * Sets a database connection. + * + * @param string $name The database name + * @param sfDatabase $database A sfDatabase instance + */ + public function setDatabase($name, sfDatabase $database) { - $configHandler = new sfDatabaseConfigHandler(); - $databases = $configHandler->evaluate(array($this->configuration->getRootDir().'/config/databases.yml')); + $this->databases[$name] = $database; } - foreach ($databases as $name => $database) + /** + * Retrieves the database connection associated with this sfDatabase implementation. + * + * @param string $name A database name + * + * @return mixed A Database instance + * + * @throws sfDatabaseException If the requested database name does not exist + */ + public function getDatabase($name = 'default') { - $this->setDatabase($name, $database); - } - } + if (isset($this->databases[$name])) { + return $this->databases[$name]; + } - /** - * Sets a database connection. - * - * @param string $name The database name - * @param sfDatabase $database A sfDatabase instance - */ - public function setDatabase($name, sfDatabase $database) - { - $this->databases[$name] = $database; - } + // nonexistent database name + throw new sfDatabaseException(sprintf('Database "%s" does not exist.', $name)); + } - /** - * Retrieves the database connection associated with this sfDatabase implementation. - * - * @param string $name A database name - * - * @return mixed A Database instance - * - * @throws sfDatabaseException If the requested database name does not exist - */ - public function getDatabase($name = 'default') - { - if (isset($this->databases[$name])) + /** + * Returns the names of all database connections. + * + * @return array An array containing all database connection names + */ + public function getNames() { - return $this->databases[$name]; + return array_keys($this->databases); } - // nonexistent database name - throw new sfDatabaseException(sprintf('Database "%s" does not exist.', $name)); - } - - /** - * Returns the names of all database connections. - * - * @return array An array containing all database connection names - */ - public function getNames() - { - return array_keys($this->databases); - } - - /** - * Executes the shutdown procedure - * - * @return void - * - * @throws sfDatabaseException If an error occurs while shutting down this DatabaseManager - */ - public function shutdown() - { - // loop through databases and shutdown connections - foreach ($this->databases as $database) + /** + * Executes the shutdown procedure. + * + * @throws sfDatabaseException If an error occurs while shutting down this DatabaseManager + */ + public function shutdown() { - $database->shutdown(); + // loop through databases and shutdown connections + foreach ($this->databases as $database) { + $database->shutdown(); + } } - } } diff --git a/lib/database/sfMySQLDatabase.class.php b/lib/database/sfMySQLDatabase.class.php new file mode 100644 index 000000000..88d315f12 --- /dev/null +++ b/lib/database/sfMySQLDatabase.class.php @@ -0,0 +1,110 @@ + + * (c) 2004-2006 Sean Kerr + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * sfMySQLDatabase provides connectivity for the MySQL brand database. + * + * Optional parameters: + * + * # database - [none] - The database name. + * # host - [localhost] - The database host. + * # username - [none] - The database username. + * # password - [none] - The database password. + * # persistent - [No] - Indicates that the connection should be persistent. + * + * @author Fabien Potencier + * @author Sean Kerr + */ +class sfMySQLDatabase extends sfDatabase +{ + /** + * Connects to the database. + * + * @throws sfDatabaseException If a connection could not be created + */ + public function connect() + { + $database = $this->getParameter('database'); + $host = $this->getParameter('host', 'localhost'); + $password = $this->getParameter('password'); + $username = $this->getParameter('username'); + $encoding = $this->getParameter('encoding'); + + // let's see if we need a persistent connection + $connect = $this->getConnectMethod($this->getParameter('persistent', false)); + if (null == $password) { + if (null == $username) { + $this->connection = @$connect($host); + } else { + $this->connection = @$connect($host, $username); + } + } else { + $this->connection = @$connect($host, $username, $password); + } + + // make sure the connection went through + if (false === $this->connection) { + // the connection's foobar'd + throw new sfDatabaseException('Failed to create a MySQLDatabase connection.'); + } + + // select our database + if ($this->selectDatabase($database)) { + // can't select the database + throw new sfDatabaseException(sprintf('Failed to select MySQLDatabase "%s".', $database)); + } + + // set encoding if specified + if ($encoding) { + @mysql_query("SET NAMES '".$encoding."'", $this->connection); + } + + // since we're not an abstraction layer, we copy the connection + // to the resource + $this->resource = $this->connection; + } + + /** + * Execute the shutdown procedure. + * + * @throws sfDatabaseException If an error occurs while shutting down this database + */ + public function shutdown() + { + if (null != $this->connection) { + @mysql_close($this->connection); + } + } + + /** + * Returns the appropriate connect method. + * + * @param bool $persistent wether persistent connections are use or not + * + * @return string name of connect method + */ + protected function getConnectMethod($persistent) + { + return $persistent ? 'mysql_pconnect' : 'mysql_connect'; + } + + /** + * Selects the database to be used in this connection. + * + * @param string $database Name of database to be connected + * + * @return bool true if this was successful + */ + protected function selectDatabase($database) + { + return null != $database && !@mysql_select_db($database, $this->connection); + } +} diff --git a/lib/database/sfMySQLiDatabase.class.php b/lib/database/sfMySQLiDatabase.class.php index cb13c1edc..a7c485c39 100644 --- a/lib/database/sfMySQLiDatabase.class.php +++ b/lib/database/sfMySQLiDatabase.class.php @@ -11,61 +11,59 @@ /** * sfMySQLiDatabase provides connectivity for the MySQL brand database. + * * @see sfMySQLDatabase * * @property $connection mysqli */ class sfMySQLiDatabase extends sfMySQLDatabase { + /** + * @throws sfDatabaseException + */ + public function connect() + { + // PHP 8.1 Activate Exception per default, revert behavior to "return false" + mysqli_report(MYSQLI_REPORT_OFF); - /** - * @return void - * @throws sfDatabaseException - */ - public function connect() - { - // PHP 8.1 Activate Exception per default, revert behavior to "return false" - mysqli_report(MYSQLI_REPORT_OFF); - - parent::connect(); - } + parent::connect(); + } - /** - * Returns the appropriate connect method. - * - * @param bool $persistent Whether persistent connections are use or not - * The MySQLi driver does not support persistent - * connections so this argument is ignored. - * - * @return string name of connect method - */ - protected function getConnectMethod($persistent) - { - return 'mysqli_connect'; - } + /** + * Execute the shutdown procedure. + * + * @throws sfDatabaseException If an error occurs while shutting down this database + */ + public function shutdown() + { + if (null != $this->connection) { + @mysqli_close($this->connection); + } + } - /** - * Selects the database to be used in this connection - * - * @param string $database Name of database to be connected - * - * @return bool true if this was successful - */ - protected function selectDatabase($database) - { - return ($database != null && !@mysqli_select_db($this->connection, $database)); - } + /** + * Returns the appropriate connect method. + * + * @param bool $persistent whether persistent connections are use or not + * The MySQLi driver does not support persistent + * connections so this argument is ignored + * + * @return string name of connect method + */ + protected function getConnectMethod($persistent) + { + return 'mysqli_connect'; + } - /** - * Execute the shutdown procedure - * - * @throws sfDatabaseException If an error occurs while shutting down this database - */ - public function shutdown() - { - if ($this->connection != null) + /** + * Selects the database to be used in this connection. + * + * @param string $database Name of database to be connected + * + * @return bool true if this was successful + */ + protected function selectDatabase($database) { - @mysqli_close($this->connection); + return null != $database && !@mysqli_select_db($this->connection, $database); } - } } diff --git a/lib/database/sfPDODatabase.class.php b/lib/database/sfPDODatabase.class.php index 886d19d0c..73c02cbdb 100644 --- a/lib/database/sfPDODatabase.class.php +++ b/lib/database/sfPDODatabase.class.php @@ -12,103 +12,84 @@ /** * sfPDODatabase provides connectivity for the PDO database abstraction layer. * - * @package symfony - * @subpackage database - * @author Daniel Swarbrick (daniel@pressure.net.nz) + * @author Daniel Swarbrick * @author Fabien Potencier * @author Sean Kerr * @author Dustin Whittle - * @version SVN: $Id$ */ class sfPDODatabase extends sfDatabase { - /** - * Connects to the database. - * - * @throws sfDatabaseException If a connection could not be created - */ - public function connect() - { - if (!$dsn = $this->getParameter('dsn')) + /** + * Magic method for calling PDO directly via sfPDODatabase. + * + * @param string $method + * @param array $arguments + */ + public function __call($method, $arguments) { - // missing required dsn parameter - throw new sfDatabaseException('Database configuration is missing the "dsn" parameter.'); + return call_user_func_array([$this->getConnection(), $method], $arguments); } - try + /** + * Connects to the database. + * + * @throws sfDatabaseException If a connection could not be created + */ + public function connect() { - $pdo_class = $this->getParameter('class', 'PDO'); - $username = $this->getParameter('username'); - $password = $this->getParameter('password'); - $persistent = $this->getParameter('persistent'); + if (!$dsn = $this->getParameter('dsn')) { + // missing required dsn parameter + throw new sfDatabaseException('Database configuration is missing the "dsn" parameter.'); + } - $options = $persistent ? array(PDO::ATTR_PERSISTENT => true) : array(); + try { + $pdo_class = $this->getParameter('class', 'PDO'); + $username = $this->getParameter('username'); + $password = $this->getParameter('password'); + $persistent = $this->getParameter('persistent'); - $this->connection = new $pdo_class($dsn, $username, $password, $options); + $options = $persistent ? [PDO::ATTR_PERSISTENT => true] : []; - } - catch (PDOException $e) - { - throw new sfDatabaseException($e->getMessage()); - } - - // lets generate exceptions instead of silent failures - if (sfConfig::get('sf_debug')) - { - $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - } - else - { - $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); - } + $this->connection = new $pdo_class($dsn, $username, $password, $options); + } catch (PDOException $e) { + throw new sfDatabaseException($e->getMessage()); + } - // compatability - $compatability = $this->getParameter('compat'); - if ($compatability) - { - $this->connection->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); - } + // lets generate exceptions instead of silent failures + if (sfConfig::get('sf_debug')) { + $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } else { + $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); + } - // nulls - $nulls = $this->getParameter('nulls'); - if ($nulls) - { - $this->connection->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_EMPTY_STRING); - } + // compatability + $compatability = $this->getParameter('compat'); + if ($compatability) { + $this->connection->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); + } - // auto commit - $autocommit = $this->getParameter('autocommit'); - if ($autocommit) - { - $this->connection->setAttribute(PDO::ATTR_AUTOCOMMIT, true); - } + // nulls + $nulls = $this->getParameter('nulls'); + if ($nulls) { + $this->connection->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_EMPTY_STRING); + } - $this->resource = $this->connection; + // auto commit + $autocommit = $this->getParameter('autocommit'); + if ($autocommit) { + $this->connection->setAttribute(PDO::ATTR_AUTOCOMMIT, true); + } - } + $this->resource = $this->connection; + } - /** - * Execute the shutdown procedure. - * - * @return void - */ - public function shutdown() - { - if ($this->connection !== null) + /** + * Execute the shutdown procedure. + */ + public function shutdown() { - @$this->connection = null; + if (null !== $this->connection) { + @$this->connection = null; + } } - } - - /** - * Magic method for calling PDO directly via sfPDODatabase - * - * @param string $method - * @param array $arguments - * @return mixed - */ - public function __call($method, $arguments) - { - return call_user_func_array(array($this->getConnection(), $method), $arguments); - } } diff --git a/lib/database/sfPostgreSQLDatabase.class.php b/lib/database/sfPostgreSQLDatabase.class.php index 0bbf8abf3..a66bb2a53 100644 --- a/lib/database/sfPostgreSQLDatabase.class.php +++ b/lib/database/sfPostgreSQLDatabase.class.php @@ -21,62 +21,57 @@ * # persistent - [No] - Indicates that the connection should be persistent. * # port - [none] - TCP/IP port on which PostgreSQL is listening. * - * @package symfony - * @subpackage database * @author Fabien Potencier * @author Sean Kerr - * @version SVN: $Id$ */ class sfPostgreSQLDatabase extends sfDatabase { - /** - * Connects to the database. - * - * @throws sfDatabaseException If a connection could not be created - */ - public function connect() - { - $database = $this->getParameter('database'); - $host = $this->getParameter('host'); - $password = $this->getParameter('password'); - $port = $this->getParameter('port'); - $username = $this->getParameter('username'); + /** + * Connects to the database. + * + * @throws sfDatabaseException If a connection could not be created + */ + public function connect() + { + $database = $this->getParameter('database'); + $host = $this->getParameter('host'); + $password = $this->getParameter('password'); + $port = $this->getParameter('port'); + $username = $this->getParameter('username'); - // construct connection string - $string = ($database != null ? (' dbname=' .$database) : ''). - ($host != null ? (' host=' .$host) : ''). - ($password != null ? (' password=' .$password) : ''). - ($port != null ? (' port=' .$port) : ''). - ($username != null ? (' user=' .$username) : ''); + // construct connection string + $string = (null != $database ? (' dbname='.$database) : ''). + (null != $host ? (' host='.$host) : ''). + (null != $password ? (' password='.$password) : ''). + (null != $port ? (' port='.$port) : ''). + (null != $username ? (' user='.$username) : ''); - // let's see if we need a persistent connection - $persistent = $this->getParameter('persistent', false); - $connect = $persistent ? 'pg_pconnect' : 'pg_connect'; + // let's see if we need a persistent connection + $persistent = $this->getParameter('persistent', false); + $connect = $persistent ? 'pg_pconnect' : 'pg_connect'; - $this->connection = @$connect($string); + $this->connection = @$connect($string); - // make sure the connection went through - if ($this->connection === false) - { - // the connection's foobar'd - throw new sfDatabaseException('Failed to create a PostgreSQLDatabase connection.'); - } + // make sure the connection went through + if (false === $this->connection) { + // the connection's foobar'd + throw new sfDatabaseException('Failed to create a PostgreSQLDatabase connection.'); + } - // since we're not an abstraction layer, we copy the connection - // to the resource - $this->resource = $this->connection; - } + // since we're not an abstraction layer, we copy the connection + // to the resource + $this->resource = $this->connection; + } - /** - * Executes the shutdown procedure. - * - * @throws sfDatabaseException If an error occurs while shutting down this database - */ - public function shutdown() - { - if ($this->connection != null) + /** + * Executes the shutdown procedure. + * + * @throws sfDatabaseException If an error occurs while shutting down this database + */ + public function shutdown() { - @pg_close($this->connection); + if (null != $this->connection) { + @pg_close($this->connection); + } } - } } diff --git a/lib/debug/sfDebug.class.php b/lib/debug/sfDebug.class.php index fda40d5c1..e671fe03a 100644 --- a/lib/debug/sfDebug.class.php +++ b/lib/debug/sfDebug.class.php @@ -11,262 +11,240 @@ /** * sfDebug provides some method to help debugging a symfony application. * - * @package symfony - * @subpackage debug * @author Fabien Potencier - * @version SVN: $Id$ */ class sfDebug { - /** - * Returns symfony information as an array. - * - * @return array An array of symfony information - */ - public static function symfonyInfoAsArray() - { - return array( - 'version' => SYMFONY_VERSION, - 'path' => sfConfig::get('sf_symfony_lib_dir'), - ); - } - - /** - * Returns PHP information as an array. - * - * @return array An array of php information - */ - public static function phpInfoAsArray() - { - $values = array( - 'php' => phpversion(), - 'os' => php_uname(), - 'extensions' => get_loaded_extensions(), - ); - - natcasesort($values['extensions']); - - // assign extension version - if ($values['extensions']) + /** + * Returns symfony information as an array. + * + * @return array An array of symfony information + */ + public static function symfonyInfoAsArray() { - foreach($values['extensions'] as $key => $extension) - { - $values['extensions'][$key] = phpversion($extension) ? sprintf('%s (%s)', $extension, phpversion($extension)) : $extension; - } + return [ + 'version' => SYMFONY_VERSION, + 'path' => sfConfig::get('sf_symfony_lib_dir'), + ]; } - return $values; - } - - /** - * Returns PHP globals variables as a sorted array. - * - * @return array PHP globals - */ - public static function globalsAsArray() - { - $values = array(); - foreach (array('cookie', 'server', 'get', 'post', 'files', 'env', 'session') as $name) + /** + * Returns PHP information as an array. + * + * @return array An array of php information + */ + public static function phpInfoAsArray() { - if (!isset($GLOBALS['_'.strtoupper($name)])) - { - continue; - } + $values = [ + 'php' => phpversion(), + 'os' => php_uname(), + 'extensions' => get_loaded_extensions(), + ]; + + natcasesort($values['extensions']); + + // assign extension version + if ($values['extensions']) { + foreach ($values['extensions'] as $key => $extension) { + $values['extensions'][$key] = phpversion($extension) ? sprintf('%s (%s)', $extension, phpversion($extension)) : $extension; + } + } - $values[$name] = array(); - foreach ($GLOBALS['_'.strtoupper($name)] as $key => $value) - { - $values[$name][$key] = $value; - } - ksort($values[$name]); + return $values; } - ksort($values); - - return $values; - } - - /** - * Returns sfConfig variables as a sorted array. - * - * @return array sfConfig variables - */ - public static function settingsAsArray() - { - $config = sfConfig::getAll(); - - ksort($config); + /** + * Returns PHP globals variables as a sorted array. + * + * @return array PHP globals + */ + public static function globalsAsArray() + { + $values = []; + foreach (['cookie', 'server', 'get', 'post', 'files', 'env', 'session'] as $name) { + if (!isset($GLOBALS['_'.strtoupper($name)])) { + continue; + } + + $values[$name] = []; + foreach ($GLOBALS['_'.strtoupper($name)] as $key => $value) { + $values[$name][$key] = $value; + } + ksort($values[$name]); + } - return $config; - } + ksort($values); - /** - * Returns request parameter holders as an array. - * - * @param sfRequest $request A sfRequest instance - * - * @return array The request parameter holders - */ - public static function requestAsArray(sfRequest $request = null) - { - if (!$request) - { - return array(); + return $values; } - return array( - 'options' => $request->getOptions(), - 'parameterHolder' => self::flattenParameterHolder($request->getParameterHolder(), true), - 'attributeHolder' => self::flattenParameterHolder($request->getAttributeHolder(), true), - ); - } - - /** - * Returns response parameters as an array. - * - * @param sfWebResponse $response A sfResponse instance - * - * @return array The response parameters - */ - public static function responseAsArray(sfResponse $response = null) - { - if (!$response) + /** + * Returns sfConfig variables as a sorted array. + * + * @return array sfConfig variables + */ + public static function settingsAsArray() { - return array(); - } + $config = sfConfig::getAll(); - return array( - 'status' => array('code' => $response->getStatusCode(), 'text' => $response->getStatusText()), - 'options' => $response->getOptions(), - 'cookies' => method_exists($response, 'getCookies') ? $response->getCookies() : array(), - 'httpHeaders' => method_exists($response, 'getHttpHeaders') ? $response->getHttpHeaders() : array(), - 'javascripts' => method_exists($response, 'getJavascripts') ? $response->getJavascripts('ALL') : array(), - 'stylesheets' => method_exists($response, 'getStylesheets') ? $response->getStylesheets('ALL') : array(), - 'metas' => method_exists($response, 'getMetas') ? $response->getMetas() : array(), - 'httpMetas' => method_exists($response, 'getHttpMetas') ? $response->getHttpMetas() : array(), - ); - } + ksort($config); - /** - * Returns user parameters as an array. - * - * @param sfUser $user A sfUser instance - * - * @return array The user parameters - */ - public static function userAsArray(sfUser $user = null) - { - if (!$user) - { - return array(); + return $config; } - $data = array( - 'options' => $user->getOptions(), - 'attributeHolder' => self::flattenParameterHolder($user->getAttributeHolder(), true), - 'culture' => $user->getCulture(), - ); - - if ($user instanceof sfBasicSecurityUser) + /** + * Returns request parameter holders as an array. + * + * @param sfRequest $request A sfRequest instance + * + * @return array The request parameter holders + */ + public static function requestAsArray(?sfRequest $request = null) { - $data = array_merge($data, array( - 'authenticated' => $user->isAuthenticated(), - 'credentials' => $user->getCredentials(), - 'lastRequest' => $user->getLastRequestTime(), - )); - } + if (!$request) { + return []; + } - return $data; - } + return [ + 'options' => $request->getOptions(), + 'parameterHolder' => self::flattenParameterHolder($request->getParameterHolder(), true), + 'attributeHolder' => self::flattenParameterHolder($request->getAttributeHolder(), true), + ]; + } - /** - * Returns a parameter holder as an array. - * - * @param sfParameterHolder $parameterHolder A sfParameterHolder instance - * @param boolean $removeObjects when set to true, objects are removed. default is false for BC. - * - * @return array The parameter holder as an array - */ - public static function flattenParameterHolder($parameterHolder, $removeObjects = false) - { - $values = array(); - if ($parameterHolder instanceof sfNamespacedParameterHolder) + /** + * Returns response parameters as an array. + * + * @param sfWebResponse $response A sfResponse instance + * + * @return array The response parameters + */ + public static function responseAsArray(?sfResponse $response = null) { - foreach ($parameterHolder->getNamespaces() as $ns) - { - $values[$ns] = array(); - foreach ($parameterHolder->getAll($ns) as $key => $value) - { - $values[$ns][$key] = $value; + if (!$response) { + return []; } - ksort($values[$ns]); - } + + return [ + 'status' => ['code' => $response->getStatusCode(), 'text' => $response->getStatusText()], + 'options' => $response->getOptions(), + 'cookies' => method_exists($response, 'getCookies') ? $response->getCookies() : [], + 'httpHeaders' => method_exists($response, 'getHttpHeaders') ? $response->getHttpHeaders() : [], + 'javascripts' => method_exists($response, 'getJavascripts') ? $response->getJavascripts('ALL') : [], + 'stylesheets' => method_exists($response, 'getStylesheets') ? $response->getStylesheets('ALL') : [], + 'metas' => method_exists($response, 'getMetas') ? $response->getMetas() : [], + 'httpMetas' => method_exists($response, 'getHttpMetas') ? $response->getHttpMetas() : [], + ]; } - else + + /** + * Returns user parameters as an array. + * + * @param sfUser $user A sfUser instance + * + * @return array The user parameters + */ + public static function userAsArray(?sfUser $user = null) { - foreach ($parameterHolder->getAll() as $key => $value) - { - $values[$key] = $value; - } + if (!$user) { + return []; + } + + $data = [ + 'options' => $user->getOptions(), + 'attributeHolder' => self::flattenParameterHolder($user->getAttributeHolder(), true), + 'culture' => $user->getCulture(), + ]; + + if ($user instanceof sfBasicSecurityUser) { + $data = array_merge($data, [ + 'authenticated' => $user->isAuthenticated(), + 'credentials' => $user->getCredentials(), + 'lastRequest' => $user->getLastRequestTime(), + ]); + } + + return $data; } - if ($removeObjects) + /** + * Returns a parameter holder as an array. + * + * @param sfParameterHolder $parameterHolder A sfParameterHolder instance + * @param bool $removeObjects when set to true, objects are removed. default is false for BC. + * + * @return array The parameter holder as an array + */ + public static function flattenParameterHolder($parameterHolder, $removeObjects = false) { - $values = self::removeObjects($values); - } + $values = []; + if ($parameterHolder instanceof sfNamespacedParameterHolder) { + foreach ($parameterHolder->getNamespaces() as $ns) { + $values[$ns] = []; + foreach ($parameterHolder->getAll($ns) as $key => $value) { + $values[$ns][$key] = $value; + } + ksort($values[$ns]); + } + } else { + foreach ($parameterHolder->getAll() as $key => $value) { + $values[$key] = $value; + } + } - ksort($values); + if ($removeObjects) { + $values = self::removeObjects($values); + } - return $values; - } + ksort($values); - /** - * Removes objects from the array by replacing them with a String containing the class name. - * - * @param array $values an array - * - * @return array The array without objects - */ - public static function removeObjects($values) - { - $nvalues = array(); - foreach ($values as $key => $value) - { - if (is_array($value)) - { - $nvalues[$key] = self::removeObjects($value); - } - else if (is_object($value)) - { - $nvalues[$key] = sprintf('%s Object()', get_class($value)); - } - else - { - $nvalues[$key] = $value; - } + return $values; } - return $nvalues; - } - - /** - * Shortens a file path by replacing symfony directory constants. - * - * @param string $file - * - * @return string - */ - static public function shortenFilePath($file) - { - foreach (array('sf_root_dir', 'sf_symfony_lib_dir') as $key) + /** + * Removes objects from the array by replacing them with a String containing the class name. + * + * @param array $values an array + * + * @return array The array without objects + */ + public static function removeObjects($values) { - if (0 === strpos($file, $value = sfConfig::get($key))) - { - $file = str_replace($value, strtoupper($key), $file); - break; - } + $nvalues = []; + foreach ($values as $key => $value) { + if (is_array($value)) { + $nvalues[$key] = self::removeObjects($value); + } elseif (is_object($value)) { + $nvalues[$key] = sprintf('%s Object()', get_class($value)); + } else { + $nvalues[$key] = $value; + } + } + + return $nvalues; } - return $file; - } + /** + * Shortens a file path by replacing symfony directory constants. + * + * @param string $file + * + * @return string + */ + public static function shortenFilePath($file) + { + if (!$file) { + return $file; + } + + foreach (['sf_root_dir', 'sf_symfony_lib_dir'] as $key) { + if (0 === strpos($file, $value = sfConfig::get($key))) { + $file = str_replace($value, strtoupper($key), $file); + + break; + } + } + + return $file; + } } diff --git a/lib/debug/sfTimer.class.php b/lib/debug/sfTimer.class.php index a08037784..8540366fd 100644 --- a/lib/debug/sfTimer.class.php +++ b/lib/debug/sfTimer.class.php @@ -11,74 +11,69 @@ /** * sfTimer class allows to time some PHP code. * - * @package symfony - * @subpackage util * @author Fabien Potencier - * @version SVN: $Id$ */ class sfTimer { - protected - $startTime = null, - $totalTime = null, - $name = '', - $calls = 0; + protected $startTime; + protected $totalTime; + protected $name = ''; + protected $calls = 0; - /** - * Creates a new sfTimer instance. - * - * @param string $name The name of the timer - */ - public function __construct($name = '') - { - $this->name = $name; - $this->startTimer(); - } - - /** - * Starts the timer. - */ - public function startTimer() - { - $this->startTime = microtime(true); - } + /** + * Creates a new sfTimer instance. + * + * @param string $name The name of the timer + */ + public function __construct($name = '') + { + $this->name = $name; + $this->startTimer(); + } - /** - * Stops the timer and add the amount of time since the start to the total time. - * - * @return float Time spend for the last call - */ - public function addTime() - { - $spend = microtime(true) - $this->startTime; - $this->totalTime += $spend; - ++$this->calls; + /** + * Starts the timer. + */ + public function startTimer() + { + $this->startTime = microtime(true); + } - return $spend; - } + /** + * Stops the timer and add the amount of time since the start to the total time. + * + * @return float Time spend for the last call + */ + public function addTime() + { + $spend = microtime(true) - $this->startTime; + $this->totalTime += $spend; + ++$this->calls; - /** - * Gets the number of calls this timer has been called to time code. - * - * @return integer Number of calls - */ - public function getCalls() - { - return $this->calls; - } + return $spend; + } - /** - * Gets the total time elapsed for all calls of this timer. - * - * @return float Time in seconds - */ - public function getElapsedTime() - { - if (null === $this->totalTime) + /** + * Gets the number of calls this timer has been called to time code. + * + * @return int Number of calls + */ + public function getCalls() { - $this->addTime(); + return $this->calls; } - return $this->totalTime; - } + /** + * Gets the total time elapsed for all calls of this timer. + * + * @return float Time in seconds + */ + public function getElapsedTime() + { + if (null === $this->totalTime) { + $this->addTime(); + } + + return $this->totalTime; + } } diff --git a/lib/debug/sfTimerManager.class.php b/lib/debug/sfTimerManager.class.php index 0f06d09a8..e099797e2 100644 --- a/lib/debug/sfTimerManager.class.php +++ b/lib/debug/sfTimerManager.class.php @@ -11,57 +11,51 @@ /** * sfTimerManager is a container for sfTimer objects. * - * @package symfony - * @subpackage util * @author Fabien Potencier - * @version SVN: $Id$ */ class sfTimerManager { - /** @var sfTimer[] */ - static public $timers = array(); + /** @var sfTimer[] */ + public static $timers = []; - /** - * Gets a sfTimer instance. - * - * It returns the timer named $name or create a new one if it does not exist. - * - * @param string $name The name of the timer - * - * @param bool $reset - * - * @return sfTimer The timer instance - */ - public static function getTimer($name, $reset=true) - { - if (!isset(self::$timers[$name])) + /** + * Gets a sfTimer instance. + * + * It returns the timer named $name or create a new one if it does not exist. + * + * @param string $name The name of the timer + * @param bool $reset + * + * @return sfTimer The timer instance + */ + public static function getTimer($name, $reset = true) { - self::$timers[$name] = new sfTimer($name); + if (!isset(self::$timers[$name])) { + self::$timers[$name] = new sfTimer($name); + } + + if ($reset) { + self::$timers[$name]->startTimer(); + } + + return self::$timers[$name]; } - if ($reset) + /** + * Gets all sfTimer instances stored in sfTimerManager. + * + * @return sfTimer[] An array of all sfTimer instances + */ + public static function getTimers() { - self::$timers[$name]->startTimer(); + return self::$timers; } - return self::$timers[$name]; - } - - /** - * Gets all sfTimer instances stored in sfTimerManager. - * - * @return sfTimer[] An array of all sfTimer instances - */ - public static function getTimers() - { - return self::$timers; - } - - /** - * Clears all sfTimer instances stored in sfTimerManager. - */ - public static function clearTimers() - { - self::$timers = array(); - } + /** + * Clears all sfTimer instances stored in sfTimerManager. + */ + public static function clearTimers() + { + self::$timers = []; + } } diff --git a/lib/debug/sfWebDebug.class.php b/lib/debug/sfWebDebug.class.php index e7b7eea82..3e1d2258b 100644 --- a/lib/debug/sfWebDebug.class.php +++ b/lib/debug/sfWebDebug.class.php @@ -11,222 +11,203 @@ /** * sfWebDebug creates debug information for easy debugging in the browser. * - * @package symfony - * @subpackage debug * @author Fabien Potencier - * @version SVN: $Id$ */ class sfWebDebug { - protected - $dispatcher = null, - $logger = null, - $options = array(), - $panels = array(); - - /** - * Constructor. - * - * Available options: - * - * * image_root_path: The image root path - * * request_parameters: The current request parameters - * - * @param sfEventDispatcher $dispatcher The event dispatcher - * @param sfVarLogger $logger The logger - * @param array $options An array of options - */ - public function __construct(sfEventDispatcher $dispatcher, sfVarLogger $logger, array $options = array()) - { - $this->dispatcher = $dispatcher; - $this->logger = $logger; - $this->options = $options; - - if (!isset($this->options['image_root_path'])) + protected $dispatcher; + protected $logger; + protected $options = []; + protected $panels = []; + + /** + * Constructor. + * + * Available options: + * + * * image_root_path: The image root path + * * request_parameters: The current request parameters + * + * @param sfEventDispatcher $dispatcher The event dispatcher + * @param sfVarLogger $logger The logger + * @param array $options An array of options + */ + public function __construct(sfEventDispatcher $dispatcher, sfVarLogger $logger, array $options = []) { - $this->options['image_root_path'] = ''; - } + $this->dispatcher = $dispatcher; + $this->logger = $logger; + $this->options = $options; - if (!isset($this->options['request_parameters'])) - { - $this->options['request_parameters'] = array(); - } + if (!isset($this->options['image_root_path'])) { + $this->options['image_root_path'] = ''; + } - $this->configure(); + if (!isset($this->options['request_parameters'])) { + $this->options['request_parameters'] = []; + } - $this->dispatcher->notify(new sfEvent($this, 'debug.web.load_panels')); - } + $this->configure(); - /** - * Configures the web debug toolbar. - */ - public function configure() - { - $this->setPanel('symfony_version', new sfWebDebugPanelSymfonyVersion($this)); - if (sfConfig::get('sf_debug') && sfConfig::get('sf_cache')) - { - $this->setPanel('cache', new sfWebDebugPanelCache($this)); + $this->dispatcher->notify(new sfEvent($this, 'debug.web.load_panels')); } - if (sfConfig::get('sf_logging_enabled')) + + /** + * Configures the web debug toolbar. + */ + public function configure() { - $this->setPanel('config', new sfWebDebugPanelConfig($this)); - $this->setPanel('view', new sfWebDebugPanelView($this)); + $this->setPanel('symfony_version', new sfWebDebugPanelSymfonyVersion($this)); + if (sfConfig::get('sf_debug') && sfConfig::get('sf_cache')) { + $this->setPanel('cache', new sfWebDebugPanelCache($this)); + } + if (sfConfig::get('sf_logging_enabled')) { + $this->setPanel('config', new sfWebDebugPanelConfig($this)); + $this->setPanel('view', new sfWebDebugPanelView($this)); + } + $this->setPanel('logs', new sfWebDebugPanelLogs($this)); + $this->setPanel('memory', new sfWebDebugPanelMemory($this)); + if (sfConfig::get('sf_debug')) { + $this->setPanel('time', new sfWebDebugPanelTimer($this)); + } + + $this->setPanel('mailer', new sfWebDebugPanelMailer($this)); } - $this->setPanel('logs', new sfWebDebugPanelLogs($this)); - $this->setPanel('memory', new sfWebDebugPanelMemory($this)); - if (sfConfig::get('sf_debug')) + + /** + * Gets the logger. + * + * @return sfVarLogger The logger instance + */ + public function getLogger() { - $this->setPanel('time', new sfWebDebugPanelTimer($this)); + return $this->logger; } - $this->setPanel('mailer', new sfWebDebugPanelMailer($this)); - } - - /** - * Gets the logger. - * - * @return sfVarLogger The logger instance - */ - public function getLogger() - { - return $this->logger; - } - - /** - * Gets the event dispatcher. - * - * @return sfEventDispatcher The event dispatcher - */ - public function getEventDispatcher() - { - return $this->dispatcher; - } - - /** - * Gets the registered panels. - * - * @return array The panels - */ - public function getPanels() - { - return $this->panels; - } - - /** - * Sets a panel by name. - * - * @param string $name The panel name - * @param sfWebDebugPanel $panel The panel - */ - public function setPanel($name, sfWebDebugPanel $panel) - { - $this->panels[$name] = $panel; - } - - /** - * Removes a panel by name. - * - * @param string $name The panel name - */ - public function removePanel($name) - { - unset($this->panels[$name]); - } - - /** - * Gets an option value by name. - * - * @param string $name The option name - * @param mixed $default - * - * @return mixed The option value - */ - public function getOption($name, $default = null) - { - return isset($this->options[$name]) ? $this->options[$name] : $default; - } - - /** - * Injects the web debug toolbar into a given HTML string. - * - * @param string $content The HTML content - * - * @return string The content with the web debug toolbar injected - */ - public function injectToolbar($content) - { - if (function_exists('mb_stripos')) + /** + * Gets the event dispatcher. + * + * @return sfEventDispatcher The event dispatcher + */ + public function getEventDispatcher() { - $posFunction = 'mb_stripos'; - $posrFunction = 'mb_strripos'; - $substrFunction = 'mb_substr'; + return $this->dispatcher; } - else + + /** + * Gets the registered panels. + * + * @return array The panels + */ + public function getPanels() { - $posFunction = 'stripos'; - $posrFunction = 'strripos'; - $substrFunction = 'substr'; + return $this->panels; } - if (false !== $pos = $posFunction($content, '')) + /** + * Sets a panel by name. + * + * @param string $name The panel name + * @param sfWebDebugPanel $panel The panel + */ + public function setPanel($name, sfWebDebugPanel $panel) { - $styles = ''; - $content = $substrFunction($content, 0, $pos).$styles.$substrFunction($content, $pos); + $this->panels[$name] = $panel; } - $debug = $this->asHtml(); - if (false === $pos = $posrFunction($content, '')) + /** + * Removes a panel by name. + * + * @param string $name The panel name + */ + public function removePanel($name) { - $content .= $debug; + unset($this->panels[$name]); } - else + + /** + * Gets an option value by name. + * + * @param string $name The option name + * @param mixed|null $default + * + * @return mixed The option value + */ + public function getOption($name, $default = null) { - $content = $substrFunction($content, 0, $pos).''.$debug.$substrFunction($content, $pos); + return isset($this->options[$name]) ? $this->options[$name] : $default; } - return $content; - } - - /** - * Returns the web debug toolbar as HTML. - * - * @return string The web debug toolbar HTML - */ - public function asHtml() - { - $current = isset($this->options['request_parameters']['sfWebDebugPanel']) ? $this->options['request_parameters']['sfWebDebugPanel'] : null; - - $titles = array(); - $panels = array(); - foreach ($this->panels as $name => $panel) + /** + * Injects the web debug toolbar into a given HTML string. + * + * @param string $content The HTML content + * + * @return string The content with the web debug toolbar injected + */ + public function injectToolbar($content) { - if ($title = $panel->getTitle()) - { - if (($content = $panel->getPanelContent()) || $panel->getTitleUrl()) - { - $id = sprintf('sfWebDebug%sDetails', $name); - $titles[] = sprintf('%s', - $panel->getStatus() ? ' class="sfWebDebug'.ucfirst($this->getPriority($panel->getStatus())).'"' : '', - $panel->getPanelTitle(), - $panel->getTitleUrl() ?: '#', - $panel->getTitleUrl() ? '' : ' onclick="sfWebDebugShowDetailsFor(\''.$id.'\'); return false;"', - $title - ); - $panels[] = sprintf('

%s

%s
', - $id, - $name == $current ? 'block' : 'none', - $panel->getPanelTitle(), - $content - ); + if (function_exists('mb_stripos')) { + $posFunction = 'mb_stripos'; + $posrFunction = 'mb_strripos'; + $substrFunction = 'mb_substr'; + } else { + $posFunction = 'stripos'; + $posrFunction = 'strripos'; + $substrFunction = 'substr'; + } + + if (false !== $pos = $posFunction($content, '')) { + $styles = ''; + $content = $substrFunction($content, 0, $pos).$styles.$substrFunction($content, $pos); } - else - { - $titles[] = sprintf('
  • %s
  • ', $title); + + $debug = $this->asHtml(); + if (false === $pos = $posrFunction($content, '')) { + $content .= $debug; + } else { + $content = $substrFunction($content, 0, $pos).''.$debug.$substrFunction($content, $pos); } - } + + return $content; } - return ' + /** + * Returns the web debug toolbar as HTML. + * + * @return string The web debug toolbar HTML + */ + public function asHtml() + { + $current = isset($this->options['request_parameters']['sfWebDebugPanel']) ? $this->options['request_parameters']['sfWebDebugPanel'] : null; + + $titles = []; + $panels = []; + foreach ($this->panels as $name => $panel) { + if ($title = $panel->getTitle()) { + if (($content = $panel->getPanelContent()) || $panel->getTitleUrl()) { + $id = sprintf('sfWebDebug%sDetails', $name); + $titles[] = sprintf( + '%s', + $panel->getStatus() ? ' class="sfWebDebug'.ucfirst($this->getPriority($panel->getStatus())).'"' : '', + $panel->getPanelTitle(), + $panel->getTitleUrl() ?: '#', + $panel->getTitleUrl() ? '' : ' onclick="sfWebDebugShowDetailsFor(\''.$id.'\'); return false;"', + $title + ); + $panels[] = sprintf( + '

    %s

    %s
    ', + $id, + $name == $current ? 'block' : 'none', + $panel->getPanelTitle(), + $content + ); + } else { + $titles[] = sprintf('
  • %s
  • ', $title); + } + } + } + + return '
    Debug toolbar @@ -242,39 +223,35 @@ public function asHtml() '.implode("\n", $panels).'
    '; - } - - /** - * Converts a priority value to a string. - * - * @param integer $value The priority value - * - * @return string The priority as a string - */ - public function getPriority($value) - { - if ($value >= sfLogger::INFO) - { - return 'info'; } - else if ($value >= sfLogger::WARNING) - { - return 'warning'; - } - else + + /** + * Converts a priority value to a string. + * + * @param int $value The priority value + * + * @return string The priority as a string + */ + public function getPriority($value) { - return 'error'; + if ($value >= sfLogger::INFO) { + return 'info'; + } + if ($value >= sfLogger::WARNING) { + return 'warning'; + } + + return 'error'; } - } - /** - * Gets the javascript code to inject in the head tag. - * - * @return string The javascript code - */ - public function getJavascript() - { - return << */ EOF; - } + } - /** - * Gets the stylesheet code to inject in the head tag. - * - * @return string The stylesheet code - */ - public function getStylesheet() - { - return << - * @version SVN: $Id$ */ abstract class sfWebDebugPanel { - protected - $webDebug = null, - $status = sfLogger::INFO; - - /** - * Constructor. - * - * @param sfWebDebug $webDebug The web debug toolbar instance - */ - public function __construct(sfWebDebug $webDebug) - { - $this->webDebug = $webDebug; - } - - /** - * Gets the link URL for the link. - * - * @return string The URL link - */ - public function getTitleUrl() - { - } - - /** - * Gets the text for the link. - * - * @return string The link text - */ - abstract public function getTitle(); - - /** - * Gets the title of the panel. - * - * @return string The panel title - */ - abstract public function getPanelTitle(); - - /** - * Gets the panel HTML content. - * - * @return string The panel HTML content - */ - abstract public function getPanelContent(); - - /** - * Returns the current status. - * - * @return integer A {@link sfLogger} priority constant - */ - public function getStatus() - { - return $this->status; - } - - /** - * Sets the current panel's status. - * - * @param integer $status A {@link sfLogger} priority constant - */ - public function setStatus($status) - { - $this->status = $status; - } - - /** - * Returns a toggler element. - * - * @param string $element The value of an element's DOM id attribute - * @param string $title A title attribute - * - * @return string - */ - public function getToggler($element, $title = 'Toggle details') - { - return ''.$title.''; - } - - /** - * Returns a toggleable presentation of a debug stack. - * - * @param array $debugStack - * - * @return string - */ - public function getToggleableDebugStack($debugStack) - { - static $i = 1; - - if (!$debugStack) + protected $webDebug; + protected $status = sfLogger::INFO; + + /** + * Constructor. + * + * @param sfWebDebug $webDebug The web debug toolbar instance + */ + public function __construct(sfWebDebug $webDebug) { - return ''; + $this->webDebug = $webDebug; } - $element = get_class($this).'Debug'.$i++; - $keys = array_reverse(array_keys($debugStack)); - - $html = $this->getToggler($element, 'Toggle debug stack'); - $html .= '\n"; - - return $html; - } - - /** - * Formats a file link. - * - * @param string $file A file path or class name - * @param integer $line - * @param string $text Text to use for the link - * - * @return string - */ - public function formatFileLink($file, $line = null, $text = null) - { - // this method is called a lot so we avoid calling class_exists() - if ($file && !sfToolkit::isPathAbsolute($file)) + + /** + * Sets the current panel's status. + * + * @param int $status A {@link sfLogger} priority constant + */ + public function setStatus($status) { - if (null === $text) - { - $text = $file; - } - - // translate class to file name - $r = new ReflectionClass($file); - $file = $r->getFileName(); + $this->status = $status; } - $shortFile = sfDebug::shortenFilePath($file); + /** + * Returns a toggler element. + * + * @param string $element The value of an element's DOM id attribute + * @param string $title A title attribute + * + * @return string + */ + public function getToggler($element, $title = 'Toggle details') + { + return ''.$title.''; + } - if ($linkFormat = sfConfig::get('sf_file_link_format', ini_get('xdebug.file_link_format'))) + /** + * Returns a toggleable presentation of a debug stack. + * + * @param array $debugStack + * + * @return string + */ + public function getToggleableDebugStack($debugStack) { - // return a link - return sprintf( - '%s', - htmlspecialchars(strtr($linkFormat, array('%f' => $file, '%l' => $line)), ENT_QUOTES, sfConfig::get('sf_charset')), - htmlspecialchars($shortFile, ENT_QUOTES, sfConfig::get('sf_charset')), - null === $text ? $shortFile : $text); + static $i = 1; + + if (!$debugStack) { + return ''; + } + + $element = get_class($this).'Debug'.$i++; + $keys = array_reverse(array_keys($debugStack)); + + $html = $this->getToggler($element, 'Toggle debug stack'); + $html .= '\n"; + + return $html; } - else if (null === $text) + + /** + * Formats a file link. + * + * @param string $file A file path or class name + * @param int $line + * @param string $text Text to use for the link + * + * @return string + */ + public function formatFileLink($file, $line = null, $text = null) { - // return the shortened file path - return $shortFile; + // this method is called a lot so we avoid calling class_exists() + if ($file && !sfToolkit::isPathAbsolute($file)) { + if (null === $text) { + $text = $file; + } + + // translate class to file name + $r = new ReflectionClass($file); + $file = $r->getFileName(); + } + + $shortFile = sfDebug::shortenFilePath($file); + + if ($linkFormat = sfConfig::get('sf_file_link_format', ini_get('xdebug.file_link_format'))) { + // return a link + return sprintf( + '%s', + htmlspecialchars(strtr($linkFormat, ['%f' => $file, '%l' => $line]), ENT_QUOTES, sfConfig::get('sf_charset')), + htmlspecialchars($shortFile, ENT_QUOTES, sfConfig::get('sf_charset')), + null === $text ? $shortFile : $text + ); + } + if (null === $text) { + // return the shortened file path + return $shortFile; + } + + // return the provided text with the shortened file path as a tooltip + return sprintf('%s', $shortFile, $text); } - else + + /** + * Format a SQL string with some colors on SQL keywords to make it more readable. + * + * @param string $sql SQL string to format + * + * @return string $newSql The new formatted SQL string + */ + public function formatSql($sql) { - // return the provided text with the shortened file path as a tooltip - return sprintf('%s', $shortFile, $text); + return preg_replace('/\b(UPDATE|SET|SELECT|FROM|AS|LIMIT|ASC|COUNT|DESC|WHERE|LEFT JOIN|INNER JOIN|RIGHT JOIN|ORDER BY|GROUP BY|IN|LIKE|DISTINCT|DELETE|INSERT|INTO|VALUES)\b/', '\\1', $sql); } - } - - /** - * Format a SQL string with some colors on SQL keywords to make it more readable. - * - * @param string $sql SQL string to format - * - * @return string $newSql The new formatted SQL string - */ - public function formatSql($sql) - { - return preg_replace('/\b(UPDATE|SET|SELECT|FROM|AS|LIMIT|ASC|COUNT|DESC|WHERE|LEFT JOIN|INNER JOIN|RIGHT JOIN|ORDER BY|GROUP BY|IN|LIKE|DISTINCT|DELETE|INSERT|INTO|VALUES)\b/', '\\1', $sql); - } } diff --git a/lib/debug/sfWebDebugPanelCache.class.php b/lib/debug/sfWebDebugPanelCache.class.php index dce7f206d..142067a74 100644 --- a/lib/debug/sfWebDebugPanelCache.class.php +++ b/lib/debug/sfWebDebugPanelCache.class.php @@ -12,38 +12,32 @@ * sfWebDebugPanelCache adds a panel to the web debug toolbar with a link to ignore the cache * on the next request. * - * @package symfony - * @subpackage debug * @author Fabien Potencier - * @version SVN: $Id$ */ class sfWebDebugPanelCache extends sfWebDebugPanel { - public function getTitle() - { - return 'Reload'; - } - - public function getTitleUrl() - { - $queryString = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY); - - if (false === strpos($queryString, '_sf_ignore_cache')) + public function getTitle() { - return sprintf('?%s_sf_ignore_cache=1', $queryString ? $queryString.'&' : ''); + return 'Reload'; } - else + + public function getTitleUrl() { - return '?'.$queryString; + $queryString = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY); + + if (false === strpos($queryString, '_sf_ignore_cache')) { + return sprintf('?%s_sf_ignore_cache=1', $queryString ? $queryString.'&' : ''); + } + + return '?'.$queryString; } - } - public function getPanelTitle() - { - return 'reload and ignore cache'; - } + public function getPanelTitle() + { + return 'reload and ignore cache'; + } - public function getPanelContent() - { - } + public function getPanelContent() + { + } } diff --git a/lib/debug/sfWebDebugPanelConfig.class.php b/lib/debug/sfWebDebugPanelConfig.class.php index 5e212203b..107281de1 100644 --- a/lib/debug/sfWebDebugPanelConfig.class.php +++ b/lib/debug/sfWebDebugPanelConfig.class.php @@ -11,71 +11,65 @@ /** * sfWebDebugPanelConfig adds a panel to the web debug toolbar with the current configuration. * - * @package symfony - * @subpackage debug * @author Fabien Potencier - * @version SVN: $Id$ */ class sfWebDebugPanelConfig extends sfWebDebugPanel { - public function getTitle() - { - return 'Config config'; - } - - public function getPanelTitle() - { - return 'Configuration'; - } - - public function getPanelContent() - { - $config = array( - 'debug' => sfConfig::get('sf_debug') ? 'on' : 'off', - 'xdebug' => extension_loaded('xdebug') ? 'on' : 'off', - 'logging' => sfConfig::get('sf_logging_enabled') ? 'on' : 'off', - 'cache' => sfConfig::get('sf_cache') ? 'on' : 'off', - 'compression' => sfConfig::get('sf_compressed') ? 'on' : 'off', - 'tokenizer' => function_exists('token_get_all') ? 'on' : 'off', - 'eaccelerator' => extension_loaded('eaccelerator') && ini_get('eaccelerator.enable') ? 'on' : 'off', - 'apc' => extension_loaded('apc') && ini_get('apc.enabled') ? 'on' : 'off', - 'xcache' => extension_loaded('xcache') && ini_get('xcache.cacher') ? 'on' : 'off', - ); + public function getTitle() + { + return 'Config config'; + } - $html = '
      '; - foreach ($config as $key => $value) + public function getPanelTitle() { - $html .= '
    • '.$key.'
    • '; + return 'Configuration'; } - $html .= '
    '; - $context = sfContext::getInstance(); - $html .= $this->formatArrayAsHtml('request', sfDebug::requestAsArray($context->getRequest())); - $html .= $this->formatArrayAsHtml('response', sfDebug::responseAsArray($context->getResponse())); - $html .= $this->formatArrayAsHtml('user', sfDebug::userAsArray($context->getUser())); - $html .= $this->formatArrayAsHtml('settings', sfDebug::settingsAsArray()); - $html .= $this->formatArrayAsHtml('globals', sfDebug::globalsAsArray()); - $html .= $this->formatArrayAsHtml('php', sfDebug::phpInfoAsArray()); - $html .= $this->formatArrayAsHtml('symfony', sfDebug::symfonyInfoAsArray()); + public function getPanelContent() + { + $config = [ + 'debug' => sfConfig::get('sf_debug') ? 'on' : 'off', + 'xdebug' => extension_loaded('xdebug') ? 'on' : 'off', + 'logging' => sfConfig::get('sf_logging_enabled') ? 'on' : 'off', + 'cache' => sfConfig::get('sf_cache') ? 'on' : 'off', + 'compression' => sfConfig::get('sf_compressed') ? 'on' : 'off', + 'tokenizer' => function_exists('token_get_all') ? 'on' : 'off', + 'apc' => extension_loaded('apc') && ini_get('apc.enabled') ? 'on' : 'off', + ]; + + $html = '
      '; + foreach ($config as $key => $value) { + $html .= '
    • '.$key.'
    • '; + } + $html .= '
    '; - return $html; - } + $context = sfContext::getInstance(); + $html .= $this->formatArrayAsHtml('request', sfDebug::requestAsArray($context->getRequest())); + $html .= $this->formatArrayAsHtml('response', sfDebug::responseAsArray($context->getResponse())); + $html .= $this->formatArrayAsHtml('user', sfDebug::userAsArray($context->getUser())); + $html .= $this->formatArrayAsHtml('settings', sfDebug::settingsAsArray()); + $html .= $this->formatArrayAsHtml('globals', sfDebug::globalsAsArray()); + $html .= $this->formatArrayAsHtml('php', sfDebug::phpInfoAsArray()); + $html .= $this->formatArrayAsHtml('symfony', sfDebug::symfonyInfoAsArray()); - /** - * Converts an array to HTML. - * - * @param string $id The identifier to use - * @param array $values The array of values - * - * @return string An HTML string - */ - protected function formatArrayAsHtml($id, $values) - { - $id = ucfirst(strtolower($id)); + return $html; + } - return ' + /** + * Converts an array to HTML. + * + * @param string $id The identifier to use + * @param array $values The array of values + * + * @return string An HTML string + */ + protected function formatArrayAsHtml($id, $values) + { + $id = ucfirst(strtolower($id)); + + return '

    '.$id.' '.$this->getToggler('sfWebDebug'.$id).'

    '; - } + } } diff --git a/lib/debug/sfWebDebugPanelLogs.class.php b/lib/debug/sfWebDebugPanelLogs.class.php index 126ba6468..e80a05791 100644 --- a/lib/debug/sfWebDebugPanelLogs.class.php +++ b/lib/debug/sfWebDebugPanelLogs.class.php @@ -11,87 +11,82 @@ /** * sfWebDebugPanelLogs adds a panel to the web debug toolbar with log messages. * - * @package symfony - * @subpackage debug * @author Fabien Potencier - * @version SVN: $Id$ */ class sfWebDebugPanelLogs extends sfWebDebugPanel { - public function getTitle() - { - return 'Log logs'; - } - - public function getPanelTitle() - { - return 'Logs'; - } - - public function getPanelContent() - { - $event = $this->webDebug->getEventDispatcher()->filter(new sfEvent($this, 'debug.web.filter_logs'), $this->webDebug->getLogger()->getLogs()); - $logs = $event->getReturnValue(); - - $html = ' - - - - - - '."\n"; - $line_nb = 0; - $numlogs = count($logs); - for ($i = 0; $i < $numlogs; $i++) + public function getTitle() { - $log = $logs[$i]; - - if ($i < $numlogs - 1) { - $time = $logs[$i + 1]['time'] - $log['time']; - } else { - $time = microtime(true) - $log['time']; - } - if ($time > 2) { - $colour = '#FF5555'; - } elseif ($time > 1) { - $colour = 'orange'; - } elseif ($time > 0.3) { - $colour = 'yellow'; - } else { - $colour = '#AAFFAA'; - } - $time = number_format($time, 3); - - $priority = $this->webDebug->getPriority($log['priority']); - - // increase status - if ($log['priority'] < $this->getStatus()) - { - $this->setStatus($log['priority']); - } - - ++$line_nb; - $html .= sprintf("\n", - ucfirst($priority), - $log['type'], - $line_nb, - $colour, - $time, - ''.ucfirst($priority).'', - class_exists($log['type'], false) ? $this->formatFileLink($log['type']) : $log['type'], - $this->formatLogLine($log['message']), - $this->getToggleableDebugStack($log['debug_backtrace']) - ); + return 'Log logs'; } - $html .= '
    #time (s)typemessage
    %s%s%s %s%s %s
    '; - $types = array(); - foreach ($this->webDebug->getLogger()->getTypes() as $type) + public function getPanelTitle() { - $types[] = ''.$type.''; + return 'Logs'; } - return ' + public function getPanelContent() + { + $event = $this->webDebug->getEventDispatcher()->filter(new sfEvent($this, 'debug.web.filter_logs'), $this->webDebug->getLogger()->getLogs()); + $logs = $event->getReturnValue(); + + $html = ' + + + + + + '."\n"; + $line_nb = 0; + $numlogs = count($logs); + for ($i = 0; $i < $numlogs; ++$i) { + $log = $logs[$i]; + + if ($i < $numlogs - 1) { + $time = $logs[$i + 1]['time'] - $log['time']; + } else { + $time = microtime(true) - $log['time']; + } + if ($time > 2) { + $colour = '#FF5555'; + } elseif ($time > 1) { + $colour = 'orange'; + } elseif ($time > 0.3) { + $colour = 'yellow'; + } else { + $colour = '#AAFFAA'; + } + $time = number_format($time, 3); + + $priority = $this->webDebug->getPriority($log['priority']); + + // increase status + if ($log['priority'] < $this->getStatus()) { + $this->setStatus($log['priority']); + } + + ++$line_nb; + $html .= sprintf( + "\n", + ucfirst($priority), + $log['type'], + $line_nb, + $colour, + $time, + ''.ucfirst($priority).'', + class_exists($log['type'], false) ? $this->formatFileLink($log['type']) : $log['type'], + $this->formatLogLine($log['message']), + $this->getToggleableDebugStack($log['debug_backtrace']) + ); + } + $html .= '
    #time (s)typemessage
    %s%s%s %s%s %s
    '; + + $types = []; + foreach ($this->webDebug->getLogger()->getTypes() as $type) { + $types[] = ''.$type.''; + } + + return '
    • [all]
    • [none]
    • @@ -102,45 +97,42 @@ class_exists($log['type'], false) ? $this->formatFileLink($log['type']) : $log['
    '.$html.'
    '; - } - - /** - * Formats a log line. - * - * @param string $logLine The log line to format - * - * @return string The formatted log lin - */ - protected function formatLogLine($logLine) - { - static $constants; - - if (!$constants) - { - foreach (array('sf_app_dir', 'sf_root_dir', 'sf_symfony_lib_dir') as $constant) - { - $constants[realpath(sfConfig::get($constant)).DIRECTORY_SEPARATOR] = $constant.DIRECTORY_SEPARATOR; - } } - // escape HTML - $logLine = htmlspecialchars($logLine, ENT_QUOTES, sfConfig::get('sf_charset')); + /** + * Formats a log line. + * + * @param string $logLine The log line to format + * + * @return string The formatted log lin + */ + protected function formatLogLine($logLine) + { + static $constants; + + if (!$constants) { + foreach (['sf_app_dir', 'sf_root_dir', 'sf_symfony_lib_dir'] as $constant) { + $constants[realpath(sfConfig::get($constant)).DIRECTORY_SEPARATOR] = $constant.DIRECTORY_SEPARATOR; + } + } - // replace constants value with constant name - $logLine = str_replace(array_keys($constants), array_values($constants), $logLine); - $logLine = preg_replace('/"(.+?)"/s', "\\1", $logLine); - $logLine = preg_replace('/^(.+?)\(\)\:/S', "\\1():", $logLine); - $logLine = preg_replace('/line (\d+)$/', "line \\1", $logLine); + // escape HTML + $logLine = htmlspecialchars($logLine, ENT_QUOTES, sfConfig::get('sf_charset')); - // special formatting for SQL lines - $logLine = $this->formatSql($logLine); + // replace constants value with constant name + $logLine = str_replace(array_keys($constants), array_values($constants), $logLine); + $logLine = preg_replace('/"(.+?)"/s', '\\1', $logLine); + $logLine = preg_replace('/^(.+?)\(\)\:/S', '\\1():', $logLine); + $logLine = preg_replace('/line (\d+)$/', 'line \\1', $logLine); - // remove username/password from DSN - if (strpos($logLine, 'DSN') !== false) - { - $logLine = preg_replace("/=>\s+'?[^'\s,]+'?/", "=> '****'", $logLine); - } + // special formatting for SQL lines + $logLine = $this->formatSql($logLine); - return $logLine; - } + // remove username/password from DSN + if (false !== strpos($logLine, 'DSN')) { + $logLine = preg_replace("/=>\\s+'?[^'\\s,]+'?/", "=> '****'", $logLine); + } + + return $logLine; + } } diff --git a/lib/debug/sfWebDebugPanelMailer.class.php b/lib/debug/sfWebDebugPanelMailer.class.php index 6b4ce3e7f..d1a7002f9 100644 --- a/lib/debug/sfWebDebugPanelMailer.class.php +++ b/lib/debug/sfWebDebugPanelMailer.class.php @@ -11,96 +11,87 @@ /** * sfWebDebugPanelMailer adds a panel to the web debug toolbar with sent emails. * - * @package symfony - * @subpackage debug * @author Fabien Potencier - * @version SVN: $Id$ */ class sfWebDebugPanelMailer extends sfWebDebugPanel { - /** @var sfMailer */ - protected $mailer = null; - - /** - * Constructor. - * - * @param sfWebDebug $webDebug The web debug toolbar instance - */ - public function __construct(sfWebDebug $webDebug) - { - parent::__construct($webDebug); - - $this->webDebug->getEventDispatcher()->connect('mailer.configure', array($this, 'listenForMailerConfigure')); - } - - public function getTitle() - { - if ($this->mailer && ($logger = $this->mailer->getLogger()) && $logger->countMessages()) + /** @var sfMailer */ + protected $mailer; + + /** + * Constructor. + * + * @param sfWebDebug $webDebug The web debug toolbar instance + */ + public function __construct(sfWebDebug $webDebug) { - return 'Emailer '.$logger->countMessages(); - } - } + parent::__construct($webDebug); - public function getPanelTitle() - { - return 'Emails'; - } + $this->webDebug->getEventDispatcher()->connect('mailer.configure', [$this, 'listenForMailerConfigure']); + } - public function getPanelContent() - { - $logger = $this->mailer->getLogger(); + public function getTitle() + { + if ($this->mailer && ($logger = $this->mailer->getLogger()) && $logger->countMessages()) { + return 'Emailer '.$logger->countMessages(); + } + } - if (!$logger || !$messages = $logger->getMessages()) + public function getPanelTitle() { - return false; + return 'Emails'; } - $html = array(); + public function getPanelContent() + { + $logger = $this->mailer->getLogger(); - // configuration information - $strategy = $this->mailer->getDeliveryStrategy(); - $html[] = '

    Configuration

    '; - $html[] = 'Delivery strategy: '.$strategy; + if (!$logger || !$messages = $logger->getMessages()) { + return false; + } - if (sfMailer::SINGLE_ADDRESS == $strategy) - { - $html[] = ' - all emails are delivered to: '.$this->mailer->getDeliveryAddress(); + $html = []; + + // configuration information + $strategy = $this->mailer->getDeliveryStrategy(); + $html[] = '

    Configuration

    '; + $html[] = 'Delivery strategy: '.$strategy; + + if (sfMailer::SINGLE_ADDRESS == $strategy) { + $html[] = ' - all emails are delivered to: '.$this->mailer->getDeliveryAddress(); + } + + // email sent + $html[] = '

    Email sent

    '; + foreach ($messages as $message) { + $html[] = $this->renderMessageInformation($message); + } + + return implode("\n", $html); } - // email sent - $html[] = '

    Email sent

    '; - foreach ($messages as $message) + /** + * Listens for the mailer.configure event and captures a reference to the mailer. + */ + public function listenForMailerConfigure(sfEvent $event) { - $html[] = $this->renderMessageInformation($message); + $this->mailer = $event->getSubject(); } - return implode("\n", $html); - } - - protected function renderMessageInformation(Swift_Message $message) - { - static $i = 0; - - $i++; + protected function renderMessageInformation(Swift_Message $message) + { + static $i = 0; - $to = null === $message->getTo() ? '' : implode(', ', array_keys($message->getTo())); + ++$i; - $html = array(); - $html[] = sprintf('

    %s (to: %s) %s

    ', $message->getSubject(), $to, $this->getToggler('sfWebDebugMailTemplate'.$i)); - $html[] = '
    '; - $html[] = '
    '.htmlentities($message->toString(), ENT_QUOTES, $message->getCharset()).'
    '; - $html[] = '
    '; + $to = null === $message->getTo() ? '' : implode(', ', array_keys($message->getTo())); - return implode("\n", $html); - } + $html = []; + $html[] = sprintf('

    %s (to: %s) %s

    ', $message->getSubject(), $to, $this->getToggler('sfWebDebugMailTemplate'.$i)); + $html[] = '
    '; + $html[] = '
    '.htmlentities($message->toString(), ENT_QUOTES, $message->getCharset()).'
    '; + $html[] = '
    '; - /** - * Listens for the mailer.configure event and captures a reference to the mailer. - * - * @param sfEvent $event - */ - public function listenForMailerConfigure(sfEvent $event) - { - $this->mailer = $event->getSubject(); - } + return implode("\n", $html); + } } diff --git a/lib/debug/sfWebDebugPanelMemory.class.php b/lib/debug/sfWebDebugPanelMemory.class.php index 2a37073ab..4fcf1d5c3 100644 --- a/lib/debug/sfWebDebugPanelMemory.class.php +++ b/lib/debug/sfWebDebugPanelMemory.class.php @@ -11,25 +11,22 @@ /** * sfWebDebugPanelMemory adds a panel to the web debug toolbar with the memory used by the script. * - * @package symfony - * @subpackage debug * @author Fabien Potencier - * @version SVN: $Id$ */ class sfWebDebugPanelMemory extends sfWebDebugPanel { - public function getTitle() - { - $totalMemory = sprintf('%.1f', memory_get_peak_usage(true) / 1024); + public function getTitle() + { + $totalMemory = sprintf('%.1f', memory_get_peak_usage(true) / 1024); - return 'Memory '.$totalMemory.' KB'; - } + return 'Memory '.$totalMemory.' KB'; + } - public function getPanelTitle() - { - } + public function getPanelTitle() + { + } - public function getPanelContent() - { - } + public function getPanelContent() + { + } } diff --git a/lib/debug/sfWebDebugPanelSymfonyVersion.class.php b/lib/debug/sfWebDebugPanelSymfonyVersion.class.php index 02b9ad1d5..872453c52 100644 --- a/lib/debug/sfWebDebugPanelSymfonyVersion.class.php +++ b/lib/debug/sfWebDebugPanelSymfonyVersion.class.php @@ -11,23 +11,20 @@ /** * sfWebDebugPanelSymfonyVersion adds a panel to the web debug toolbar with the symfony version. * - * @package symfony - * @subpackage debug * @author Fabien Potencier - * @version SVN: $Id$ */ class sfWebDebugPanelSymfonyVersion extends sfWebDebugPanel { - public function getTitle() - { - return ''.SYMFONY_VERSION.''; - } + public function getTitle() + { + return ''.SYMFONY_VERSION.''; + } - public function getPanelTitle() - { - } + public function getPanelTitle() + { + } - public function getPanelContent() - { - } + public function getPanelContent() + { + } } diff --git a/lib/debug/sfWebDebugPanelTimer.class.php b/lib/debug/sfWebDebugPanelTimer.class.php index e9e039a59..3eb90d6c8 100644 --- a/lib/debug/sfWebDebugPanelTimer.class.php +++ b/lib/debug/sfWebDebugPanelTimer.class.php @@ -11,80 +11,72 @@ /** * sfWebDebugPanelTimer adds a panel to the web debug toolbar with timer information. * - * @package symfony - * @subpackage debug * @author Fabien Potencier - * @version SVN: $Id$ */ class sfWebDebugPanelTimer extends sfWebDebugPanel { - static protected - $startTime = null; + protected static $startTime; - /** - * Constructor. - * - * @param sfWebDebug $webDebug The web debug toolbar instance - */ - public function __construct(sfWebDebug $webDebug) - { - parent::__construct($webDebug); + /** + * Constructor. + * + * @param sfWebDebug $webDebug The web debug toolbar instance + */ + public function __construct(sfWebDebug $webDebug) + { + parent::__construct($webDebug); - $this->webDebug->getEventDispatcher()->connect('debug.web.filter_logs', array($this, 'filterLogs')); - } + $this->webDebug->getEventDispatcher()->connect('debug.web.filter_logs', [$this, 'filterLogs']); + } - public function getTitle() - { - return 'Time '.$this->getTotalTime().' ms'; - } + public function getTitle() + { + return 'Time '.$this->getTotalTime().' ms'; + } - public function getPanelTitle() - { - return 'Timers'; - } + public function getPanelTitle() + { + return 'Timers'; + } - public function getPanelContent() - { - if (sfTimerManager::getTimers()) + public function getPanelContent() { - $totalTime = $this->getTotalTime(); - $panel = ''; - foreach (sfTimerManager::getTimers() as $name => $timer) - { - $panel .= sprintf('', $name, $timer->getCalls(), $timer->getElapsedTime() * 1000, $totalTime ? ($timer->getElapsedTime() * 1000 * 100 / $totalTime) : 'N/A'); - } - $panel .= '
    typecallstime (ms)time (%)
    %s%d%.2f%d
    '; + if (sfTimerManager::getTimers()) { + $totalTime = $this->getTotalTime(); + $panel = ''; + foreach (sfTimerManager::getTimers() as $name => $timer) { + $panel .= sprintf('', $name, $timer->getCalls(), $timer->getElapsedTime() * 1000, $totalTime ? ($timer->getElapsedTime() * 1000 * 100 / $totalTime) : 'N/A'); + } + $panel .= '
    typecallstime (ms)time (%)
    %s%d%.2f%d
    '; - return $panel; + return $panel; + } } - } - public function filterLogs(sfEvent $event, $logs) - { - $newLogs = array(); - foreach ($logs as $log) + public function filterLogs(sfEvent $event, $logs) { - if ('sfWebDebugLogger' != $log['type']) - { - $newLogs[] = $log; - } - } + $newLogs = []; + foreach ($logs as $log) { + if ('sfWebDebugLogger' != $log['type']) { + $newLogs[] = $log; + } + } - return $newLogs; - } + return $newLogs; + } - static public function startTime() - { - self::$startTime = microtime(true); - } + public static function startTime() + { + self::$startTime = microtime(true); + } - static public function isStarted() - { - return null !== self::$startTime; - } + public static function isStarted() + { + return null !== self::$startTime; + } - protected function getTotalTime() - { - return null !== self::$startTime ? sprintf('%.0f', (microtime(true) - self::$startTime) * 1000) : 0; - } + protected function getTotalTime() + { + return null !== self::$startTime ? sprintf('%.0f', (microtime(true) - self::$startTime) * 1000) : 0; + } } diff --git a/lib/debug/sfWebDebugPanelView.class.php b/lib/debug/sfWebDebugPanelView.class.php index bab2b3712..96af9c19f 100644 --- a/lib/debug/sfWebDebugPanelView.class.php +++ b/lib/debug/sfWebDebugPanelView.class.php @@ -11,356 +11,319 @@ /** * sfWebDebugPanelView adds a panel to the web debug toolbar with information about the view layer. * - * @package symfony - * @subpackage debug * @author Kris Wallsmith + * * @version SVN: $Id$ */ class sfWebDebugPanelView extends sfWebDebugPanel { - protected - $actions = array(), - $partials = array(); - - /** - * Constructor. - * - * @param sfWebDebug $webDebug The web debug toolbar instance - */ - public function __construct(sfWebDebug $webDebug) - { - parent::__construct($webDebug); - - $this->webDebug->getEventDispatcher()->connect('controller.change_action', array($this, 'listenForChangeAction')); - $this->webDebug->getEventDispatcher()->connect('template.filter_parameters', array($this, 'filterTemplateParameters')); - } - - /** - * Resets the parameter collections. - * - * @param sfEvent $event - */ - public function listenForChangeAction(sfEvent $event) - { - $this->actions = array(); - $this->partials = array(); - } - - /** - * Stacks action and partial parameters in the template.filter_parameters event. - * - * @param sfEvent $event - * @param array $parameters - * - * @return array - */ - public function filterTemplateParameters(sfEvent $event, $parameters) - { - $entry = array('parameters' => $parameters); - - if ('action' == $parameters['sf_type'] && $file = $this->getLastTemplate()) - { - $this->actions[] = $entry + array('file' => $file); - } - else if ('partial' == $parameters['sf_type'] && $file = $this->getLastTemplate('sfPartialView')) + protected $actions = []; + protected $partials = []; + + /** + * Constructor. + * + * @param sfWebDebug $webDebug The web debug toolbar instance + */ + public function __construct(sfWebDebug $webDebug) { - $this->partials[] = $entry + array('file' => $file); + parent::__construct($webDebug); + + $this->webDebug->getEventDispatcher()->connect('controller.change_action', [$this, 'listenForChangeAction']); + $this->webDebug->getEventDispatcher()->connect('template.filter_parameters', [$this, 'filterTemplateParameters']); } - return $parameters; - } - - /** - * Returns the path to the last template rendered. - * - * @param string $class Name of the rendering view class - * - * @return string|null - */ - protected function getLastTemplate($class = 'sfPHPView') - { - foreach (array_reverse($this->webDebug->getLogger()->getLogs()) as $log) + /** + * Resets the parameter collections. + */ + public function listenForChangeAction(sfEvent $event) { - if ( - ($class == $log['type'] || (class_exists($log['type'], false) && is_subclass_of($log['type'], $class))) - && - preg_match('/^Render "(.*)"$/', $log['message'], $match) - ) - { - return $match[1]; - } + $this->actions = []; + $this->partials = []; } - } - - /** - * @see sfWebDebugPanel - */ - public function getTitle() - { - if (count($this->actions) || count($this->partials)) + + /** + * Stacks action and partial parameters in the template.filter_parameters event. + * + * @param array $parameters + * + * @return array + */ + public function filterTemplateParameters(sfEvent $event, $parameters) { - return 'View Layer view'; + $entry = ['parameters' => $parameters]; + + if ('action' == $parameters['sf_type'] && $file = $this->getLastTemplate()) { + $this->actions[] = $entry + ['file' => $file]; + } elseif ('partial' == $parameters['sf_type'] && $file = $this->getLastTemplate('sfPartialView')) { + $this->partials[] = $entry + ['file' => $file]; + } + + return $parameters; } - } - - /** - * @see sfWebDebugPanel - */ - public function getPanelTitle() - { - return 'View Layer'; - } - - /** - * @see sfWebDebugPanel - */ - public function getPanelContent() - { - $html = array(); - - foreach ($this->actions as $action) + + /** + * @see sfWebDebugPanel + */ + public function getTitle() { - $html[] = $this->renderTemplateInformation($action['file'], $action['parameters']); + if (count($this->actions) || count($this->partials)) { + return 'View Layer view'; + } } - foreach ($this->partials as $partial) + /** + * @see sfWebDebugPanel + */ + public function getPanelTitle() { - $html[] = $this->renderTemplateInformation($partial['file'], $partial['parameters'], 'Partial'); + return 'View Layer'; } - return implode("\n", $html); - } - - /** - * Renders information about the passed template and its parameters. - * - * The rendered HTML for each parameter is filtered through the "debug.web.view.filter_parameter_html" event. - * - * @param string $file The template file path - * @param array $parameters - * @param string $label - * - * @return string - */ - protected function renderTemplateInformation($file, $parameters, $label = 'Template') - { - static $i = 0; - - $parameters = $this->filterCoreParameters($parameters); - $i++; - - $html = array(); - $html[] = sprintf('

    %s: %s %s

    ', $label, $this->formatFileLink($file, null, $this->shortenTemplatePath($file)), $this->getToggler('sfWebDebugViewTemplate'.$i)); - $html[] = '
    '; - if (count($parameters)) + /** + * @see sfWebDebugPanel + */ + public function getPanelContent() { - $html[] = '

    Parameters:

    '; - $html[] = '
      '; - foreach ($parameters as $name => $parameter) - { - $presentation = '
    • '.$this->formatParameterAsHtml($name, $parameter).'
    • '; - $html[] = $this->webDebug->getEventDispatcher()->filter(new sfEvent($this, 'debug.web.view.filter_parameter_html', array('parameter' => $parameter)), $presentation)->getReturnValue(); - } - $html[] = '
    '; + $html = []; + + foreach ($this->actions as $action) { + $html[] = $this->renderTemplateInformation($action['file'], $action['parameters']); + } + + foreach ($this->partials as $partial) { + $html[] = $this->renderTemplateInformation($partial['file'], $partial['parameters'], 'Partial'); + } + + return implode("\n", $html); } - else + + /** + * Returns the path to the last template rendered. + * + * @param string $class Name of the rendering view class + * + * @return string|null + */ + protected function getLastTemplate($class = 'sfPHPView') { - $html[] = '

    No parameters were passed to this template.

    '; + foreach (array_reverse($this->webDebug->getLogger()->getLogs()) as $log) { + if ( + ($class == $log['type'] || (class_exists($log['type'], false) && is_subclass_of($log['type'], $class))) + && preg_match('/^Render "(.*)"$/', $log['message'], $match) + ) { + return $match[1]; + } + } } - $html[] = '
    '; - - return implode("\n", $html); - } - - /** - * Formats information about a parameter as HTML. - * - * @param string $name - * @param mixed $parameter - * - * @return string - */ - protected function formatParameterAsHtml($name, $parameter) - { - if (!method_exists($this, $method = 'format'.ucwords(gettype($parameter)).'AsHtml')) + + /** + * Renders information about the passed template and its parameters. + * + * The rendered HTML for each parameter is filtered through the "debug.web.view.filter_parameter_html" event. + * + * @param string $file The template file path + * @param array $parameters + * @param string $label + * + * @return string + */ + protected function renderTemplateInformation($file, $parameters, $label = 'Template') { - $method = 'getParameterDescription'; + static $i = 0; + + $parameters = $this->filterCoreParameters($parameters); + ++$i; + + $html = []; + $html[] = sprintf('

    %s: %s %s

    ', $label, $this->formatFileLink($file, null, $this->shortenTemplatePath($file)), $this->getToggler('sfWebDebugViewTemplate'.$i)); + $html[] = '
    '; + if (count($parameters)) { + $html[] = '

    Parameters:

    '; + $html[] = '
      '; + foreach ($parameters as $name => $parameter) { + $presentation = '
    • '.$this->formatParameterAsHtml($name, $parameter).'
    • '; + $html[] = $this->webDebug->getEventDispatcher()->filter(new sfEvent($this, 'debug.web.view.filter_parameter_html', ['parameter' => $parameter]), $presentation)->getReturnValue(); + } + $html[] = '
    '; + } else { + $html[] = '

    No parameters were passed to this template.

    '; + } + $html[] = '
    '; + + return implode("\n", $html); } - return $this->$method($name, $parameter); - } - - /** - * Formats object information as HTML. - * - * @param string $name - * @param object $parameter - * - * @return string - */ - protected function formatObjectAsHtml($name, $parameter) - { - if ($parameter instanceof sfForm) + /** + * Formats information about a parameter as HTML. + * + * @param string $name + * + * @return string + */ + protected function formatParameterAsHtml($name, $parameter) { - return $this->formatFormAsHtml($name, $parameter); + if (!method_exists($this, $method = 'format'.ucwords(gettype($parameter)).'AsHtml')) { + $method = 'getParameterDescription'; + } + + return $this->{$method}($name, $parameter); } - else + + /** + * Formats object information as HTML. + * + * @param string $name + * @param object $parameter + * + * @return string + */ + protected function formatObjectAsHtml($name, $parameter) { - return $this->getParameterDescription($name, $parameter); + if ($parameter instanceof sfForm) { + return $this->formatFormAsHtml($name, $parameter); + } + + return $this->getParameterDescription($name, $parameter); } - } - - /** - * Formats form information as HTML. - * - * @param string $name - * @param sfForm $form - * - * @return string - */ - protected function formatFormAsHtml($name, sfForm $form) - { - static $i = 0; - - $i++; - - if ($form->hasErrors() && sfLogger::NOTICE < $this->getStatus()) + + /** + * Formats form information as HTML. + * + * @param string $name + * + * @return string + */ + protected function formatFormAsHtml($name, sfForm $form) { - $this->setStatus(sfLogger::NOTICE); - } + static $i = 0; - $html = array(); - $html[] = $this->getParameterDescription($name, $form, $form->hasErrors() ? '$%s' : null); - $html[] = $this->getToggler('sfWebDebugViewForm'.$i); - $html[] = ''; - - return implode("\n", $html); - } - - /** - * Formats form field schema information as HTML. - * - * @param sfFormFieldSchema $fieldSchema - * @param string $nameFormat - * - * @return string - */ - protected function formatFormFieldSchemaAsHtml(sfFormFieldSchema $fieldSchema, $nameFormat = '%s') - { - $html = array(); - - foreach ($fieldSchema as $field) - { - $name = sprintf($nameFormat, $this->varExport($field->getName())); - if ($field instanceof sfFormFieldSchema) - { - $html[] = $this->formatFormFieldSchemaAsHtml($field, $name.'[%s]'); - } - else - { - $html[] = '
  • '; - $html[] = $this->getParameterDescription($name, $field->getWidget()); - - if ($field->hasError()) - { - $html[] = sprintf('

    %s

    ', $field->getError()); + $html = []; + $html[] = $this->getParameterDescription($name, $form, $form->hasErrors() ? '$%s' : null); + $html[] = $this->getToggler('sfWebDebugViewForm'.$i); + $html[] = '
  • '; - } + $html[] = '
      '.$this->formatFormFieldSchemaAsHtml($form->getFormFieldSchema(), $name.'[%s]').'
    '; + $html[] = '
    '; + + return implode("\n", $html); } - return implode("\n", $html); - } - - /** - * Formats information about a parameter as HTML. - * - * @param string $name - * @param mixed $parameter - * - * @return string - */ - protected function getParameterDescription($name, $parameter, $nameFormat = null, $typeFormat = null) - { - if (null === $nameFormat) + /** + * Formats form field schema information as HTML. + * + * @param string $nameFormat + * + * @return string + */ + protected function formatFormFieldSchemaAsHtml(sfFormFieldSchema $fieldSchema, $nameFormat = '%s') { - $nameFormat = '$%s'; + $html = []; + + foreach ($fieldSchema as $field) { + $name = sprintf($nameFormat, $this->varExport($field->getName())); + if ($field instanceof sfFormFieldSchema) { + $html[] = $this->formatFormFieldSchemaAsHtml($field, $name.'[%s]'); + } else { + $html[] = '
  • '; + $html[] = $this->getParameterDescription($name, $field->getWidget()); + + if ($field->hasError()) { + $html[] = sprintf('

    %s

    ', $field->getError()); + } + + $html[] = '
  • '; + } + } + + return implode("\n", $html); } - if (null === $typeFormat) + /** + * Formats information about a parameter as HTML. + * + * @param string $name + * @param mixed|null $nameFormat + * @param mixed|null $typeFormat + * + * @return string + */ + protected function getParameterDescription($name, $parameter, $nameFormat = null, $typeFormat = null) { - $typeFormat = '(%s)'; + if (null === $nameFormat) { + $nameFormat = '$%s'; + } + + if (null === $typeFormat) { + $typeFormat = '(%s)'; + } + + return sprintf($nameFormat.' '.$typeFormat, $name, is_object($parameter) ? $this->formatFileLink(get_class($parameter)) : gettype($parameter)); } - return sprintf($nameFormat.' '.$typeFormat, $name, is_object($parameter) ? $this->formatFileLink(get_class($parameter)) : gettype($parameter)); - } - - /** - * Shortens an action's template path. - * - * @param string $path - * - * @return string - */ - protected function shortenTemplatePath($path) - { - $path = realpath($path); - - // application module - $sep = preg_quote(DIRECTORY_SEPARATOR); - if (preg_match('#modules'.$sep.'(\w+)'.$sep.'templates'.$sep.'(.*)$#', $path, $match)) + /** + * Shortens an action's template path. + * + * @param string $path + * + * @return string + */ + protected function shortenTemplatePath($path) { - return $match[1].' … '.$match[2]; + $path = realpath($path); + + // application module + $sep = preg_quote(DIRECTORY_SEPARATOR); + if (preg_match('#modules'.$sep.'(\w+)'.$sep.'templates'.$sep.'(.*)$#', $path, $match)) { + return $match[1].' … '.$match[2]; + } + + return str_replace('SF_ROOT_DIR'.DIRECTORY_SEPARATOR, '', sfDebug::shortenFilePath($path)); } - return str_replace('SF_ROOT_DIR'.DIRECTORY_SEPARATOR, '', sfDebug::shortenFilePath($path)); - } - - /** - * Removes parameters prefixed with "sf_" from the array. - * - * @param array $parameters - * - * @return array - */ - protected function filterCoreParameters($parameters) - { - $filtered = array(); - - foreach ($parameters as $name => $value) + /** + * Removes parameters prefixed with "sf_" from the array. + * + * @param array $parameters + * + * @return array + */ + protected function filterCoreParameters($parameters) { - if (0 !== strpos($name, 'sf_')) - { - $filtered[$name] = $value; - } + $filtered = []; + + foreach ($parameters as $name => $value) { + if (0 !== strpos($name, 'sf_')) { + $filtered[$name] = $value; + } + } + + return $filtered; } - return $filtered; - } - - /** - * Returns a string representation of a value. - * - * @param string $value - * - * @return string - */ - protected function varExport($value) - { - if (is_numeric($value)) + /** + * Returns a string representation of a value. + * + * @param string $value + * + * @return string + */ + protected function varExport($value) { - $value = (integer) $value; - } + if (is_numeric($value)) { + $value = (int) $value; + } - return var_export($value, true); - } + return var_export($value, true); + } } diff --git a/lib/escaper/sfOutputEscaper.class.php b/lib/escaper/sfOutputEscaper.class.php index 6eeec7dcd..fb7c2d3d0 100644 --- a/lib/escaper/sfOutputEscaper.class.php +++ b/lib/escaper/sfOutputEscaper.class.php @@ -11,233 +11,210 @@ /** * Abstract class that provides an interface for escaping of output. * - * @package symfony - * @subpackage view * @author Mike Squire - * @version SVN: $Id$ */ abstract class sfOutputEscaper { - /** - * The value that is to be escaped. - * - * @var mixed - */ - protected $value; - - /** - * The escaping method that is going to be applied to the value and its - * children. This is actually the name of a PHP callable. - * - * @var string - */ - protected $escapingMethod; - - static protected $safeClasses = array(); - - /** - * Constructor stores the escaping method and value. - * - * Since sfOutputEscaper is an abstract class, instances cannot be created - * directly but the constructor will be inherited by sub-classes. - * - * @param string $escapingMethod Escaping method - * @param string $value Escaping value - */ - public function __construct($escapingMethod, $value) - { - $this->value = $value; - $this->escapingMethod = $escapingMethod; - } - - /** - * Decorates a PHP variable with something that will escape any data obtained - * from it. - * - * The following cases are dealt with: - * - * - The value is null or false: null or false is returned. - * - The value is scalar: the result of applying the escaping method is - * returned. - * - The value is an array or an object that implements the ArrayAccess - * interface: the array is decorated such that accesses to elements yield - * an escaped value. - * - The value implements the Traversable interface (either an Iterator, an - * IteratorAggregate or an internal PHP class that implements - * Traversable): decorated much like the array. - * - The value is another type of object: decorated such that the result of - * method calls is escaped. - * - * The escaping method is actually the name of a PHP callable. There are a set - * of standard escaping methods listed in the escaping helper - * (EscapingHelper.php). - * - * @param string $escapingMethod The escaping method (a PHP callable) to apply to the value - * @param mixed $value The value to escape - * - * @return mixed Escaping value - * - * @throws InvalidArgumentException If the escaping fails - */ - public static function escape($escapingMethod, $value) - { - if (null === $value) + /** + * The value that is to be escaped. + */ + protected $value; + + /** + * The escaping method that is going to be applied to the value and its + * children. This is actually the name of a PHP callable. + * + * @var string + */ + protected $escapingMethod; + + protected static $safeClasses = []; + + /** + * Constructor stores the escaping method and value. + * + * Since sfOutputEscaper is an abstract class, instances cannot be created + * directly but the constructor will be inherited by sub-classes. + * + * @param string $escapingMethod Escaping method + * @param string $value Escaping value + */ + public function __construct($escapingMethod, $value) { - return $value; + $this->value = $value; + $this->escapingMethod = $escapingMethod; } - // Scalars are anything other than arrays, objects and resources. - if (is_scalar($value)) + /** + * Gets a value from the escaper. + * + * @param string $var Value to get + * + * @return mixed Value + */ + public function __get($var) { - return call_user_func($escapingMethod, $value); + return $this->escape($this->escapingMethod, $this->value->{$var}); } - if (is_array($value)) + /** + * Decorates a PHP variable with something that will escape any data obtained + * from it. + * + * The following cases are dealt with: + * + * - The value is null or false: null or false is returned. + * - The value is scalar: the result of applying the escaping method is + * returned. + * - The value is an array or an object that implements the ArrayAccess + * interface: the array is decorated such that accesses to elements yield + * an escaped value. + * - The value implements the Traversable interface (either an Iterator, an + * IteratorAggregate or an internal PHP class that implements + * Traversable): decorated much like the array. + * - The value is another type of object: decorated such that the result of + * method calls is escaped. + * + * The escaping method is actually the name of a PHP callable. There are a set + * of standard escaping methods listed in the escaping helper + * (EscapingHelper.php). + * + * @param string $escapingMethod The escaping method (a PHP callable) to apply to the value + * @param mixed $value The value to escape + * + * @return mixed Escaping value + * + * @throws InvalidArgumentException If the escaping fails + */ + public static function escape($escapingMethod, $value) { - return new sfOutputEscaperArrayDecorator($escapingMethod, $value); + if (null === $value) { + return $value; + } + + // Scalars are anything other than arrays, objects and resources. + if (is_scalar($value)) { + return call_user_func($escapingMethod, $value); + } + + if (is_array($value)) { + return new sfOutputEscaperArrayDecorator($escapingMethod, $value); + } + + if (is_object($value)) { + if ($value instanceof sfOutputEscaper) { + // avoid double decoration + $copy = clone $value; + + $copy->escapingMethod = $escapingMethod; + + return $copy; + } + if (self::isClassMarkedAsSafe(get_class($value))) { + // the class or one of its children is marked as safe + // return the unescaped object + return $value; + } + if ($value instanceof sfOutputEscaperSafe) { + // do not escape objects marked as safe + // return the original object + return $value->getValue(); + } + if ($value instanceof Traversable) { + return new sfOutputEscaperIteratorDecorator($escapingMethod, $value); + } + + return new sfOutputEscaperObjectDecorator($escapingMethod, $value); + } + + // it must be a resource; cannot escape that. + throw new InvalidArgumentException(sprintf('Unable to escape value "%s".', var_export($value, true))); } - if (is_object($value)) + /** + * Unescapes a value that has been escaped previously with the escape() method. + * + * @param mixed $value The value to unescape + * + * @return mixed Unescaped value + * + * @throws InvalidArgumentException If the escaping fails + */ + public static function unescape($value) { - if ($value instanceof sfOutputEscaper) - { - // avoid double decoration - $copy = clone $value; - - $copy->escapingMethod = $escapingMethod; - - return $copy; - } - else if (self::isClassMarkedAsSafe(get_class($value))) - { - // the class or one of its children is marked as safe - // return the unescaped object + if (null === $value || is_bool($value)) { + return $value; + } + + if (is_scalar($value)) { + return html_entity_decode($value, ENT_QUOTES, sfConfig::get('sf_charset')); + } + if (is_array($value)) { + foreach ($value as $name => $v) { + $value[$name] = self::unescape($v); + } + + return $value; + } + if (is_object($value)) { + return $value instanceof sfOutputEscaper ? $value->getRawValue() : $value; + } + return $value; - } - else if ($value instanceof sfOutputEscaperSafe) - { - // do not escape objects marked as safe - // return the original object - return $value->getValue(); - } - else if ($value instanceof Traversable) - { - return new sfOutputEscaperIteratorDecorator($escapingMethod, $value); - } - else - { - return new sfOutputEscaperObjectDecorator($escapingMethod, $value); - } } - // it must be a resource; cannot escape that. - throw new InvalidArgumentException(sprintf('Unable to escape value "%s".', var_export($value, true))); - } - - /** - * Unescapes a value that has been escaped previously with the escape() method. - * - * @param mixed $value The value to unescape - * - * @return mixed Unescaped value - * - * @throws InvalidArgumentException If the escaping fails - */ - static public function unescape($value) - { - if (null === $value || is_bool($value)) + /** + * Returns true if the class if marked as safe. + * + * @param string $class A class name + * + * @return bool true if the class if safe, false otherwise + */ + public static function isClassMarkedAsSafe($class) { - return $value; - } + if (in_array($class, self::$safeClasses)) { + return true; + } - if (is_scalar($value)) - { - return html_entity_decode($value, ENT_QUOTES, sfConfig::get('sf_charset')); - } - elseif (is_array($value)) - { - foreach ($value as $name => $v) - { - $value[$name] = self::unescape($v); - } + foreach (self::$safeClasses as $safeClass) { + if (is_subclass_of($class, $safeClass)) { + return true; + } + } - return $value; + return false; } - elseif (is_object($value)) + + /** + * Marks an array of classes (and all its children) as being safe for output. + * + * @param array $classes An array of class names + */ + public static function markClassesAsSafe(array $classes) { - return $value instanceof sfOutputEscaper ? $value->getRawValue() : $value; + self::$safeClasses = array_unique(array_merge(self::$safeClasses, $classes)); } - return $value; - } - - /** - * Returns true if the class if marked as safe. - * - * @param string $class A class name - * - * @return bool true if the class if safe, false otherwise - */ - static public function isClassMarkedAsSafe($class) - { - if (in_array($class, self::$safeClasses)) + /** + * Marks a class (and all its children) as being safe for output. + * + * @param string $class A class name + */ + public static function markClassAsSafe($class) { - return true; + self::markClassesAsSafe([$class]); } - foreach (self::$safeClasses as $safeClass) + /** + * Returns the raw value associated with this instance. + * + * Concrete instances of sfOutputEscaper classes decorate a value which is + * stored by the constructor. This returns that original, unescaped, value. + * + * @return mixed The original value used to construct the decorator + */ + public function getRawValue() { - if (is_subclass_of($class, $safeClass)) - { - return true; - } + return $this->value; } - - return false; - } - - /** - * Marks an array of classes (and all its children) as being safe for output. - * - * @param array $classes An array of class names - */ - static public function markClassesAsSafe(array $classes) - { - self::$safeClasses = array_unique(array_merge(self::$safeClasses, $classes)); - } - - /** - * Marks a class (and all its children) as being safe for output. - * - * @param string $class A class name - */ - static public function markClassAsSafe($class) - { - self::markClassesAsSafe(array($class)); - } - - /** - * Returns the raw value associated with this instance. - * - * Concrete instances of sfOutputEscaper classes decorate a value which is - * stored by the constructor. This returns that original, unescaped, value. - * - * @return mixed The original value used to construct the decorator - */ - public function getRawValue() - { - return $this->value; - } - - /** - * Gets a value from the escaper. - * - * @param string $var Value to get - * - * @return mixed Value - */ - public function __get($var) - { - return $this->escape($this->escapingMethod, $this->value->$var); - } } diff --git a/lib/escaper/sfOutputEscaperArrayDecorator.class.php b/lib/escaper/sfOutputEscaperArrayDecorator.class.php index 072bff9f8..bec3b3ee1 100644 --- a/lib/escaper/sfOutputEscaperArrayDecorator.class.php +++ b/lib/escaper/sfOutputEscaperArrayDecorator.class.php @@ -12,176 +12,174 @@ * Output escaping decorator class for arrays. * * @see sfOutputEscaper - * @package symfony - * @subpackage view + * * @author Mike Squire - * @version SVN: $Id$ */ class sfOutputEscaperArrayDecorator extends sfOutputEscaperGetterDecorator implements Iterator, ArrayAccess, Countable { - /** - * Used by the iterator to know if the current element is valid. - * - * @var int - */ - private $count; - - /** - * Constructor. - * - * @see sfOutputEscaper - * @inheritdoc - */ - public function __construct($escapingMethod, $value) - { - parent::__construct($escapingMethod, $value); - - $this->count = count($this->value); - } - - /** - * Reset the array to the beginning (as required for the Iterator interface). - */ - #[\ReturnTypeWillChange] - public function rewind() - { - reset($this->value); - - $this->count = count($this->value); - } - - /** - * Get the key associated with the current value (as required by the Iterator interface). - * - * @return string The key - */ - #[\ReturnTypeWillChange] - public function key() - { - return key($this->value); - } - - /** - * Escapes and return the current value (as required by the Iterator interface). - * - * This escapes the value using {@link sfOutputEscaper::escape()} with - * whatever escaping method is set for this instance. - * - * @return mixed The escaped value - */ - #[\ReturnTypeWillChange] - public function current() - { - return sfOutputEscaper::escape($this->escapingMethod, current($this->value)); - } - - /** - * Moves to the next element (as required by the Iterator interface). - */ - #[\ReturnTypeWillChange] - public function next() - { - next($this->value); - - $this->count--; - } - - /** - * Returns true if the current element is valid (as required by the Iterator interface). - * - * The current element will not be valid if {@link next()} has fallen off the - * end of the array or if there are no elements in the array and {@link - * rewind()} was called. - * - * @return bool The validity of the current element; true if it is valid - */ - #[\ReturnTypeWillChange] - public function valid() - { - return $this->count > 0; - } - - /** - * Returns true if the supplied offset isset in the array (as required by the ArrayAccess interface). - * - * @param string $offset The offset of the value to check existance of - * - * @return bool true if the offset isset; false otherwise - */ - #[\ReturnTypeWillChange] - public function offsetExists($offset) - { - return isset($this->value[$offset]); - } - - /** - * Returns the element associated with the offset supplied (as required by the ArrayAccess interface). - * - * @param string $offset The offset of the value to get - * - * @return mixed The escaped value - */ - #[\ReturnTypeWillChange] - public function offsetGet($offset) - { - return sfOutputEscaper::escape($this->escapingMethod, isset($this->value[$offset]) ? $this->value[$offset] : null); - } - - /** - * Throws an exception saying that values cannot be set (this method is - * required for the ArrayAccess interface). - * - * This (and the other sfOutputEscaper classes) are designed to be read only - * so this is an illegal operation. - * - * @param string $offset (ignored) - * @param string $value (ignored) - * - * @throws sfException - */ - #[\ReturnTypeWillChange] - public function offsetSet($offset, $value) - { - throw new sfException('Cannot set values.'); - } - - /** - * Throws an exception saying that values cannot be unset (this method is - * required for the ArrayAccess interface). - * - * This (and the other sfOutputEscaper classes) are designed to be read only - * so this is an illegal operation. - * - * @param string $offset (ignored) - * - * @throws sfException - */ - #[\ReturnTypeWillChange] - public function offsetUnset($offset) - { - throw new sfException('Cannot unset values.'); - } - - /** - * Returns the size of the array (are required by the Countable interface). - * - * @return int The size of the array - */ - #[\ReturnTypeWillChange] - public function count() - { - return count($this->value); - } - - /** - * Returns the (unescaped) value from the array associated with the key supplied. - * - * @param string $key The key into the array to use - * - * @return mixed The value - */ - public function getRaw($key) - { - return $this->value[$key]; - } + /** + * Used by the iterator to know if the current element is valid. + * + * @var int + */ + private $count; + + /** + * Constructor. + * + * @see sfOutputEscaper + */ + public function __construct($escapingMethod, $value) + { + parent::__construct($escapingMethod, $value); + + $this->count = count($this->value); + } + + /** + * Reset the array to the beginning (as required for the Iterator interface). + */ + #[ReturnTypeWillChange] + public function rewind() + { + reset($this->value); + + $this->count = count($this->value); + } + + /** + * Get the key associated with the current value (as required by the Iterator interface). + * + * @return string The key + */ + #[ReturnTypeWillChange] + public function key() + { + return key($this->value); + } + + /** + * Escapes and return the current value (as required by the Iterator interface). + * + * This escapes the value using {@link sfOutputEscaper::escape()} with + * whatever escaping method is set for this instance. + * + * @return mixed The escaped value + */ + #[ReturnTypeWillChange] + public function current() + { + return sfOutputEscaper::escape($this->escapingMethod, current($this->value)); + } + + /** + * Moves to the next element (as required by the Iterator interface). + */ + #[ReturnTypeWillChange] + public function next() + { + next($this->value); + + --$this->count; + } + + /** + * Returns true if the current element is valid (as required by the Iterator interface). + * + * The current element will not be valid if {@link next()} has fallen off the + * end of the array or if there are no elements in the array and {@link * rewind()} was called. + * + * @return bool The validity of the current element; true if it is valid + */ + #[ReturnTypeWillChange] + public function valid() + { + return $this->count > 0; + } + + /** + * Returns true if the supplied offset isset in the array (as required by the ArrayAccess interface). + * + * @param string $offset The offset of the value to check existance of + * + * @return bool true if the offset isset; false otherwise + */ + #[ReturnTypeWillChange] + public function offsetExists($offset) + { + return isset($this->value[$offset]); + } + + /** + * Returns the element associated with the offset supplied (as required by the ArrayAccess interface). + * + * @param string $offset The offset of the value to get + * + * @return mixed The escaped value + */ + #[ReturnTypeWillChange] + public function offsetGet($offset) + { + $value = isset($this->value[$offset]) ? $this->value[$offset] : null; + + return sfOutputEscaper::escape($this->escapingMethod, $value); + } + + /** + * Throws an exception saying that values cannot be set (this method is + * required for the ArrayAccess interface). + * + * This (and the other sfOutputEscaper classes) are designed to be read only + * so this is an illegal operation. + * + * @param string $offset (ignored) + * @param string $value (ignored) + * + * @throws sfException + */ + #[ReturnTypeWillChange] + public function offsetSet($offset, $value) + { + throw new sfException('Cannot set values.'); + } + + /** + * Throws an exception saying that values cannot be unset (this method is + * required for the ArrayAccess interface). + * + * This (and the other sfOutputEscaper classes) are designed to be read only + * so this is an illegal operation. + * + * @param string $offset (ignored) + * + * @throws sfException + */ + #[ReturnTypeWillChange] + public function offsetUnset($offset) + { + throw new sfException('Cannot unset values.'); + } + + /** + * Returns the size of the array (are required by the Countable interface). + * + * @return int The size of the array + */ + #[ReturnTypeWillChange] + public function count() + { + return count($this->value); + } + + /** + * Returns the (unescaped) value from the array associated with the key supplied. + * + * @param string $key The key into the array to use + * + * @return mixed The value + */ + public function getRaw($key) + { + return $this->value[$key]; + } } diff --git a/lib/escaper/sfOutputEscaperGetterDecorator.class.php b/lib/escaper/sfOutputEscaperGetterDecorator.class.php index 7ff241f64..251eb0cf7 100644 --- a/lib/escaper/sfOutputEscaperGetterDecorator.class.php +++ b/lib/escaper/sfOutputEscaperGetterDecorator.class.php @@ -12,43 +12,40 @@ * Abstract output escaping decorator class for "getter" objects. * * @see sfOutputEscaper - * @package symfony - * @subpackage view + * * @author Mike Squire - * @version SVN: $Id$ */ abstract class sfOutputEscaperGetterDecorator extends sfOutputEscaper { - /** - * Returns the raw, unescaped value associated with the key supplied. - * - * The key might be an index into an array or a value to be passed to the - * decorated object's get() method. - * - * @param string $key The key to retrieve - * - * @return mixed The value - */ - public abstract function getRaw($key); + /** + * Returns the raw, unescaped value associated with the key supplied. + * + * The key might be an index into an array or a value to be passed to the + * decorated object's get() method. + * + * @param string $key The key to retrieve + * + * @return mixed The value + */ + abstract public function getRaw($key); - /** - * Returns the escaped value associated with the key supplied. - * - * Typically (using this implementation) the raw value is obtained using the - * {@link getRaw()} method, escaped and the result returned. - * - * @param string $key The key to retieve - * @param string $escapingMethod The escaping method (a PHP function) to use - * - * @return mixed The escaped value - */ - public function get($key, $escapingMethod = null) - { - if (!$escapingMethod) + /** + * Returns the escaped value associated with the key supplied. + * + * Typically (using this implementation) the raw value is obtained using the + * {@link getRaw()} method, escaped and the result returned. + * + * @param string $key The key to retieve + * @param string $escapingMethod The escaping method (a PHP function) to use + * + * @return mixed The escaped value + */ + public function get($key, $escapingMethod = null) { - $escapingMethod = $this->escapingMethod; - } + if (!$escapingMethod) { + $escapingMethod = $this->escapingMethod; + } - return sfOutputEscaper::escape($escapingMethod, $this->getRaw($key)); - } + return sfOutputEscaper::escape($escapingMethod, $this->getRaw($key)); + } } diff --git a/lib/escaper/sfOutputEscaperIteratorDecorator.class.php b/lib/escaper/sfOutputEscaperIteratorDecorator.class.php index 68ed43dfd..ca0ab0430 100644 --- a/lib/escaper/sfOutputEscaperIteratorDecorator.class.php +++ b/lib/escaper/sfOutputEscaperIteratorDecorator.class.php @@ -21,150 +21,146 @@ * exception. * * @see sfOutputEscaper - * @package symfony - * @subpackage view + * * @author Mike Squire + * * @version SVN: $Id$ */ class sfOutputEscaperIteratorDecorator extends sfOutputEscaperObjectDecorator implements Iterator, ArrayAccess { - /** - * The iterator to be used. - * - * @var IteratorIterator - */ - private $iterator; + /** + * The iterator to be used. + * + * @var IteratorIterator + */ + private $iterator; - /** - * Constructs a new escaping iteratoror using the escaping method and value supplied. - * - * @param string $escapingMethod The escaping method to use - * @param Traversable $value The iterator to escape - */ - public function __construct($escapingMethod, Traversable $value) - { - // Set the original value for __call(). Set our own iterator because passing - // it to IteratorIterator will lose any other method calls. + /** + * Constructs a new escaping iteratoror using the escaping method and value supplied. + * + * @param string $escapingMethod The escaping method to use + * @param Traversable $value The iterator to escape + */ + public function __construct($escapingMethod, Traversable $value) + { + // Set the original value for __call(). Set our own iterator because passing + // it to IteratorIterator will lose any other method calls. - parent::__construct($escapingMethod, $value); + parent::__construct($escapingMethod, $value); - $this->iterator = new IteratorIterator($value); - } + $this->iterator = new IteratorIterator($value); + } - /** - * Resets the iterator (as required by the Iterator interface). - * - * @return void - */ - #[\ReturnTypeWillChange] - public function rewind() - { - return $this->iterator->rewind(); - } + /** + * Resets the iterator (as required by the Iterator interface). + */ + #[ReturnTypeWillChange] + public function rewind() + { + return $this->iterator->rewind(); + } - /** - * Escapes and gets the current element (as required by the Iterator interface). - * - * @return mixed The escaped value - */ - #[\ReturnTypeWillChange] - public function current() - { - return sfOutputEscaper::escape($this->escapingMethod, $this->iterator->current()); - } + /** + * Escapes and gets the current element (as required by the Iterator interface). + * + * @return mixed The escaped value + */ + #[ReturnTypeWillChange] + public function current() + { + return sfOutputEscaper::escape($this->escapingMethod, $this->iterator->current()); + } - /** - * Gets the current key (as required by the Iterator interface). - * - * @return string Iterator key - */ - #[\ReturnTypeWillChange] - public function key() - { - return $this->iterator->key(); - } + /** + * Gets the current key (as required by the Iterator interface). + * + * @return string Iterator key + */ + #[ReturnTypeWillChange] + public function key() + { + return $this->iterator->key(); + } - /** - * Moves to the next element in the iterator (as required by the Iterator interface). - * - * @return void - */ - #[\ReturnTypeWillChange] - public function next() - { - return $this->iterator->next(); - } + /** + * Moves to the next element in the iterator (as required by the Iterator interface). + */ + #[ReturnTypeWillChange] + public function next() + { + return $this->iterator->next(); + } - /** - * Returns whether the current element is valid or not (as required by the - * Iterator interface). - * - * @return bool true if the current element is valid; false otherwise - */ - #[\ReturnTypeWillChange] - public function valid() - { - return $this->iterator->valid(); - } + /** + * Returns whether the current element is valid or not (as required by the + * Iterator interface). + * + * @return bool true if the current element is valid; false otherwise + */ + #[ReturnTypeWillChange] + public function valid() + { + return $this->iterator->valid(); + } - /** - * Returns true if the supplied offset isset in the array (as required by the ArrayAccess interface). - * - * @param string $offset The offset of the value to check existance of - * - * @return bool true if the offset isset; false otherwise - */ - #[\ReturnTypeWillChange] - public function offsetExists($offset) - { - return isset($this->value[$offset]); - } + /** + * Returns true if the supplied offset isset in the array (as required by the ArrayAccess interface). + * + * @param string $offset The offset of the value to check existance of + * + * @return bool true if the offset isset; false otherwise + */ + #[ReturnTypeWillChange] + public function offsetExists($offset) + { + return isset($this->value[$offset]); + } - /** - * Returns the element associated with the offset supplied (as required by the ArrayAccess interface). - * - * @param string $offset The offset of the value to get - * - * @return mixed The escaped value - */ - #[\ReturnTypeWillChange] - public function offsetGet($offset) - { - return sfOutputEscaper::escape($this->escapingMethod, $this->value[$offset]); - } + /** + * Returns the element associated with the offset supplied (as required by the ArrayAccess interface). + * + * @param string $offset The offset of the value to get + * + * @return mixed The escaped value + */ + #[ReturnTypeWillChange] + public function offsetGet($offset) + { + return sfOutputEscaper::escape($this->escapingMethod, $this->value[$offset]); + } - /** - * Throws an exception saying that values cannot be set (this method is - * required for the ArrayAccess interface). - * - * This (and the other sfOutputEscaper classes) are designed to be read only - * so this is an illegal operation. - * - * @param string $offset (ignored) - * @param string $value (ignored) - * - * @throws sfException - */ - #[\ReturnTypeWillChange] - public function offsetSet($offset, $value) - { - throw new sfException('Cannot set values.'); - } + /** + * Throws an exception saying that values cannot be set (this method is + * required for the ArrayAccess interface). + * + * This (and the other sfOutputEscaper classes) are designed to be read only + * so this is an illegal operation. + * + * @param string $offset (ignored) + * @param string $value (ignored) + * + * @throws sfException + */ + #[ReturnTypeWillChange] + public function offsetSet($offset, $value) + { + throw new sfException('Cannot set values.'); + } - /** - * Throws an exception saying that values cannot be unset (this method is - * required for the ArrayAccess interface). - * - * This (and the other sfOutputEscaper classes) are designed to be read only - * so this is an illegal operation. - * - * @param string $offset (ignored) - * - * @throws sfException - */ - #[\ReturnTypeWillChange] - public function offsetUnset($offset) - { - throw new sfException('Cannot unset values.'); - } + /** + * Throws an exception saying that values cannot be unset (this method is + * required for the ArrayAccess interface). + * + * This (and the other sfOutputEscaper classes) are designed to be read only + * so this is an illegal operation. + * + * @param string $offset (ignored) + * + * @throws sfException + */ + #[ReturnTypeWillChange] + public function offsetUnset($offset) + { + throw new sfException('Cannot unset values.'); + } } diff --git a/lib/escaper/sfOutputEscaperObjectDecorator.class.php b/lib/escaper/sfOutputEscaperObjectDecorator.class.php index ea4adcc57..fd8864bd8 100644 --- a/lib/escaper/sfOutputEscaperObjectDecorator.class.php +++ b/lib/escaper/sfOutputEscaperObjectDecorator.class.php @@ -13,116 +13,107 @@ * their return values. * * @see sfOutputEscaper - * @package symfony - * @subpackage view + * * @author Mike Squire - * @version SVN: $Id$ */ class sfOutputEscaperObjectDecorator extends sfOutputEscaperGetterDecorator implements Countable { - /** - * Magic PHP method that intercepts method calls, calls them on the objects - * that is being escaped and escapes the result. - * - * The calling of the method is changed slightly to accommodate passing a - * specific escaping strategy. An additional parameter is appended to the - * argument list which is the escaping strategy. The decorator will remove - * and use this parameter as the escaping strategy if it begins with 'esc_' - * (the prefix all escaping helper functions have). - * - * For example if an object, $o, implements methods a() and b($arg): - * - * $o->a() // Escapes the return value of a() - * $o->a(ESC_RAW) // Uses the escaping method ESC_RAW with a() - * $o->b('a') // Escapes the return value of b('a') - * $o->b('a', ESC_RAW); // Uses the escaping method ESC_RAW with b('a') - * - * @param string $method The method on the object to be called - * @param array $args An array of arguments to be passed to the method - * - * @return mixed The escaped value returned by the method - */ - public function __call($method, $args) - { - if (count($args) > 0) - { - $escapingMethod = $args[count($args) - 1]; - if (is_string($escapingMethod) && substr($escapingMethod, 0, 4) === 'esc_') - { - array_pop($args); - } - else - { - $escapingMethod = $this->escapingMethod; - } - } - else + /** + * Magic PHP method that intercepts method calls, calls them on the objects + * that is being escaped and escapes the result. + * + * The calling of the method is changed slightly to accommodate passing a + * specific escaping strategy. An additional parameter is appended to the + * argument list which is the escaping strategy. The decorator will remove + * and use this parameter as the escaping strategy if it begins with 'esc_' + * (the prefix all escaping helper functions have). + * + * For example if an object, $o, implements methods a() and b($arg): + * + * $o->a() // Escapes the return value of a() + * $o->a(ESC_RAW) // Uses the escaping method ESC_RAW with a() + * $o->b('a') // Escapes the return value of b('a') + * $o->b('a', ESC_RAW); // Uses the escaping method ESC_RAW with b('a') + * + * @param string $method The method on the object to be called + * @param array $args An array of arguments to be passed to the method + * + * @return mixed The escaped value returned by the method + */ + public function __call($method, $args) { - $escapingMethod = $this->escapingMethod; - } + if (count($args) > 0) { + $escapingMethod = $args[count($args) - 1]; + if (is_string($escapingMethod) && 'esc_' === substr($escapingMethod, 0, 4)) { + array_pop($args); + } else { + $escapingMethod = $this->escapingMethod; + } + } else { + $escapingMethod = $this->escapingMethod; + } - $value = call_user_func_array(array($this->value, $method), $args); + $value = call_user_func_array([$this->value, $method], $args); - return sfOutputEscaper::escape($escapingMethod, $value); - } + return sfOutputEscaper::escape($escapingMethod, $value); + } - /** - * Returns the result of calling the get() method on the object, bypassing - * any escaping, if that method exists. - * - * If there is not a callable get() method this will throw an exception. - * - * @param string $key The parameter to be passed to the get() get method - * - * @return mixed The unescaped value returned - * - * @throws sfException if the object does not have a callable get() method - */ - public function getRaw($key) - { - if (!is_callable(array($this->value, 'get'))) + /** + * Try to call decorated object __toString() method if exists. + * + * @return string + */ + public function __toString() { - throw new sfException('Object does not have a callable get() method.'); + return $this->escape($this->escapingMethod, (string) $this->value); } - return $this->value->get($key); - } + /** + * Asks the wrapped object whether a property is set. + * + * @return bool + */ + public function __isset($key) + { + return isset($this->value->{$key}); + } - /** - * Try to call decorated object __toString() method if exists. - * - * @return string - */ - public function __toString() - { - return $this->escape($this->escapingMethod, (string) $this->value); - } + /** + * Returns the result of calling the get() method on the object, bypassing + * any escaping, if that method exists. + * + * If there is not a callable get() method this will throw an exception. + * + * @param string $key The parameter to be passed to the get() get method + * + * @return mixed The unescaped value returned + * + * @throws sfException if the object does not have a callable get() method + */ + public function getRaw($key) + { + if (!is_callable([$this->value, 'get'])) { + throw new sfException('Object does not have a callable get() method.'); + } - /** - * Asks the wrapped object whether a property is set. - * - * @return boolean - */ - public function __isset($key) - { - return isset($this->value->$key); - } + return $this->value->get($key); + } - /** - * Returns the size of the object if it implements Countable (is required by the Countable interface). - * - * It returns 1 if other cases (which was the default PHP behavior in such a case before php 7.3). - * - * @return int The size of the object - */ - #[\ReturnTypeWillChange] - public function count() - { - // See https://github.com/symfony/polyfill/commit/d330c0094a47d8edceeea1ed553d6e08215a9fc2 - if (is_array($this->value) || $this->value instanceof Countable || $this->value instanceof ResourceBundle || $this->value instanceof SimpleXmlElement) + /** + * Returns the size of the object if it implements Countable (is required by the Countable interface). + * + * It returns 1 if other cases (which was the default PHP behavior in such a case before php 7.3). + * + * @return int The size of the object + */ + #[ReturnTypeWillChange] + public function count() { - return count($this->value); + // See https://github.com/symfony/polyfill/commit/d330c0094a47d8edceeea1ed553d6e08215a9fc2 + if (is_array($this->value) || $this->value instanceof Countable || $this->value instanceof ResourceBundle || $this->value instanceof SimpleXMLElement) { + return count($this->value); + } + + return 1; } - return 1; - } } diff --git a/lib/escaper/sfOutputEscaperSafe.class.php b/lib/escaper/sfOutputEscaperSafe.class.php index c4ddba4c2..b5594f972 100644 --- a/lib/escaper/sfOutputEscaperSafe.class.php +++ b/lib/escaper/sfOutputEscaperSafe.class.php @@ -11,68 +11,63 @@ /** * Marks a variable as being safe for output. * - * @package symfony - * @subpackage view * @author Fabien Potencier - * @version SVN: $Id$ */ class sfOutputEscaperSafe extends ArrayIterator { - protected - $value = null; + protected $value; - /** - * Constructor. - * - * @param mixed $value The value to mark as safe - */ - public function __construct($value) - { - $this->value = $value; - - if (is_array($value) || is_object($value)) + /** + * Constructor. + * + * @param mixed $value The value to mark as safe + */ + public function __construct($value) { - parent::__construct($value); + $this->value = $value; + + if (is_array($value) || is_object($value)) { + parent::__construct($value); + } } - } - public function __toString() - { - return (string) $this->value; - } + public function __toString() + { + return (string) $this->value; + } - public function __get($key) - { - return $this->value->$key; - } + public function __get($key) + { + return $this->value->{$key}; + } - public function __set($key, $value) - { - $this->value->$key = $value; - } + public function __set($key, $value) + { + $this->value->{$key} = $value; + } - public function __call($method, $arguments) - { - return call_user_func_array(array($this->value, $method), $arguments); - } + public function __call($method, $arguments) + { + return call_user_func_array([$this->value, $method], $arguments); + } - public function __isset($key) - { - return isset($this->value->$key); - } + public function __isset($key) + { + return isset($this->value->{$key}); + } - public function __unset($key) - { - unset($this->value->$key); - } + public function __unset($key) + { + unset($this->value->{$key}); + } - /** - * Returns the embedded value. - * - * @return mixed The embedded value - */ - public function getValue() - { - return $this->value; - } + /** + * Returns the embedded value. + * + * @return mixed The embedded value + */ + public function getValue() + { + return $this->value; + } } diff --git a/lib/event/sfEvent.class.php b/lib/event/sfEvent.class.php index 67415e7ee..18863be1d 100644 --- a/lib/event/sfEvent.class.php +++ b/lib/event/sfEvent.class.php @@ -11,156 +11,151 @@ /** * sfEvent. * - * @package symfony - * @subpackage event * @author Fabien Potencier - * @version SVN: $Id: sfEvent.class.php 8698 2008-04-30 16:35:28Z fabien $ */ class sfEvent implements ArrayAccess { - protected - $value = null, - $processed = false, - $subject = null, - $name = '', - $parameters = null; - - /** - * Constructs a new sfEvent. - * - * @param mixed $subject The subject - * @param string $name The event name - * @param array $parameters An array of parameters - */ - public function __construct($subject, $name, $parameters = array()) - { - $this->subject = $subject; - $this->name = $name; - - $this->parameters = $parameters; - } - - /** - * Returns the subject. - * - * @return mixed The subject - */ - public function getSubject() - { - return $this->subject; - } - - /** - * Returns the event name. - * - * @return string The event name - */ - public function getName() - { - return $this->name; - } - - /** - * Sets the return value for this event. - * - * @param mixed $value The return value - */ - public function setReturnValue($value) - { - $this->value = $value; - } - - /** - * Returns the return value. - * - * @return mixed The return value - */ - public function getReturnValue() - { - return $this->value; - } - - /** - * Sets the processed flag. - * - * @param bool $processed The processed flag value - */ - public function setProcessed($processed) - { - $this->processed = (boolean) $processed; - } - - /** - * Returns whether the event has been processed by a listener or not. - * - * @return Boolean true if the event has been processed, false otherwise - */ - public function isProcessed() - { - return $this->processed; - } - - /** - * Returns the event parameters. - * - * @return array The event parameters - */ - public function getParameters() - { - return $this->parameters; - } - - /** - * Returns true if the parameter exists (implements the ArrayAccess interface). - * - * @param string $name The parameter name - * - * @return Boolean true if the parameter exists, false otherwise - */ - #[\ReturnTypeWillChange] - public function offsetExists($name) - { - return array_key_exists($name, $this->parameters); - } - - /** - * Returns a parameter value (implements the ArrayAccess interface). - * - * @param string $name The parameter name - * - * @return mixed The parameter value - */ - #[\ReturnTypeWillChange] - public function offsetGet($name) - { - if (!array_key_exists($name, $this->parameters)) + protected $value; + protected $processed = false; + protected $subject; + protected $name = ''; + protected $parameters; + + /** + * Constructs a new sfEvent. + * + * @param mixed $subject The subject + * @param string $name The event name + * @param array $parameters An array of parameters + */ + public function __construct($subject, $name, $parameters = []) { - throw new InvalidArgumentException(sprintf('The event "%s" has no "%s" parameter.', $this->name, $name)); + $this->subject = $subject; + $this->name = $name; + + $this->parameters = $parameters; + } + + /** + * Returns the subject. + * + * @return mixed The subject + */ + public function getSubject() + { + return $this->subject; + } + + /** + * Returns the event name. + * + * @return string The event name + */ + public function getName() + { + return $this->name; + } + + /** + * Sets the return value for this event. + * + * @param mixed $value The return value + */ + public function setReturnValue($value) + { + $this->value = $value; + } + + /** + * Returns the return value. + * + * @return mixed The return value + */ + public function getReturnValue() + { + return $this->value; + } + + /** + * Sets the processed flag. + * + * @param bool $processed The processed flag value + */ + public function setProcessed($processed) + { + $this->processed = (bool) $processed; + } + + /** + * Returns whether the event has been processed by a listener or not. + * + * @return bool true if the event has been processed, false otherwise + */ + public function isProcessed() + { + return $this->processed; + } + + /** + * Returns the event parameters. + * + * @return array The event parameters + */ + public function getParameters() + { + return $this->parameters; } - return $this->parameters[$name]; - } - - /** - * Sets a parameter (implements the ArrayAccess interface). - * - * @param string $name The parameter name - * @param mixed $value The parameter value - */ - #[\ReturnTypeWillChange] - public function offsetSet($name, $value) - { - $this->parameters[$name] = $value; - } - - /** - * Removes a parameter (implements the ArrayAccess interface). - * - * @param string $name The parameter name - */ - #[\ReturnTypeWillChange] - public function offsetUnset($name) - { - unset($this->parameters[$name]); - } + /** + * Returns true if the parameter exists (implements the ArrayAccess interface). + * + * @param string $name The parameter name + * + * @return bool true if the parameter exists, false otherwise + */ + #[ReturnTypeWillChange] + public function offsetExists($name) + { + return array_key_exists($name, $this->parameters); + } + + /** + * Returns a parameter value (implements the ArrayAccess interface). + * + * @param string $name The parameter name + * + * @return mixed The parameter value + */ + #[ReturnTypeWillChange] + public function offsetGet($name) + { + if (!array_key_exists($name, $this->parameters)) { + throw new InvalidArgumentException(sprintf('The event "%s" has no "%s" parameter.', $this->name, $name)); + } + + return $this->parameters[$name]; + } + + /** + * Sets a parameter (implements the ArrayAccess interface). + * + * @param string $name The parameter name + * @param mixed $value The parameter value + */ + #[ReturnTypeWillChange] + public function offsetSet($name, $value) + { + $this->parameters[$name] = $value; + } + + /** + * Removes a parameter (implements the ArrayAccess interface). + * + * @param string $name The parameter name + */ + #[ReturnTypeWillChange] + public function offsetUnset($name) + { + unset($this->parameters[$name]); + } } diff --git a/lib/event/sfEventDispatcher.class.php b/lib/event/sfEventDispatcher.class.php index 1a4d38819..322322c8f 100644 --- a/lib/event/sfEventDispatcher.class.php +++ b/lib/event/sfEventDispatcher.class.php @@ -13,145 +13,132 @@ * * @see http://developer.apple.com/documentation/Cocoa/Conceptual/Notifications/index.html Apple's Cocoa framework * - * @package symfony - * @subpackage event * @author Fabien Potencier - * @version SVN: $Id: sfEventDispatcher.class.php 10631 2008-08-03 16:50:47Z fabien $ */ class sfEventDispatcher { - protected - $listeners = array(); - - /** - * Connects a listener to a given event name. - * - * @param string $name An event name - * @param mixed $listener A PHP callable - */ - public function connect($name, $listener) - { - if (!isset($this->listeners[$name])) + protected $listeners = []; + + /** + * Connects a listener to a given event name. + * + * @param string $name An event name + * @param mixed $listener A PHP callable + */ + public function connect($name, $listener) { - $this->listeners[$name] = array(); - } + if (!isset($this->listeners[$name])) { + $this->listeners[$name] = []; + } - $this->listeners[$name][] = $listener; - } - - /** - * Disconnects a listener for a given event name. - * - * @param string $name An event name - * @param mixed $listener A PHP callable - * - * @return mixed false if listener does not exist, null otherwise - */ - public function disconnect($name, $listener) - { - if (!isset($this->listeners[$name])) - { - return false; + $this->listeners[$name][] = $listener; } - foreach ($this->listeners[$name] as $i => $callable) + /** + * Disconnects a listener for a given event name. + * + * @param string $name An event name + * @param mixed $listener A PHP callable + * + * @return mixed false if listener does not exist, null otherwise + */ + public function disconnect($name, $listener) { - if ($listener === $callable) - { - unset($this->listeners[$name][$i]); - } + if (!isset($this->listeners[$name])) { + return false; + } + + foreach ($this->listeners[$name] as $i => $callable) { + if ($listener === $callable) { + unset($this->listeners[$name][$i]); + } + } } - } - - /** - * Notifies all listeners of a given event. - * - * @param sfEvent $event A sfEvent instance - * - * @return sfEvent The sfEvent instance - */ - public function notify(sfEvent $event) - { - foreach ($this->getListeners($event->getName()) as $listener) + + /** + * Notifies all listeners of a given event. + * + * @param sfEvent $event A sfEvent instance + * + * @return sfEvent The sfEvent instance + */ + public function notify(sfEvent $event) { - call_user_func($listener, $event); + foreach ($this->getListeners($event->getName()) as $listener) { + call_user_func($listener, $event); + } + + return $event; } - return $event; - } - - /** - * Notifies all listeners of a given event until one returns a non null value. - * - * @param sfEvent $event A sfEvent instance - * - * @return sfEvent The sfEvent instance - */ - public function notifyUntil(sfEvent $event) - { - foreach ($this->getListeners($event->getName()) as $listener) + /** + * Notifies all listeners of a given event until one returns a non null value. + * + * @param sfEvent $event A sfEvent instance + * + * @return sfEvent The sfEvent instance + */ + public function notifyUntil(sfEvent $event) { - if (call_user_func($listener, $event)) - { - $event->setProcessed(true); - break; - } + foreach ($this->getListeners($event->getName()) as $listener) { + if (call_user_func($listener, $event)) { + $event->setProcessed(true); + + break; + } + } + + return $event; } - return $event; - } - - /** - * Filters a value by calling all listeners of a given event. - * - * @param sfEvent $event A sfEvent instance - * @param mixed $value The value to be filtered - * - * @return sfEvent The sfEvent instance - */ - public function filter(sfEvent $event, $value) - { - foreach ($this->getListeners($event->getName()) as $listener) + /** + * Filters a value by calling all listeners of a given event. + * + * @param sfEvent $event A sfEvent instance + * @param mixed $value The value to be filtered + * + * @return sfEvent The sfEvent instance + */ + public function filter(sfEvent $event, $value) { - $value = call_user_func_array($listener, array($event, $value)); + foreach ($this->getListeners($event->getName()) as $listener) { + $value = call_user_func_array($listener, [$event, $value]); + } + + $event->setReturnValue($value); + + return $event; } - $event->setReturnValue($value); - - return $event; - } - - /** - * Returns true if the given event name has some listeners. - * - * @param string $name The event name - * - * @return Boolean true if some listeners are connected, false otherwise - */ - public function hasListeners($name) - { - if (!isset($this->listeners[$name])) + /** + * Returns true if the given event name has some listeners. + * + * @param string $name The event name + * + * @return bool true if some listeners are connected, false otherwise + */ + public function hasListeners($name) { - $this->listeners[$name] = array(); + if (!isset($this->listeners[$name])) { + $this->listeners[$name] = []; + } + + return (bool) count($this->listeners[$name]); } - return (boolean) count($this->listeners[$name]); - } - - /** - * Returns all listeners associated with a given event name. - * - * @param string $name The event name - * - * @return array An array of listeners - */ - public function getListeners($name) - { - if (!isset($this->listeners[$name])) + /** + * Returns all listeners associated with a given event name. + * + * @param string $name The event name + * + * @return array An array of listeners + */ + public function getListeners($name) { - return array(); - } + if (!isset($this->listeners[$name])) { + return []; + } - return $this->listeners[$name]; - } + return $this->listeners[$name]; + } } diff --git a/lib/exception/data/error.atom.php b/lib/exception/data/error.atom.php index 43cc506c3..7f2a14d27 100644 --- a/lib/exception/data/error.atom.php +++ b/lib/exception/data/error.atom.php @@ -1 +1,3 @@ - + + */ diff --git a/lib/exception/data/error.html.php b/lib/exception/data/error.html.php index 1ef93c050..a8c3acb9c 100644 --- a/lib/exception/data/error.html.php +++ b/lib/exception/data/error.html.php @@ -1,6 +1,6 @@ - + @@ -14,20 +14,20 @@ symfony project - +
    - +
    - page not found + page not found

    Oops! An Error Occurred

    -
    The server returned a " ".
    +
    The server returned a " ".
    diff --git a/lib/exception/data/error.js.php b/lib/exception/data/error.js.php index 9f4ae4d34..740604b51 100644 --- a/lib/exception/data/error.js.php +++ b/lib/exception/data/error.js.php @@ -1,3 +1,3 @@ /* - + */ diff --git a/lib/exception/data/error.json.php b/lib/exception/data/error.json.php index 7d2374bed..bf61b5288 100644 --- a/lib/exception/data/error.json.php +++ b/lib/exception/data/error.json.php @@ -1,5 +1,7 @@ - array( - 'code' => $code, - 'message' => $text, -))) ?> + [ + 'code' => $code, + 'message' => $text, + ]]); diff --git a/lib/exception/data/error.rdf.php b/lib/exception/data/error.rdf.php index 43cc506c3..7f2a14d27 100644 --- a/lib/exception/data/error.rdf.php +++ b/lib/exception/data/error.rdf.php @@ -1 +1,3 @@ - + ". +The server returned a " ". Please e-mail us at [email] and let us know what you were doing when this error occurred. We will fix it as soon as possible. Sorry for any diff --git a/lib/exception/data/error.xml.php b/lib/exception/data/error.xml.php index a039c5bc8..128a17b7e 100644 --- a/lib/exception/data/error.xml.php +++ b/lib/exception/data/error.xml.php @@ -1,2 +1,2 @@ -', sfConfig::get('sf_charset', 'UTF-8'))."\n" ?> - +', sfConfig::get('sf_charset', 'UTF-8'))."\n"; ?> + diff --git a/lib/exception/data/exception.atom.php b/lib/exception/data/exception.atom.php index 35e80548c..503c53f19 100644 --- a/lib/exception/data/exception.atom.php +++ b/lib/exception/data/exception.atom.php @@ -1 +1,3 @@ - + + - - + + - - - + + + */ diff --git a/lib/exception/data/exception.html.php b/lib/exception/data/exception.html.php index 029b82b52..8e47ef618 100644 --- a/lib/exception/data/exception.html.php +++ b/lib/exception/data/exception.html.php @@ -2,7 +2,7 @@ - <?php echo $name ?>: <?php echo htmlspecialchars($message, ENT_QUOTES, sfConfig::get('sf_charset', 'UTF-8')) ?> + <?php echo $name; ?>: <?php echo htmlspecialchars($message, ENT_QUOTES, sfConfig::get('sf_charset', 'UTF-8')); ?>