From e8cbc9d3cccda68220b0f46a1322cc8ddf656320 Mon Sep 17 00:00:00 2001 From: Alexandre Quercia Date: Sat, 11 Sep 2021 03:17:09 +0200 Subject: [PATCH 01/43] 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 --- .docker/php53/Dockerfile | 57 ++++++++ .docker/php54/Dockerfile | 34 +++++ .docker/php55_71/Dockerfile | 40 ++++++ .docker/php72_73/Dockerfile | 56 ++++++++ .docker/php74_81/Dockerfile | 68 +++++++++ .env.dist | 11 ++ README.md | 31 +++++ docker-compose.yml | 176 ++++++++++++++++++++++++ test/bin/test | 89 ++++++++++++ test/unit/cache/sfMemcacheCacheTest.php | 10 +- 10 files changed, 571 insertions(+), 1 deletion(-) create mode 100644 .docker/php53/Dockerfile create mode 100644 .docker/php54/Dockerfile create mode 100644 .docker/php55_71/Dockerfile create mode 100644 .docker/php72_73/Dockerfile create mode 100644 .docker/php74_81/Dockerfile create mode 100644 .env.dist create mode 100644 docker-compose.yml create mode 100755 test/bin/test diff --git a/.docker/php53/Dockerfile b/.docker/php53/Dockerfile new file mode 100644 index 000000000..99ca06bf0 --- /dev/null +++ b/.docker/php53/Dockerfile @@ -0,0 +1,57 @@ +FROM buildpack-deps:jessie + +ENV PHP_VERSION 5.3.29 + +# php 5.3 needs older autoconf +RUN set -eux; \ + \ + apt-get update; \ + apt-get install -y \ + curl \ + autoconf2.13 \ + ; \ + rm -r /var/lib/apt/lists/*; \ + \ + curl -sSLfO http://launchpadlibrarian.net/140087283/libbison-dev_2.7.1.dfsg-1_amd64.deb; \ + curl -sSLfO http://launchpadlibrarian.net/140087282/bison_2.7.1.dfsg-1_amd64.deb; \ + dpkg -i libbison-dev_2.7.1.dfsg-1_amd64.deb; \ + dpkg -i bison_2.7.1.dfsg-1_amd64.deb; \ + rm *.deb; \ + \ + curl -sSLf "https://php.net/get/php-$PHP_VERSION.tar.bz2/from/this/mirror" -o php.tar.bz2; \ + echo 'c4e1cf6972b2a9c7f2777a18497d83bf713cdbecabb65d3ff62ba441aebb0091 php.tar.bz2' | sha256sum -cw --status; \ + \ + mkdir -p /usr/src/php; \ + tar -xf php.tar.bz2 -C /usr/src/php --strip-components=1; \ + rm php.tar.bz2*; \ + \ + cd /usr/src/php; \ + ./buildconf --force; \ + ./configure --disable-cgi \ + $(command -v apxs2 > /dev/null 2>&1 && echo '--with-apxs2' || true) \ + --with-pdo-mysql \ + --with-zlib \ + --enable-mbstring \ + ; \ + make -j"$(nproc)"; \ + make install; \ + \ + dpkg -r \ + bison \ + libbison-dev \ + ; \ + apt-get purge -y --auto-remove \ + autoconf2.13 \ + ; \ + rm -r /usr/src/php + +# Install APC PHP extension +# +RUN set -eux; \ + \ + pecl install apc-3.1.13; \ + echo 'extension=apc.so' >> /usr/local/lib/php.ini; \ + \ + rm -r /tmp/pear; + +CMD ["php", "-a"] diff --git a/.docker/php54/Dockerfile b/.docker/php54/Dockerfile new file mode 100644 index 000000000..ef5acfd0e --- /dev/null +++ b/.docker/php54/Dockerfile @@ -0,0 +1,34 @@ +FROM php:5.4-cli + +RUN docker-php-ext-install pdo +RUN docker-php-ext-install pdo_mysql +RUN docker-php-ext-install mbstring + +# Install APC PHP extension +# +RUN set -eux; \ + pecl install apc-3.1.13; \ + docker-php-ext-enable apc; \ + 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 diff --git a/.docker/php55_71/Dockerfile b/.docker/php55_71/Dockerfile new file mode 100644 index 000000000..1aa2171a3 --- /dev/null +++ b/.docker/php55_71/Dockerfile @@ -0,0 +1,40 @@ +ARG PHP_TAG +FROM php:${PHP_TAG} + +RUN docker-php-ext-install pdo +RUN docker-php-ext-install pdo_mysql +RUN 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 diff --git a/.docker/php72_73/Dockerfile b/.docker/php72_73/Dockerfile new file mode 100644 index 000000000..69353468b --- /dev/null +++ b/.docker/php72_73/Dockerfile @@ -0,0 +1,56 @@ +ARG PHP_VERSION +FROM php:${PHP_VERSION}-cli + +RUN docker-php-ext-install pdo +RUN docker-php-ext-install pdo_mysql +RUN 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/.docker/php74_81/Dockerfile b/.docker/php74_81/Dockerfile new file mode 100644 index 000000000..a9d410dbf --- /dev/null +++ b/.docker/php74_81/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/.env.dist b/.env.dist new file mode 100644 index 000000000..14b756ef5 --- /dev/null +++ b/.env.dist @@ -0,0 +1,11 @@ +# +# Environment variables used by docker-compose for test. +# +# Copy to `.env` in order to use it. +# + +# APC test are disabled. +# +# To enable them in order to provide a fix, set to "on". +# +APC_ENABLE_CLI=off diff --git a/README.md b/README.md index 38d65cc4b..900179110 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,37 @@ Option 2: Using Git submodules: 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 ------------- diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..b18e91032 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,176 @@ +version: '3.5' + +volumes: + db_socket: + +services: + composer: + image: composer + working_dir: /app + volumes: + - .:/app + entrypoint: + - sh + - -c + - | + exec tail -f /dev/null + + php53: + build: .docker/php53 + 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 = ${APC_ENABLE_CLI-off}' + echo 'apc.use_request_time = 0' + } | tee -a /usr/local/lib/php.ini + + exec tail -f /dev/null + depends_on: + - db + + php54: &services_php54 + build: + context: .docker/php54 + args: + MEMCACHE_VERSION: '3.0.8' + 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 = ${APC_ENABLE_CLI-off}' + echo 'apc.use_request_time = 0' + } | tee -a /usr/local/etc/php/php.ini + + exec tail -f /dev/null + depends_on: + - db + - memcached + + php55: + <<: *services_php54 + build: + context: .docker/php55_71 + args: + PHP_TAG: '5.5-cli' + MEMCACHE_VERSION: '3.0.8' + APCU_VERSION: '4.0.11' + + php56: + <<: *services_php54 + build: + context: .docker/php55_71 + args: + PHP_TAG: '5.6-cli-jessie' + MEMCACHE_VERSION: '3.0.8' + APCU_VERSION: '4.0.11' + + php70: + <<: *services_php54 + build: + context: .docker/php55_71 + args: + PHP_TAG: '7.0-cli-jessie' + MEMCACHE_VERSION: '4.0.5.2' + APCU_VERSION: '' + + php71: + <<: *services_php54 + build: + context: .docker/php55_71 + args: + PHP_TAG: '7.1-cli-jessie' + MEMCACHE_VERSION: '4.0.5.2' + APCU_VERSION: '' + + + php72: + <<: *services_php54 + build: + context: .docker/php72_73 + args: + PHP_VERSION: '7.2' + MEMCACHE_VERSION: '4.0.5.2' + APCU_VERSION: '' + + + php73: + <<: *services_php54 + build: + context: .docker/php72_73 + args: + PHP_VERSION: '7.3' + MEMCACHE_VERSION: '4.0.5.2' + APCU_VERSION: '' + + + php74: + <<: *services_php54 + build: + context: .docker/php74_81 + args: + PHP_VERSION: '7.4' + MEMCACHE_VERSION: '4.0.5.2' + APCU_VERSION: '' + + + php80: + <<: *services_php54 + build: + context: .docker/php74_81 + args: + PHP_VERSION: '8.0' + MEMCACHE_VERSION: '8.0' + APCU_VERSION: '' + + + php81: + <<: *services_php54 + build: + context: .docker/php74_81 + args: + PHP_VERSION: '8.1' + MEMCACHE_VERSION: '8.0' + APCU_VERSION: '' + + + 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/test/bin/test b/test/bin/test new file mode 100755 index 000000000..5305c0541 --- /dev/null +++ b/test/bin/test @@ -0,0 +1,89 @@ +#! /bin/sh -eu +# +# [] [] [] +# +# example: php70 +# One of highest (default), lowest +# +# Both arguments can be a space separated value. +# Example: "lowest highest" +# + +# Configuration +# +dependencyPreferences='highest' +skipPHPVersions='php8' + +# Commands +# +dcexec="docker-compose exec -u `id -u`:`id -g`" +installSubmodule='git submodule update --checkout --recursive --force' +composerUpdate='composer update --prefer-dist --no-suggest --optimize-autoloader' +symfonyTestSuite='data/bin/symfony symfony:test --trace' + +# Parse arguments +# +phpVersions="${1-}" +dependencyPreferences="${2-${dependencyPreferences}}" +phpTestRuntime="${3-${symfonyTestSuite}}" + +script () +{ + echo + echo + echo $0 ${1} ${2} + echo + ${dcexec} ${1} php data/bin/check_configuration.php + ${dcexec} ${1} php ${phpTestRuntime} +} + +scriptAll () +{ + for dependencyPreference in ${dependencyPreferences} + do + install_${dependencyPreference} + + for phpVersion in ${phpVersions} + do + script ${phpVersion} ${dependencyPreference} + done + done +} + +fetchAllPHPVersions () +{ + docker-compose 2>/dev/null ps --services --filter status=running \ + | grep php \ + | sort \ + | grep -v ${skipPHPVersions} +} + +install_highest () +{ + ${installSubmodule} --remote + ${dcexec} composer ${composerUpdate} +} + +install_lowest () +{ + reset_submodules + + ${installSubmodule} + ${dcexec} composer ${composerUpdate} --prefer-lowest +} + +reset_submodules () +{ + git submodule deinit --force --quiet -- . + + git submodule init +} + +echo '+ docker-compose build' +docker-compose up -d --build --remove-orphans > /dev/null + +test x"" != x"${phpVersions}" || { + phpVersions=`fetchAllPHPVersions` +} + +scriptAll diff --git a/test/unit/cache/sfMemcacheCacheTest.php b/test/unit/cache/sfMemcacheCacheTest.php index 7de822f0d..ceba9b39e 100644 --- a/test/unit/cache/sfMemcacheCacheTest.php +++ b/test/unit/cache/sfMemcacheCacheTest.php @@ -28,7 +28,15 @@ $t->diag('->initialize()'); try { - $cache = new sfMemcacheCache(array('storeCacheInfo' => true)); + $memcachedHost = getenv('MEMCACHED_HOST'); + if (!$memcachedHost) { + $memcachedHost = null; + } + + $cache = new sfMemcacheCache(array( + 'storeCacheInfo' => true, + 'host' => $memcachedHost, + )); } catch (sfInitializationException $e) { From 32b2a4b5f1f90cf6d4a6d6489f18299b01dce22c Mon Sep 17 00:00:00 2001 From: thePanz Date: Fri, 25 Nov 2022 11:19:20 +0100 Subject: [PATCH 02/43] Use GitHub actions for Continuous Integration tests Remove TravisCI integration --- .github/workflows/continuous-integration.yml | 44 ++++++++++++++++++ .travis.yml | 46 ------------------- .../sfDoctrinePlugin/lib/vendor/doctrine | 2 +- lib/vendor/swiftmailer | 2 +- 4 files changed, 46 insertions(+), 48 deletions(-) create mode 100644 .github/workflows/continuous-integration.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 000000000..13d1bdfa7 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,44 @@ +name: "Continuous Integration" + +on: [push] + +env: + fail-fast: true + +jobs: + tests: + name: "Symfony1 Tests" + runs-on: "ubuntu-22.04" + + strategy: + matrix: + php-version: + - "7.4" + # - "8.0" + # - "8.1" + memcached-version: + - "1.6" + + services: + memcached: + image: "memcached:${{ matrix.memcached-version }}" + + steps: + - name: "Checkout" + uses: "actions/checkout@v3" + with: + submodules: "true" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "${{ matrix.php-version }}" + + - name: "Install dependencies with Composer" + uses: "ramsey/composer-install@v2" + + - 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/.travis.yml b/.travis.yml deleted file mode 100644 index c163be702..000000000 --- a/.travis.yml +++ /dev/null @@ -1,46 +0,0 @@ -os: linux -dist: xenial -language: php - -php: - - 7.0 - - 7.1 - - 7.2 - - 7.3 - - 7.4 - - nightly - -# run build against nightly but allow them to fail -jobs: - fast_finish: true - allow_failures: - - php: nightly - include: - - php: 5.3 - dist: precise - - php: 5.4 - dist: precise - - php: 5.5 - dist: trusty - - php: 5.6 - dist: trusty - -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 - -script: - - php data/bin/check_configuration.php - - php data/bin/symfony symfony:test --trace diff --git a/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine b/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine index 0564971b2..f8ea8b76c 160000 --- a/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine +++ b/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine @@ -1 +1 @@ -Subproject commit 0564971b2badd778914ac0fcb74518a00d6918f1 +Subproject commit f8ea8b76cb3f932a4a21aa146c0ebc27939ccc04 diff --git a/lib/vendor/swiftmailer b/lib/vendor/swiftmailer index 4cc928420..181b89f18 160000 --- a/lib/vendor/swiftmailer +++ b/lib/vendor/swiftmailer @@ -1 +1 @@ -Subproject commit 4cc92842069c2bbc1f28daaaf1d2576ec4dfe153 +Subproject commit 181b89f18a90f8925ef805f950d47a7190e9b950 From 21b73811eed017564c87258c5538841673be653c Mon Sep 17 00:00:00 2001 From: thePanz Date: Fri, 25 Nov 2022 15:34:45 +0100 Subject: [PATCH 03/43] Fix test for /bin/ls file mimetype guessing, using application/x-pie-executable --- test/unit/validator/sfValidatorFileTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/validator/sfValidatorFileTest.php b/test/unit/validator/sfValidatorFileTest.php index 43412cffc..42463acfa 100755 --- a/test/unit/validator/sfValidatorFileTest.php +++ b/test/unit/validator/sfValidatorFileTest.php @@ -105,7 +105,7 @@ public function getMimeTypesFromCategory($category) $v = new testValidatorFile(); $t->is($v->guessFromFileBinary($tmpDir.'/test.txt'), 'text/plain', '->guessFromFileBinary() guesses the type of a given file'); $t->is($v->guessFromFileBinary($tmpDir.'/foo.txt'), null, '->guessFromFileBinary() returns null if the file type is not guessable'); -$t->is($v->guessFromFileBinary('/bin/ls'), (PHP_OS != 'Darwin') ? 'application/x-executable' : 'application/octet-stream', '->guessFromFileBinary() returns correct type if file is guessable'); +$t->is($v->guessFromFileBinary('/bin/ls'), (PHP_OS != 'Darwin') ? 'application/x-pie-executable' : 'application/octet-stream', '->guessFromFileBinary() returns correct type if file is guessable'); $t->is($v->guessFromFileBinary('-test'), null, '->guessFromFileBinary() returns null if file path has leading dash'); // ->getMimeType() From 245c7cce0d705d97fbe2b0209474d8a18920c859 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 19 May 2022 15:52:46 +0200 Subject: [PATCH 04/43] 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. --- lib/addon/sfPager.class.php | 6 ++++++ lib/escaper/sfOutputEscaperArrayDecorator.class.php | 10 ++++++++++ lib/escaper/sfOutputEscaperIteratorDecorator.class.php | 9 +++++++++ lib/escaper/sfOutputEscaperObjectDecorator.class.php | 1 + lib/event/sfEvent.class.php | 6 +++++- lib/form/sfForm.class.php | 10 ++++++++++ lib/form/sfFormFieldSchema.class.php | 10 ++++++++++ .../lib/generator/sfDoctrineColumn.class.php | 6 +++++- lib/request/sfRequest.class.php | 4 ++++ lib/routing/sfRouteCollection.class.php | 5 +++++ lib/user/sfUser.class.php | 4 ++++ lib/util/sfContext.class.php | 4 ++++ lib/util/sfDomCssSelector.class.php | 6 ++++++ lib/validator/sfValidatorErrorSchema.class.php | 10 ++++++++++ lib/validator/sfValidatorSchema.class.php | 4 ++++ lib/widget/sfWidgetFormSchema.class.php | 4 ++++ lib/widget/sfWidgetFormSchemaDecorator.class.php | 4 ++++ .../escaper/sfOutputEscaperObjectDecoratorTest.php | 1 + 18 files changed, 102 insertions(+), 2 deletions(-) diff --git a/lib/addon/sfPager.class.php b/lib/addon/sfPager.class.php index 594b1417a..84a4cc5f1 100644 --- a/lib/addon/sfPager.class.php +++ b/lib/addon/sfPager.class.php @@ -529,6 +529,7 @@ protected function resetIterator() * * @see Iterator */ + #[\ReturnTypeWillChange] public function current() { if (!$this->isIteratorInitialized()) @@ -544,6 +545,7 @@ public function current() * * @see Iterator */ + #[\ReturnTypeWillChange] public function key() { if (!$this->isIteratorInitialized()) @@ -559,6 +561,7 @@ public function key() * * @see Iterator */ + #[\ReturnTypeWillChange] public function next() { if (!$this->isIteratorInitialized()) @@ -576,6 +579,7 @@ public function next() * * @see Iterator */ + #[\ReturnTypeWillChange] public function rewind() { if (!$this->isIteratorInitialized()) @@ -593,6 +597,7 @@ public function rewind() * * @see Iterator */ + #[\ReturnTypeWillChange] public function valid() { if (!$this->isIteratorInitialized()) @@ -608,6 +613,7 @@ public function valid() * * @see Countable */ + #[\ReturnTypeWillChange] public function count() { return $this->getNbResults(); diff --git a/lib/escaper/sfOutputEscaperArrayDecorator.class.php b/lib/escaper/sfOutputEscaperArrayDecorator.class.php index 0e6b0b0ae..6b87a4322 100644 --- a/lib/escaper/sfOutputEscaperArrayDecorator.class.php +++ b/lib/escaper/sfOutputEscaperArrayDecorator.class.php @@ -42,6 +42,7 @@ public function __construct($escapingMethod, $value) /** * Reset the array to the beginning (as required for the Iterator interface). */ + #[\ReturnTypeWillChange] public function rewind() { reset($this->value); @@ -54,6 +55,7 @@ public function rewind() * * @return string The key */ + #[\ReturnTypeWillChange] public function key() { return key($this->value); @@ -67,6 +69,7 @@ public function key() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return sfOutputEscaper::escape($this->escapingMethod, current($this->value)); @@ -75,6 +78,7 @@ public function current() /** * Moves to the next element (as required by the Iterator interface). */ + #[\ReturnTypeWillChange] public function next() { next($this->value); @@ -91,6 +95,7 @@ public function next() * * @return bool The validity of the current element; true if it is valid */ + #[\ReturnTypeWillChange] public function valid() { return $this->count > 0; @@ -103,6 +108,7 @@ public function valid() * * @return bool true if the offset isset; false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->value[$offset]); @@ -115,6 +121,7 @@ public function offsetExists($offset) * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return sfOutputEscaper::escape($this->escapingMethod, $this->value[$offset]); @@ -132,6 +139,7 @@ public function offsetGet($offset) * * @throws sfException */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new sfException('Cannot set values.'); @@ -148,6 +156,7 @@ public function offsetSet($offset, $value) * * @throws sfException */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { throw new sfException('Cannot unset values.'); @@ -158,6 +167,7 @@ public function offsetUnset($offset) * * @return int The size of the array */ + #[\ReturnTypeWillChange] public function count() { return count($this->value); diff --git a/lib/escaper/sfOutputEscaperIteratorDecorator.class.php b/lib/escaper/sfOutputEscaperIteratorDecorator.class.php index 7d9eca063..68ed43dfd 100644 --- a/lib/escaper/sfOutputEscaperIteratorDecorator.class.php +++ b/lib/escaper/sfOutputEscaperIteratorDecorator.class.php @@ -56,6 +56,7 @@ public function __construct($escapingMethod, Traversable $value) * * @return void */ + #[\ReturnTypeWillChange] public function rewind() { return $this->iterator->rewind(); @@ -66,6 +67,7 @@ public function rewind() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return sfOutputEscaper::escape($this->escapingMethod, $this->iterator->current()); @@ -76,6 +78,7 @@ public function current() * * @return string Iterator key */ + #[\ReturnTypeWillChange] public function key() { return $this->iterator->key(); @@ -86,6 +89,7 @@ public function key() * * @return void */ + #[\ReturnTypeWillChange] public function next() { return $this->iterator->next(); @@ -97,6 +101,7 @@ public function next() * * @return bool true if the current element is valid; false otherwise */ + #[\ReturnTypeWillChange] public function valid() { return $this->iterator->valid(); @@ -109,6 +114,7 @@ public function valid() * * @return bool true if the offset isset; false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->value[$offset]); @@ -121,6 +127,7 @@ public function offsetExists($offset) * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return sfOutputEscaper::escape($this->escapingMethod, $this->value[$offset]); @@ -138,6 +145,7 @@ public function offsetGet($offset) * * @throws sfException */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new sfException('Cannot set values.'); @@ -154,6 +162,7 @@ public function offsetSet($offset, $value) * * @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 89e70edcd..fe506d9c1 100644 --- a/lib/escaper/sfOutputEscaperObjectDecorator.class.php +++ b/lib/escaper/sfOutputEscaperObjectDecorator.class.php @@ -115,6 +115,7 @@ public function __isset($key) * * @return int The size of the object */ + #[\ReturnTypeWillChange] public function count() { return count($this->value); diff --git a/lib/event/sfEvent.class.php b/lib/event/sfEvent.class.php index 0ffd44281..750b28023 100644 --- a/lib/event/sfEvent.class.php +++ b/lib/event/sfEvent.class.php @@ -83,7 +83,7 @@ public function getReturnValue() /** * Sets the processed flag. * - * @param Boolean $processed The processed flag value + * @param boolean $processed The processed flag value */ public function setProcessed($processed) { @@ -117,6 +117,7 @@ public function getParameters() * * @return Boolean true if the parameter exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return array_key_exists($name, $this->parameters); @@ -129,6 +130,7 @@ public function offsetExists($name) * * @return mixed The parameter value */ + #[\ReturnTypeWillChange] public function offsetGet($name) { if (!array_key_exists($name, $this->parameters)) @@ -145,6 +147,7 @@ public function offsetGet($name) * @param string $name The parameter name * @param mixed $value The parameter value */ + #[\ReturnTypeWillChange] public function offsetSet($name, $value) { $this->parameters[$name] = $value; @@ -155,6 +158,7 @@ public function offsetSet($name, $value) * * @param string $name The parameter name */ + #[\ReturnTypeWillChange] public function offsetUnset($name) { unset($this->parameters[$name]); diff --git a/lib/form/sfForm.class.php b/lib/form/sfForm.class.php index db46c4d82..2db45bbde 100644 --- a/lib/form/sfForm.class.php +++ b/lib/form/sfForm.class.php @@ -1064,6 +1064,7 @@ public function resetFormFields() * * @return Boolean true if the widget exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->widgetSchema[$name]); @@ -1076,6 +1077,7 @@ public function offsetExists($name) * * @return sfFormField|sfFormFieldSchema A form field instance */ + #[\ReturnTypeWillChange] public function offsetGet($name) { if (!isset($this->formFields[$name])) @@ -1114,6 +1116,7 @@ public function offsetGet($name) * * @throws LogicException */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new LogicException('Cannot update form fields.'); @@ -1126,6 +1129,7 @@ public function offsetSet($offset, $value) * * @param string $offset The field name */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { unset( @@ -1227,6 +1231,7 @@ public function getErrors() /** * Resets the field names array to the beginning (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function rewind() { $this->fieldNames = $this->widgetSchema->getPositions(); @@ -1240,6 +1245,7 @@ public function rewind() * * @return string The key */ + #[\ReturnTypeWillChange] public function key() { return current($this->fieldNames); @@ -1250,6 +1256,7 @@ public function key() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return $this[current($this->fieldNames)]; @@ -1258,6 +1265,7 @@ public function current() /** * Moves to the next form field (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function next() { next($this->fieldNames); @@ -1269,6 +1277,7 @@ public function next() * * @return boolean The validity of the current element; true if it is valid */ + #[\ReturnTypeWillChange] public function valid() { return $this->count > 0; @@ -1279,6 +1288,7 @@ public function valid() * * @return integer The number of embedded form fields */ + #[\ReturnTypeWillChange] public function count() { return count($this->getFormFieldSchema()); diff --git a/lib/form/sfFormFieldSchema.class.php b/lib/form/sfFormFieldSchema.class.php index 520058dfe..2e9407ad5 100644 --- a/lib/form/sfFormFieldSchema.class.php +++ b/lib/form/sfFormFieldSchema.class.php @@ -91,6 +91,7 @@ public function getHiddenFields($recursive = true) * * @return Boolean true if the widget exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->widget[$name]); @@ -103,6 +104,7 @@ public function offsetExists($name) * * @return sfFormField A form field instance */ + #[\ReturnTypeWillChange] public function offsetGet($name) { if (!isset($this->fields[$name])) @@ -144,6 +146,7 @@ public function offsetGet($name) * * @throws LogicException */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new LogicException('Cannot update form fields (read-only).'); @@ -156,6 +159,7 @@ public function offsetSet($offset, $value) * * @throws LogicException */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { throw new LogicException('Cannot remove form fields (read-only).'); @@ -164,6 +168,7 @@ public function offsetUnset($offset) /** * Resets the field names array to the beginning (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function rewind() { reset($this->fieldNames); @@ -175,6 +180,7 @@ public function rewind() * * @return string The key */ + #[\ReturnTypeWillChange] public function key() { return current($this->fieldNames); @@ -185,6 +191,7 @@ public function key() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return $this[current($this->fieldNames)]; @@ -193,6 +200,7 @@ public function current() /** * Moves to the next form field (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function next() { next($this->fieldNames); @@ -204,6 +212,7 @@ public function next() * * @return boolean The validity of the current element; true if it is valid */ + #[\ReturnTypeWillChange] public function valid() { return $this->count > 0; @@ -214,6 +223,7 @@ public function valid() * * @return integer The number of embedded form fields */ + #[\ReturnTypeWillChange] public function count() { return count($this->fieldNames); diff --git a/lib/plugins/sfDoctrinePlugin/lib/generator/sfDoctrineColumn.class.php b/lib/plugins/sfDoctrinePlugin/lib/generator/sfDoctrineColumn.class.php index 6611f26a3..f693ebb55 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/generator/sfDoctrineColumn.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/generator/sfDoctrineColumn.class.php @@ -349,23 +349,27 @@ public function getTable() return $this->table; } + #[\ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->definition[$offset]); } + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->definition[$offset] = $value; } + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->definition[$offset]; } + #[\ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->definition[$offset]); } -} \ No newline at end of file +} diff --git a/lib/request/sfRequest.class.php b/lib/request/sfRequest.class.php index b7249728b..ac6928e20 100644 --- a/lib/request/sfRequest.class.php +++ b/lib/request/sfRequest.class.php @@ -173,6 +173,7 @@ public function setMethod($method) * * @return bool true if the request parameter exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return $this->hasParameter($name); @@ -185,6 +186,7 @@ public function offsetExists($name) * * @return mixed The request parameter if exists, null otherwise */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return $this->getParameter($name, false); @@ -196,6 +198,7 @@ public function offsetGet($name) * @param string $offset The parameter name * @param string $value The parameter value */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->setParameter($offset, $value); @@ -206,6 +209,7 @@ public function offsetSet($offset, $value) * * @param string $offset The parameter name */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { $this->getParameterHolder()->remove($offset); diff --git a/lib/routing/sfRouteCollection.class.php b/lib/routing/sfRouteCollection.class.php index ee0117185..f95d2dbbb 100644 --- a/lib/routing/sfRouteCollection.class.php +++ b/lib/routing/sfRouteCollection.class.php @@ -61,6 +61,7 @@ public function getOptions() /** * Reset the error array to the beginning (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function rewind() { reset($this->routes); @@ -73,6 +74,7 @@ public function rewind() * * @return string The key */ + #[\ReturnTypeWillChange] public function key() { return key($this->routes); @@ -83,6 +85,7 @@ public function key() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return current($this->routes); @@ -91,6 +94,7 @@ public function current() /** * Moves to the next route (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function next() { next($this->routes); @@ -103,6 +107,7 @@ public function next() * * @return boolean The validity of the current route; true if it is valid */ + #[\ReturnTypeWillChange] public function valid() { return $this->count > 0; diff --git a/lib/user/sfUser.class.php b/lib/user/sfUser.class.php index 2b65fa065..47d122a20 100644 --- a/lib/user/sfUser.class.php +++ b/lib/user/sfUser.class.php @@ -227,6 +227,7 @@ public function getCulture() * * @return Boolean true if the user attribute exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return $this->hasAttribute($name); @@ -239,6 +240,7 @@ public function offsetExists($name) * * @return mixed The user attribute if exists, null otherwise */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return $this->getAttribute($name, false); @@ -250,6 +252,7 @@ public function offsetGet($name) * @param string $offset The parameter name * @param string $value The parameter value */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->setAttribute($offset, $value); @@ -260,6 +263,7 @@ public function offsetSet($offset, $value) * * @param string $offset The parameter name */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { $this->getAttributeHolder()->remove($offset); diff --git a/lib/util/sfContext.class.php b/lib/util/sfContext.class.php index 439cbf5a6..b0128afc7 100644 --- a/lib/util/sfContext.class.php +++ b/lib/util/sfContext.class.php @@ -508,6 +508,7 @@ public function getConfigCache() * * @return Boolean true if the context object exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return $this->has($name); @@ -520,6 +521,7 @@ public function offsetExists($name) * * @return mixed The context object if exists, null otherwise */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return $this->get($name); @@ -531,6 +533,7 @@ public function offsetGet($name) * @param string $offset Service name * @param mixed $value Service */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->set($offset, $value); @@ -541,6 +544,7 @@ public function offsetSet($offset, $value) * * @param string $offset The parameter name */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->factories[$offset]); diff --git a/lib/util/sfDomCssSelector.class.php b/lib/util/sfDomCssSelector.class.php index 8a6d2362f..a207f4e75 100644 --- a/lib/util/sfDomCssSelector.class.php +++ b/lib/util/sfDomCssSelector.class.php @@ -563,6 +563,7 @@ protected function nth($cur, $result = 1, $dir = 'nextSibling') /** * Reset the array to the beginning (as required for the Iterator interface). */ + #[\ReturnTypeWillChange] public function rewind() { reset($this->nodes); @@ -575,6 +576,7 @@ public function rewind() * * @return string The key */ + #[\ReturnTypeWillChange] public function key() { return key($this->nodes); @@ -585,6 +587,7 @@ public function key() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return current($this->nodes); @@ -593,6 +596,7 @@ public function current() /** * Moves to the next element (as required by the Iterator interface). */ + #[\ReturnTypeWillChange] public function next() { next($this->nodes); @@ -609,6 +613,7 @@ public function next() * * @return bool The validity of the current element; true if it is valid */ + #[\ReturnTypeWillChange] public function valid() { return $this->count > 0; @@ -619,6 +624,7 @@ public function valid() * * @param integer The number of matching nodes */ + #[\ReturnTypeWillChange] public function count() { return count($this->nodes); diff --git a/lib/validator/sfValidatorErrorSchema.class.php b/lib/validator/sfValidatorErrorSchema.class.php index d722102ac..f0175d226 100644 --- a/lib/validator/sfValidatorErrorSchema.class.php +++ b/lib/validator/sfValidatorErrorSchema.class.php @@ -176,6 +176,7 @@ public function getMessageFormat() * * @return int The number of array */ + #[\ReturnTypeWillChange] public function count() { return count($this->errors); @@ -184,6 +185,7 @@ public function count() /** * Reset the error array to the beginning (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function rewind() { reset($this->errors); @@ -196,6 +198,7 @@ public function rewind() * * @return string The key */ + #[\ReturnTypeWillChange] public function key() { return key($this->errors); @@ -206,6 +209,7 @@ public function key() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return current($this->errors); @@ -214,6 +218,7 @@ public function current() /** * Moves to the next error (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function next() { next($this->errors); @@ -226,6 +231,7 @@ public function next() * * @return boolean The validity of the current element; true if it is valid */ + #[\ReturnTypeWillChange] public function valid() { return $this->count > 0; @@ -238,6 +244,7 @@ public function valid() * * @return bool true if the error exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->errors[$name]); @@ -250,6 +257,7 @@ public function offsetExists($name) * * @return sfValidatorError A sfValidatorError instance */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return isset($this->errors[$name]) ? $this->errors[$name] : null; @@ -263,6 +271,7 @@ public function offsetGet($name) * * @throws LogicException */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new LogicException('Unable update an error.'); @@ -273,6 +282,7 @@ public function offsetSet($offset, $value) * * @param string $offset (ignored) */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { } diff --git a/lib/validator/sfValidatorSchema.class.php b/lib/validator/sfValidatorSchema.class.php index bbd215203..34c97180e 100644 --- a/lib/validator/sfValidatorSchema.class.php +++ b/lib/validator/sfValidatorSchema.class.php @@ -309,6 +309,7 @@ public function getPostValidator() * * @return bool true if the schema has a field with the given name, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->fields[$name]); @@ -321,6 +322,7 @@ public function offsetExists($name) * * @return sfValidatorBase The sfValidatorBase instance associated with the given name, null if it does not exist */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return isset($this->fields[$name]) ? $this->fields[$name] : null; @@ -332,6 +334,7 @@ public function offsetGet($name) * @param string $name The field name * @param sfValidatorBase $validator An sfValidatorBase instance */ + #[\ReturnTypeWillChange] public function offsetSet($name, $validator) { if (!$validator instanceof sfValidatorBase) @@ -347,6 +350,7 @@ public function offsetSet($name, $validator) * * @param string $name */ + #[\ReturnTypeWillChange] public function offsetUnset($name) { unset($this->fields[$name]); diff --git a/lib/widget/sfWidgetFormSchema.class.php b/lib/widget/sfWidgetFormSchema.class.php index acc3090d4..079db376f 100644 --- a/lib/widget/sfWidgetFormSchema.class.php +++ b/lib/widget/sfWidgetFormSchema.class.php @@ -659,6 +659,7 @@ public function generateName($name) * * @return bool true if the schema has a field with the given name, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->fields[$name]); @@ -671,6 +672,7 @@ public function offsetExists($name) * * @return sfWidget|null The sfWidget instance associated with the given name, null if it does not exist */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return isset($this->fields[$name]) ? $this->fields[$name] : null; @@ -684,6 +686,7 @@ public function offsetGet($name) * * @throws InvalidArgumentException when the field is not instance of sfWidget */ + #[\ReturnTypeWillChange] public function offsetSet($name, $widget) { if (!$widget instanceof sfWidget) @@ -710,6 +713,7 @@ public function offsetSet($name, $widget) * * @param string $name field name */ + #[\ReturnTypeWillChange] public function offsetUnset($name) { unset($this->fields[$name]); diff --git a/lib/widget/sfWidgetFormSchemaDecorator.class.php b/lib/widget/sfWidgetFormSchemaDecorator.class.php index c5d414068..5bc26bc5c 100644 --- a/lib/widget/sfWidgetFormSchemaDecorator.class.php +++ b/lib/widget/sfWidgetFormSchemaDecorator.class.php @@ -346,6 +346,7 @@ public function moveField($field, $action, $pivot = null) * @see sfWidgetFormSchema * @inheritdoc */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->widget[$name]); @@ -355,6 +356,7 @@ public function offsetExists($name) * @see sfWidgetFormSchema * @inheritdoc */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return $this->widget[$name]; @@ -364,6 +366,7 @@ public function offsetGet($name) * @see sfWidgetFormSchema * @inheritdoc */ + #[\ReturnTypeWillChange] public function offsetSet($name, $widget) { $this->widget[$name] = $widget; @@ -373,6 +376,7 @@ public function offsetSet($name, $widget) * @see sfWidgetFormSchema * @inheritdoc */ + #[\ReturnTypeWillChange] public function offsetUnset($name) { unset($this->widget[$name]); diff --git a/test/unit/escaper/sfOutputEscaperObjectDecoratorTest.php b/test/unit/escaper/sfOutputEscaperObjectDecoratorTest.php index 967bde98a..caff163b2 100644 --- a/test/unit/escaper/sfOutputEscaperObjectDecoratorTest.php +++ b/test/unit/escaper/sfOutputEscaperObjectDecoratorTest.php @@ -74,6 +74,7 @@ class Foo class FooCountable implements Countable { + #[\ReturnTypeWillChange] public function count() { return 2; From 6401fcc10f19b227af1227f1f3a808963558a968 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 19 May 2022 18:07:47 +0200 Subject: [PATCH 05/43] 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 --- .../lib/pager/sfDoctrinePager.class.php | 33 +++++++++++++++---- lib/response/sfResponse.class.php | 21 +++++++++++- lib/response/sfWebResponse.class.php | 22 +++++++++++-- lib/routing/sfRoute.class.php | 28 ++++++++++++++-- .../sfNamespacedParameterHolder.class.php | 29 +++++++++++++--- lib/util/sfParameterHolder.class.php | 28 +++++++++++++--- lib/validator/sfValidatorError.class.php | 29 ++++++++++++++-- lib/view/sfViewParameterHolder.class.php | 27 ++++++++++++--- test/unit/response/sfResponseTest.php | 4 ++- .../validator/sfValidatorErrorSchemaTest.php | 10 ++++++ test/unit/validator/sfValidatorErrorTest.php | 10 ++++++ 11 files changed, 212 insertions(+), 29 deletions(-) diff --git a/lib/plugins/sfDoctrinePlugin/lib/pager/sfDoctrinePager.class.php b/lib/plugins/sfDoctrinePlugin/lib/pager/sfDoctrinePager.class.php index 9592575f1..b63cd66c0 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/pager/sfDoctrinePager.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/pager/sfDoctrinePager.class.php @@ -52,9 +52,7 @@ public function setTableMethod($tableMethodName) */ public function serialize() { - $vars = get_object_vars($this); - unset($vars['query']); - return serialize($vars); + return serialize($this->__serialize()); } /** @@ -66,12 +64,35 @@ public function unserialize($serialized) { $array = unserialize($serialized); - foreach ($array as $name => $values) + return $this->__unserialize($array); + } + + /** + * Serializes the current instance for php 7.4+ + * + * @return array + */ + public function __serialize() + { + $vars = get_object_vars($this); + unset($vars['query']); + return $vars; + } + + /** + * Unserializes a sfDoctrinePager instance for php 7.4+ + * + * @param array $data + */ + public function __unserialize($data) + { + + foreach ($data as $name => $values) { - $this->$name = $values; + $this->$name = $values; } - $this->tableMethodCalled = false; + $this->tableMethodCalled = false; } /** diff --git a/lib/response/sfResponse.class.php b/lib/response/sfResponse.class.php index 0dac345cb..905d07996 100644 --- a/lib/response/sfResponse.class.php +++ b/lib/response/sfResponse.class.php @@ -152,7 +152,7 @@ public function __call($method, $arguments) /** * Serializes the current instance. * - * @return array Objects instance + * @return string Objects instance */ public function serialize() { @@ -171,4 +171,23 @@ public function unserialize($serialized) { $this->content = unserialize($serialized); } + + /** + * Serializes the current instance for php 7.4+ + * + * @return array + */ + public function __serialize() { + return array('content' => $this->content); + } + + /** + * Unserializes a sfResponse instance for php 7.4+ + * + * @param array $data + */ + public function __unserialize($data) + { + $this->content = $data['content']; + } } diff --git a/lib/response/sfWebResponse.class.php b/lib/response/sfWebResponse.class.php index 4a9a6585a..9f25c50f3 100644 --- a/lib/response/sfWebResponse.class.php +++ b/lib/response/sfWebResponse.class.php @@ -876,7 +876,7 @@ public function merge(sfWebResponse $response) */ public function serialize() { - return serialize(array($this->content, $this->statusCode, $this->statusText, $this->options, $this->headerOnly, $this->headers, $this->metas, $this->httpMetas, $this->stylesheets, $this->javascripts, $this->slots)); + return serialize($this->__serialize()); } /** @@ -885,7 +885,25 @@ public function serialize() */ public function unserialize($serialized) { - list($this->content, $this->statusCode, $this->statusText, $this->options, $this->headerOnly, $this->headers, $this->metas, $this->httpMetas, $this->stylesheets, $this->javascripts, $this->slots) = unserialize($serialized); + $this->__unserialize(unserialize($serialized)); + } + + /** + * @see sfResponse + * @return array + */ + public function __serialize() + { + return array($this->content, $this->statusCode, $this->statusText, $this->options, $this->headerOnly, $this->headers, $this->metas, $this->httpMetas, $this->stylesheets, $this->javascripts, $this->slots); + } + + /** + * @see sfResponse + * @param array $data + */ + public function __unserialize($data) + { + list($this->content, $this->statusCode, $this->statusText, $this->options, $this->headerOnly, $this->headers, $this->metas, $this->httpMetas, $this->stylesheets, $this->javascripts, $this->slots) = $data; } /** diff --git a/lib/routing/sfRoute.class.php b/lib/routing/sfRoute.class.php index 6887e4e24..5a0f0e508 100644 --- a/lib/routing/sfRoute.class.php +++ b/lib/routing/sfRoute.class.php @@ -847,15 +847,37 @@ protected function fixSuffix() public function serialize() { + return serialize($this->__serialize()); + } + + public function unserialize($serialized) + { + $array = unserialize($serialized); + + $this->__unserialize($array); + } + + /** + * Serializes the current instance for php 7.4+ + * + * @return array + */ + public function __serialize() { // always serialize compiled routes $this->compile(); // sfPatternRouting will always re-set defaultParameters, so no need to serialize them - return serialize(array($this->tokens, $this->defaultOptions, $this->options, $this->pattern, $this->staticPrefix, $this->regex, $this->variables, $this->defaults, $this->requirements, $this->suffix, $this->customToken)); + return array($this->tokens, $this->defaultOptions, $this->options, $this->pattern, $this->staticPrefix, $this->regex, $this->variables, $this->defaults, $this->requirements, $this->suffix, $this->customToken); } - public function unserialize($data) + /** + * Unserializes a sfRoute instance for php 7.4+ + * + * @param array $data + */ + public function __unserialize($data) { - list($this->tokens, $this->defaultOptions, $this->options, $this->pattern, $this->staticPrefix, $this->regex, $this->variables, $this->defaults, $this->requirements, $this->suffix, $this->customToken) = unserialize($data); + list($this->tokens, $this->defaultOptions, $this->options, $this->pattern, $this->staticPrefix, $this->regex, $this->variables, $this->defaults, $this->requirements, $this->suffix, $this->customToken) = $data; + $this->compiled = true; } } diff --git a/lib/util/sfNamespacedParameterHolder.class.php b/lib/util/sfNamespacedParameterHolder.class.php index 18eb76c67..757d86edd 100644 --- a/lib/util/sfNamespacedParameterHolder.class.php +++ b/lib/util/sfNamespacedParameterHolder.class.php @@ -366,11 +366,11 @@ public function addByRef(& $parameters, $ns = null) /** * Serializes the current instance. * - * @return array Objects instance + * @return string Objects instance */ public function serialize() { - return serialize(array($this->default_namespace, $this->parameters)); + return serialize($this->__serialize()); } /** @@ -380,9 +380,28 @@ public function serialize() */ public function unserialize($serialized) { - $data = unserialize($serialized); + $this->__unserialize(unserialize($serialized)); + } + + + /** + * Serializes the current instance for PHP 7.4+ + * + * @return array + */ + public function __serialize() + { + return array($this->default_namespace, $this->parameters); + } - $this->default_namespace = $data[0]; - $this->parameters = $data[1]; + /** + * Unserializes a sfParameterHolder instance. for PHP 7.4 + * + * @param array $data + */ + public function __unserialize($data) + { + $this->default_namespace = $data[0]; + $this->parameters = $data[1]; } } diff --git a/lib/util/sfParameterHolder.class.php b/lib/util/sfParameterHolder.class.php index 6f46b64f3..aecd57435 100644 --- a/lib/util/sfParameterHolder.class.php +++ b/lib/util/sfParameterHolder.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. */ @@ -181,11 +181,11 @@ public function addByRef(& $parameters) /** * Serializes the current instance. * - * @return array Objects instance + * @return string Objects instance */ public function serialize() { - return serialize($this->parameters); + return serialize($this->__serialize()); } /** @@ -195,6 +195,26 @@ public function serialize() */ public function unserialize($serialized) { - $this->parameters = unserialize($serialized); + $this->__unserialize(unserialize($serialized)); + } + + /** + * Serializes the current instance for PHP 7.4+ + * + * @return Array + */ + public function __serialize() { + + return $this->parameters; + } + + /** + * Unserializes a sfParameterHolder instance. for PHP 7.4 + * + * @param array $data + */ + public function __unserialize($data) + { + $this->parameters = $data; } } diff --git a/lib/validator/sfValidatorError.class.php b/lib/validator/sfValidatorError.class.php index 5eab900ae..fc4fc6c33 100644 --- a/lib/validator/sfValidatorError.class.php +++ b/lib/validator/sfValidatorError.class.php @@ -109,7 +109,7 @@ public function getArguments($raw = false) * error messages: * * $i18n->__($error->getMessageFormat(), $error->getArguments()); - * + * * If no message format has been set in the validator, the exception standard * message is returned. * @@ -140,7 +140,7 @@ public function getMessageFormat() */ public function serialize() { - return serialize(array($this->validator, $this->arguments, $this->code, $this->message)); + return serialize($this->__serialize()); } /** @@ -151,6 +151,29 @@ public function serialize() */ public function unserialize($serialized) { - list($this->validator, $this->arguments, $this->code, $this->message) = unserialize($serialized); + $array = unserialize($serialized); + + $this->__unserialize($array); + } + + /** + * Serializes the current instance for php 7.4+ + * + * @return array + */ + public function __serialize() + { + return array($this->validator, $this->arguments, $this->code, $this->message); } + + /** + * Unserializes a sfValidatorError instance for php 7.4+ + * + * @param string $serialized A serialized sfValidatorError instance + */ + public function __unserialize($data) + { + list($this->validator, $this->arguments, $this->code, $this->message) = $data; + } + } diff --git a/lib/view/sfViewParameterHolder.class.php b/lib/view/sfViewParameterHolder.class.php index 5172c8aac..4cc6d636c 100644 --- a/lib/view/sfViewParameterHolder.class.php +++ b/lib/view/sfViewParameterHolder.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. */ @@ -165,11 +165,11 @@ public function setEscapingMethod($method) /** * Serializes the current instance. * - * @return array Objects instance + * @return string Objects instance */ public function serialize() { - return serialize(array($this->getAll(), $this->escapingMethod, $this->escaping)); + return serialize($this->__serialize()); } /** @@ -179,8 +179,27 @@ public function serialize() */ public function unserialize($serialized) { - list($this->parameters, $escapingMethod, $escaping) = unserialize($serialized); + $this->__unserialize(unserialize($serialized)); + } + + /** + * Serializes the current instance for PHP 7.4+ + * + * @return array + */ + public function __serialize() + { + return array($this->getAll(), $this->escapingMethod, $this->escaping); + } + /** + * Unserializes a sfParameterHolder instance. for PHP 7.4 + * + * @param array $data + */ + public function __unserialize($data) + { + list($this->parameters, $escapingMethod, $escaping) = $data; $this->initialize(sfContext::hasInstance() ? sfContext::getInstance()->getEventDispatcher() : new sfEventDispatcher()); $this->setEscapingMethod($escapingMethod); diff --git a/test/unit/response/sfResponseTest.php b/test/unit/response/sfResponseTest.php index 31aad5842..c6f357f41 100644 --- a/test/unit/response/sfResponseTest.php +++ b/test/unit/response/sfResponseTest.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. */ @@ -14,6 +14,8 @@ class myResponse extends sfResponse { function serialize() {} function unserialize($serialized) {} + function __serialize() {} + function __unserialize($data) {} } class fakeResponse diff --git a/test/unit/validator/sfValidatorErrorSchemaTest.php b/test/unit/validator/sfValidatorErrorSchemaTest.php index e7768a9a6..7ca40047f 100644 --- a/test/unit/validator/sfValidatorErrorSchemaTest.php +++ b/test/unit/validator/sfValidatorErrorSchemaTest.php @@ -187,6 +187,16 @@ public function unserialize($serialized) { throw new Exception('Not serializable'); } + + public function __serialize() + { + throw new Exception('Not serializable'); + } + + public function __unserialize($data) + { + throw new Exception('Not serializable'); + } } function will_crash($a) diff --git a/test/unit/validator/sfValidatorErrorTest.php b/test/unit/validator/sfValidatorErrorTest.php index 41b03f4c3..f3b37ea46 100644 --- a/test/unit/validator/sfValidatorErrorTest.php +++ b/test/unit/validator/sfValidatorErrorTest.php @@ -65,6 +65,16 @@ public function unserialize($serialized) { throw new Exception('Not serializable'); } + + public function __serialize() + { + throw new Exception('Not serializable'); + } + + public function __unserialize($data) + { + throw new Exception('Not serializable'); + } } function will_crash($a) From 029b0e7e03dd8a57a35a3ea41ec67a516bb14a1e Mon Sep 17 00:00:00 2001 From: Tybaze Date: Mon, 23 May 2022 10:41:36 +0200 Subject: [PATCH 06/43] 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 --- lib/helper/DateHelper.php | 2 +- lib/helper/I18NHelper.php | 4 ++-- lib/i18n/sfDateFormat.class.php | 3 ++- .../lib/database/sfDoctrineConnectionProfiler.class.php | 2 +- .../lib/debug/sfWebDebugPanelDoctrine.class.php | 4 ++-- lib/routing/sfRoute.class.php | 4 ++-- lib/util/sfBrowserBase.class.php | 2 +- lib/util/sfInflector.class.php | 4 ++-- lib/util/sfToolkit.class.php | 2 +- lib/vendor/lime/lime.php | 2 +- lib/widget/sfWidgetFormDate.class.php | 2 +- lib/widget/sfWidgetFormTime.class.php | 4 ++-- lib/yaml/sfYamlInline.class.php | 2 +- lib/yaml/sfYamlParser.class.php | 2 +- .../apps/frontend/config/frontendConfiguration.class.php | 2 +- 15 files changed, 21 insertions(+), 20 deletions(-) diff --git a/lib/helper/DateHelper.php b/lib/helper/DateHelper.php index 564aae975..51265f48e 100644 --- a/lib/helper/DateHelper.php +++ b/lib/helper/DateHelper.php @@ -17,7 +17,7 @@ * @version SVN: $Id$ */ -function format_daterange($start_date, $end_date, $format = 'd', $full_text, $start_text, $end_text, $culture = null, $charset = null) +function format_daterange($start_date, $end_date, $format = 'd', $full_text = '', $start_text = '', $end_text = '', $culture = null, $charset = null) { if ($start_date != '' && $end_date != '') { diff --git a/lib/helper/I18NHelper.php b/lib/helper/I18NHelper.php index cde3e3352..95d285a32 100644 --- a/lib/helper/I18NHelper.php +++ b/lib/helper/I18NHelper.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. */ @@ -60,7 +60,7 @@ function __($text, $args = array(), $catalogue = 'messages') * * @return string Result of the translation */ -function format_number_choice($text, $args = array(), $number, $catalogue = 'messages') +function format_number_choice($text, $args = array(), $number = null, $catalogue = 'messages') { $translated = __($text, $args, $catalogue); diff --git a/lib/i18n/sfDateFormat.class.php b/lib/i18n/sfDateFormat.class.php index 80a5a571f..90b2aded3 100644 --- a/lib/i18n/sfDateFormat.class.php +++ b/lib/i18n/sfDateFormat.class.php @@ -239,9 +239,10 @@ public function format($time, $pattern = 'F', $inputPattern = null, $charset = ' } else { - $function = ucfirst($this->getFunctionName($pattern)); + $function = $this->getFunctionName($pattern); if ($function != null) { + $function = ucfirst($function); $fName = 'get'.$function; if (in_array($fName, $this->methods)) { diff --git a/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineConnectionProfiler.class.php b/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineConnectionProfiler.class.php index 0643cab71..e3824c7c2 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineConnectionProfiler.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineConnectionProfiler.class.php @@ -200,7 +200,7 @@ static public function fixParams($params) foreach ($params as $key => $param) { - if (strlen($param) >= 255) + if ($param && strlen($param) >= 255) { $params[$key] = '['.number_format(strlen($param) / 1024, 2).'Kb]'; } diff --git a/lib/plugins/sfDoctrinePlugin/lib/debug/sfWebDebugPanelDoctrine.class.php b/lib/plugins/sfDoctrinePlugin/lib/debug/sfWebDebugPanelDoctrine.class.php index e7477b34d..9c4bacf7d 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/debug/sfWebDebugPanelDoctrine.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/debug/sfWebDebugPanelDoctrine.class.php @@ -68,7 +68,7 @@ static public function listenToAddPanelEvent(sfEvent $event) /** * Returns an array of Doctrine query events. - * + * * @return array */ protected function getDoctrineEvents() @@ -116,7 +116,7 @@ protected function getSqlLogs() // interpolate parameters foreach ($params as $param) { - $param = htmlspecialchars($param, ENT_QUOTES, sfConfig::get('sf_charset')); + $param = htmlspecialchars((string) $param, ENT_QUOTES, sfConfig::get('sf_charset')); $query = join(var_export(is_scalar($param) ? $param : (string) $param, true), explode('?', $query, 2)); } diff --git a/lib/routing/sfRoute.class.php b/lib/routing/sfRoute.class.php index 5a0f0e508..05385fe6c 100644 --- a/lib/routing/sfRoute.class.php +++ b/lib/routing/sfRoute.class.php @@ -285,7 +285,7 @@ protected function generateWithTokens($parameters) switch ($token[0]) { case 'variable': - if (!$optional || !isset($this->defaults[$token[3]]) || $parameters[$token[3]] != $this->defaults[$token[3]]) + if (!$optional || !isset($this->defaults[$token[3]]) || (isset($parameters[$token[3]]) && $parameters[$token[3]] != $this->defaults[$token[3]])) { $url[] = urlencode($parameters[$token[3]]); $optional = false; @@ -791,7 +791,7 @@ protected function fixDefaults() } else { - $this->defaults[$key] = urldecode($value); + $this->defaults[$key] = urldecode((string) $value); } } } diff --git a/lib/util/sfBrowserBase.class.php b/lib/util/sfBrowserBase.class.php index 21d3de7da..c02c97e4f 100755 --- a/lib/util/sfBrowserBase.class.php +++ b/lib/util/sfBrowserBase.class.php @@ -908,7 +908,7 @@ public function doClickElement(DOMElement $item, $arguments = array(), $options } else { - $queryString = http_build_query($arguments, null, '&'); + $queryString = (is_array($arguments)) ? http_build_query($arguments, null, '&') : ''; $sep = false === strpos($url, '?') ? '?' : '&'; return array($url.($queryString ? $sep.$queryString : ''), 'get', array()); diff --git a/lib/util/sfInflector.class.php b/lib/util/sfInflector.class.php index 378d5e79e..f1676eb06 100644 --- a/lib/util/sfInflector.class.php +++ b/lib/util/sfInflector.class.php @@ -28,7 +28,7 @@ class sfInflector public static function camelize($lower_case_and_underscored_word) { - return strtr(ucwords(strtr($lower_case_and_underscored_word, array('/' => ':: ', '_' => ' ', '-' => ' '))), array(' ' => '')); + return strtr(ucwords(strtr((string) $lower_case_and_underscored_word, array('/' => ':: ', '_' => ' ', '-' => ' '))), array(' ' => '')); } /** @@ -40,7 +40,7 @@ public static function camelize($lower_case_and_underscored_word) */ public static function underscore($camel_cased_word) { - $tmp = $camel_cased_word; + $tmp = (string) $camel_cased_word; $tmp = str_replace('::', '/', $tmp); $tmp = sfToolkit::pregtr($tmp, array('/([A-Z]+)([A-Z][a-z])/' => '\\1_\\2', '/([a-z\d])([A-Z])/' => '\\1_\\2')); diff --git a/lib/util/sfToolkit.class.php b/lib/util/sfToolkit.class.php index b3bda1000..811df0edb 100644 --- a/lib/util/sfToolkit.class.php +++ b/lib/util/sfToolkit.class.php @@ -366,7 +366,7 @@ public static function replaceConstants($value) */ public static function pregtr($search, $replacePairs) { - return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search); + return preg_replace(array_keys($replacePairs), array_values($replacePairs), (string) $search); } /** diff --git a/lib/vendor/lime/lime.php b/lib/vendor/lime/lime.php index 53fdd0dd1..d087dd631 100644 --- a/lib/vendor/lime/lime.php +++ b/lib/vendor/lime/lime.php @@ -564,7 +564,7 @@ protected function find_caller($traces) return array($traces[$last]['file'], $traces[$last]['line']); } - public function handle_error($code, $message, $file, $line, $context) + public function handle_error($code, $message, $file, $line, $context = null) { if (!$this->options['error_reporting'] || ($code & error_reporting()) == 0) { diff --git a/lib/widget/sfWidgetFormDate.class.php b/lib/widget/sfWidgetFormDate.class.php index 96eba1a5d..c8ed674df 100644 --- a/lib/widget/sfWidgetFormDate.class.php +++ b/lib/widget/sfWidgetFormDate.class.php @@ -70,7 +70,7 @@ public function render($name, $value = null, $attributes = array(), $errors = ar } else { - $value = (string) $value == (string) (integer) $value ? (integer) $value : strtotime($value); + $value = (string) $value == (string) (integer) $value ? (integer) $value : strtotime( (string) $value); if (false === $value) { $value = $default; diff --git a/lib/widget/sfWidgetFormTime.class.php b/lib/widget/sfWidgetFormTime.class.php index d68f375df..5917ed841 100644 --- a/lib/widget/sfWidgetFormTime.class.php +++ b/lib/widget/sfWidgetFormTime.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. */ @@ -72,7 +72,7 @@ public function render($name, $value = null, $attributes = array(), $errors = ar } else { - $value = ctype_digit($value) ? (integer) $value : strtotime($value); + $value = ctype_digit( (string) $value) ? (integer) $value : strtotime( (string) $value); if (false === $value) { $value = $default; diff --git a/lib/yaml/sfYamlInline.class.php b/lib/yaml/sfYamlInline.class.php index ad9342099..2b7ccd6c5 100644 --- a/lib/yaml/sfYamlInline.class.php +++ b/lib/yaml/sfYamlInline.class.php @@ -97,7 +97,7 @@ static public function dump($value) return 'true'; case false === $value: return 'false'; - case ctype_digit($value): + case (is_string($value) && ctype_digit($value)): return is_string($value) ? "'$value'" : (int) $value; case is_numeric($value): return is_infinite($value) ? str_ireplace('INF', '.Inf', (string) $value) : (is_string($value) ? "'$value'" : $value); diff --git a/lib/yaml/sfYamlParser.class.php b/lib/yaml/sfYamlParser.class.php index 69b9f2651..58aa6b8eb 100644 --- a/lib/yaml/sfYamlParser.class.php +++ b/lib/yaml/sfYamlParser.class.php @@ -421,7 +421,7 @@ protected function parseValue($value) { $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : ''; - return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers)); + return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs((int) $modifiers)); } else { diff --git a/test/functional/fixtures/apps/frontend/config/frontendConfiguration.class.php b/test/functional/fixtures/apps/frontend/config/frontendConfiguration.class.php index 58e520532..9b0b90c90 100644 --- a/test/functional/fixtures/apps/frontend/config/frontendConfiguration.class.php +++ b/test/functional/fixtures/apps/frontend/config/frontendConfiguration.class.php @@ -11,7 +11,7 @@ public function configure() public function filter_parameters(sfEvent $event, $parameters) { - if (false !== stripos($event->getSubject()->getHttpHeader('user-agent'), 'iPhone')) + if (false !== stripos((string) $event->getSubject()->getHttpHeader('user-agent'), 'iPhone')) { $event->getSubject()->setRequestFormat('iphone'); } From dcb1ce3a6ed98127b604e1bc7b2c380367a1d581 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Mon, 23 May 2022 12:59:20 +0200 Subject: [PATCH 07/43] 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. --- lib/log/sfFileLogger.class.php | 60 +++++++++++++++++++++++++++++- test/unit/log/sfFileLoggerTest.php | 8 ++-- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/lib/log/sfFileLogger.class.php b/lib/log/sfFileLogger.class.php index dfb610a8e..eceb47255 100644 --- a/lib/log/sfFileLogger.class.php +++ b/lib/log/sfFileLogger.class.php @@ -92,7 +92,7 @@ public function initialize(sfEventDispatcher $dispatcher, $options = array()) * Logs a message. * * @param string $message Message - * @param int $priority Message priority + * @param int $priority Message priority */ protected function doLog($message, $priority) { @@ -100,7 +100,7 @@ protected function doLog($message, $priority) fwrite($this->fp, strtr($this->format, array( '%type%' => $this->type, '%message%' => $message, - '%time%' => strftime($this->timeFormat), + '%time%' => self::strftime($this->timeFormat), '%priority%' => $this->getPriority($priority), '%EOL%' => PHP_EOL, ))); @@ -129,4 +129,60 @@ public function shutdown() fclose($this->fp); } } + + /** + * @param $format + * @return false|string + */ + public static function strftime($format) + { + if (version_compare(PHP_VERSION, '8.1.0') < 0) { + return strftime($format); + } + return date(self::_strftimeFormatToDateFormat($format)); + } + + /** + * Try to Convert a strftime to date format + * + * Unable to find a perfect implementation, based on those one (Each contains some errors) + * https://github.com/Fabrik/fabrik/blob/master/plugins/fabrik_element/date/date.php + * https://gist.github.com/mcaskill/02636e5970be1bb22270 + * https://stackoverflow.com/questions/22665959/using-php-strftime-using-date-format-string + * + * Limitation: + * - Do not apply translation + * - Some few strftime format could be broken (low probability to be used on logs) + * + * Private: because it should not be used outside of this scope + * + * A better solution is to use : IntlDateFormatter, but it will require to load a new php extension, which could break some setup. + * + * @return array|string|string[] + */ + private static function _strftimeFormatToDateFormat($strftimeFormat) { + + // Missing %V %C %g %G + $search = array( + '%a', '%A', '%d', '%e', '%u', + '%w', '%W', '%b', '%h', '%B', + '%m', '%y', '%Y', '%D', '%F', + '%x', '%n', '%t', '%H', '%k', + '%I', '%l', '%M', '%p', '%P', + '%r' /* %I:%M:%S %p */, '%R' /* %H:%M */, '%S', '%T' /* %H:%M:%S */, '%X', '%z', '%Z', + '%c', '%s', '%j', + '%%'); + + $replace = array( + 'D', 'l', 'd', 'j', 'N', + 'w', 'W', 'M', 'M', 'F', + 'm', 'y', 'Y', 'm/d/y', 'Y-m-d', + 'm/d/y', "\n", "\t", 'H', 'G', + 'h', 'g', 'i', 'A', 'a', + 'h:i:s A', 'H:i', 's', 'H:i:s', 'H:i:s', 'O', 'T', + 'D M j H:i:s Y' /*Tue Feb 5 00:45:10 2009*/, 'U', 'z', + '%'); + + return str_replace($search, $replace, $strftimeFormat); + } } diff --git a/test/unit/log/sfFileLoggerTest.php b/test/unit/log/sfFileLoggerTest.php index 81fa52a58..3fbb66f9b 100644 --- a/test/unit/log/sfFileLoggerTest.php +++ b/test/unit/log/sfFileLoggerTest.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. */ @@ -61,7 +61,7 @@ protected function getPriority($priority) unlink($file); $logger = new TestLogger($dispatcher, array('file' => $file)); $logger->log('foo'); -$t->is(file_get_contents($file), strftime($logger->getTimeFormat()).' symfony [*6*] foo'.PHP_EOL, '->initialize() can take a format option'); +$t->is(file_get_contents($file), TestLogger::strftime($logger->getTimeFormat()).' symfony [*6*] foo'.PHP_EOL, '->initialize() can take a format option'); unlink($file); $logger = new TestLogger($dispatcher, array('file' => $file, 'format' => '%message%')); @@ -73,14 +73,14 @@ protected function getPriority($priority) unlink($file); $logger = new TestLogger($dispatcher, array('file' => $file, 'time_format' => '%Y %m %d')); $logger->log('foo'); -$t->is(file_get_contents($file), strftime($logger->getTimeFormat()).' symfony [*6*] foo'.PHP_EOL, '->initialize() can take a format option'); +$t->is(file_get_contents($file), TestLogger::strftime($logger->getTimeFormat()).' symfony [*6*] foo'.PHP_EOL, '->initialize() can take a format option'); // option: type $t->diag('option: type'); unlink($file); $logger = new TestLogger($dispatcher, array('file' => $file, 'type' => 'foo')); $logger->log('foo'); -$t->is(file_get_contents($file), strftime($logger->getTimeFormat()).' foo [*6*] foo'.PHP_EOL, '->initialize() can take a format option'); +$t->is(file_get_contents($file), TestLogger::strftime($logger->getTimeFormat()).' foo [*6*] foo'.PHP_EOL, '->initialize() can take a format option'); // ->shutdown() $t->diag('->shutdown()'); From 8450b13a012ac8fc216231571f95630eb073a354 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 14:31:05 +0200 Subject: [PATCH 08/43] 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 --- lib/exception/sfException.class.php | 4 ++++ .../test/functional/AdminGenBrowser.class.php | 4 ++-- lib/storage/sfSessionStorage.class.php | 1 + lib/test/sfTestFunctionalBase.class.php | 2 +- lib/util/sfBrowser.class.php | 5 +++-- lib/vendor/lime/lime.php | 19 ++++++++++++------- test/unit/storage/sfSessionStorageTest.php | 1 + 7 files changed, 24 insertions(+), 12 deletions(-) diff --git a/lib/exception/sfException.class.php b/lib/exception/sfException.class.php index 3611caada..fbd742596 100644 --- a/lib/exception/sfException.class.php +++ b/lib/exception/sfException.class.php @@ -366,6 +366,10 @@ static protected function formatArrayAsHtml($values) */ static protected function fileExcerpt($file, $line) { + // $file can be null for RuntimeException + if($file === null) { + return ''; + } if (is_readable($file)) { $content = preg_split('#
#', preg_replace('/^(.*)<\/code>$/s', '$1', highlight_file($file, true))); diff --git a/lib/plugins/sfDoctrinePlugin/test/functional/AdminGenBrowser.class.php b/lib/plugins/sfDoctrinePlugin/test/functional/AdminGenBrowser.class.php index a5efd75f7..cb29fe83e 100644 --- a/lib/plugins/sfDoctrinePlugin/test/functional/AdminGenBrowser.class.php +++ b/lib/plugins/sfDoctrinePlugin/test/functional/AdminGenBrowser.class.php @@ -152,7 +152,7 @@ protected function _testEnumDropdown() $this-> get('/subscriptions/new')-> with('response')->begin()-> - checkElement('select', 'NewActivePendingExpired')-> + checkElement('select', '/^New\R?Active\R?Pending\R?Expired\R?$/m')-> end() ; } @@ -237,7 +237,7 @@ protected function _runAdminGenModuleSanityCheck($model, $module) } protected function _generateAdminGenModule($model, $module) - { + { $this->info('Generating admin gen module "' . $module . '"'); $task = new sfDoctrineGenerateAdminTask($this->getContext()->getEventDispatcher(), new sfFormatter()); $task->run(array('application' => 'backend', 'route_or_model' => $model)); diff --git a/lib/storage/sfSessionStorage.class.php b/lib/storage/sfSessionStorage.class.php index 57ff59973..f11337d39 100644 --- a/lib/storage/sfSessionStorage.class.php +++ b/lib/storage/sfSessionStorage.class.php @@ -190,5 +190,6 @@ public function shutdown() { // don't need a shutdown procedure because read/write do it in real-time session_write_close(); + self::$sessionStarted = false; } } diff --git a/lib/test/sfTestFunctionalBase.class.php b/lib/test/sfTestFunctionalBase.class.php index 2f3da782c..97ac815a6 100644 --- a/lib/test/sfTestFunctionalBase.class.php +++ b/lib/test/sfTestFunctionalBase.class.php @@ -478,7 +478,7 @@ static public function handlePhpError($errno, $errstr, $errfile, $errline) /** * Exception handler for the current test browser instance. * - * @param Exception $exception The exception + * @param Throwable $exception The exception */ function handleException($exception) { diff --git a/lib/util/sfBrowser.class.php b/lib/util/sfBrowser.class.php index a4f89691c..ad45e1225 100644 --- a/lib/util/sfBrowser.class.php +++ b/lib/util/sfBrowser.class.php @@ -28,11 +28,12 @@ class sfBrowser extends sfBrowserBase */ protected function doCall() { + // Before getContext, it can trigger some + sfConfig::set('sf_test', true); + // recycle our context object $this->context = $this->getContext(true); - sfConfig::set('sf_test', true); - // we register a fake rendering filter sfConfig::set('sf_rendering_filter', array('sfFakeRenderingFilter', null)); diff --git a/lib/vendor/lime/lime.php b/lib/vendor/lime/lime.php index d087dd631..8020c94b5 100644 --- a/lib/vendor/lime/lime.php +++ b/lib/vendor/lime/lime.php @@ -520,11 +520,11 @@ public function error($message, $file = null, $line = null, array $traces = arra { $this->output->error($message, $file, $line, $traces); - $this->results['stats']['errors'][] = array( - 'message' => $message, - 'file' => $file, - 'line' => $line, - ); + $this->results['stats']['errors'][] = array( + 'message' => $message, + 'file' => $file, + 'line' => $line, + ); } protected function update_stats() @@ -553,7 +553,8 @@ protected function find_caller($traces) $t = array_reverse($traces); foreach ($t as $trace) { - if (isset($trace['object']) && $this->is_test_object($trace['object'])) + // In internal calls, like error_handle, 'file' will be missing + if (isset($trace['object']) && $this->is_test_object($trace['object']) && isset($trace['file'])) { return array($trace['file'], $trace['line']); } @@ -587,7 +588,11 @@ public function handle_error($code, $message, $file, $line, $context = null) $this->error($type.': '.$message, $file, $line, $trace); } - public function handle_exception(Throwable $exception) + /** + * @param Throwable $exception only available on php7 + * @return bool + */ + public function handle_exception($exception) { $this->error(get_class($exception).': '.$exception->getMessage(), $exception->getFile(), $exception->getLine(), $exception->getTrace()); diff --git a/test/unit/storage/sfSessionStorageTest.php b/test/unit/storage/sfSessionStorageTest.php index ddc1f4a6b..2349ee02b 100644 --- a/test/unit/storage/sfSessionStorageTest.php +++ b/test/unit/storage/sfSessionStorageTest.php @@ -26,6 +26,7 @@ { $storage = new sfSessionStorage(); $t->pass('->__construct() does not throw an exception when not provided with options'); + $storage->shutdown(); } catch (InvalidArgumentException $e) { From 9cb7fb482b1b91fa22a7f5f78f3055a3def5130f Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 15:31:25 +0200 Subject: [PATCH 09/43] Fix lime message: "An uncaught exception has been thrown" do not have "error" value uncaught exception does not populate error field --- lib/vendor/lime/lime.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/vendor/lime/lime.php b/lib/vendor/lime/lime.php index 8020c94b5..5b3c16560 100644 --- a/lib/vendor/lime/lime.php +++ b/lib/vendor/lime/lime.php @@ -1103,7 +1103,9 @@ function lime_shutdown() $this->output->comment(sprintf(' at %s line %s', $this->get_relative_file($testsuite['tests'][$testcase]['file']).$this->extension, $testsuite['tests'][$testcase]['line'])); $this->output->info(' '.$testsuite['tests'][$testcase]['message']); - $this->output->echoln($testsuite['tests'][$testcase]['error'], null, false); + if(isset($testsuite['tests'][$testcase]['error'])) { + $this->output->echoln($testsuite['tests'][$testcase]['error'], null, false); + } } } } From 25a5e71b67b0522d93ad9a0130b20826a6d57e90 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 18:12:21 +0200 Subject: [PATCH 10/43] PHP 8.1 > uasort(): Returning bool from comparison function is deprecated, return an integer less than, equal to, or greater than zero --- lib/routing/sfRoute.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/routing/sfRoute.class.php b/lib/routing/sfRoute.class.php index 05385fe6c..a0093b18e 100644 --- a/lib/routing/sfRoute.class.php +++ b/lib/routing/sfRoute.class.php @@ -264,7 +264,7 @@ public function generate($params, $context = array(), $absolute = false) static private function generateCompareVarsByStrlen($a, $b) { - return strlen($a) < strlen($b); + return (strlen($a) < strlen($b)) ? 1 : -1; } /** From 09fc710a73336971f816f991b8a1011c1d31c2e0 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 18:30:50 +0200 Subject: [PATCH 11/43] Fix ValueError: DOMDocument::loadHTML(): Argument #1 ($source) must not be empty --- lib/test/sfTesterResponse.class.php | 12 +++++++----- lib/util/sfBrowserBase.class.php | 4 +++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/test/sfTesterResponse.class.php b/lib/test/sfTesterResponse.class.php index 4fca01923..1a1c7a86a 100644 --- a/lib/test/sfTesterResponse.class.php +++ b/lib/test/sfTesterResponse.class.php @@ -49,7 +49,9 @@ public function initialize() } else { - @$this->dom->loadHTML($this->response->getContent()); + if($this->response->getContent()) { + @$this->dom->loadHTML($this->response->getContent()); + } } $this->domCssSelector = new sfDomCssSelector($this->dom); } @@ -120,10 +122,10 @@ public function checkElement($selector, $value = true, $options = array()) /** * Checks that a form is rendered correctly. - * + * * @param sfForm|string $form A form object or the name of a form class * @param string $selector CSS selector for the root form element for this form - * + * * @return sfTestFunctionalBase|sfTester */ public function checkForm($form, $selector = 'form') @@ -333,11 +335,11 @@ public function isHeader($key, $value) /** * Tests if a cookie was set. - * + * * @param string $name * @param string $value * @param array $attributes Other cookie attributes to check (expires, path, domain, etc) - * + * * @return sfTestFunctionalBase|sfTester */ public function setsCookie($name, $value = null, $attributes = array()) diff --git a/lib/util/sfBrowserBase.class.php b/lib/util/sfBrowserBase.class.php index c02c97e4f..4ec39098a 100755 --- a/lib/util/sfBrowserBase.class.php +++ b/lib/util/sfBrowserBase.class.php @@ -363,7 +363,9 @@ public function call($uri, $method = 'get', $parameters = array(), $changeStack } else { - @$this->dom->loadHTML($response->getContent()); + if($response->getContent()) { + @$this->dom->loadHTML($response->getContent()); + } } $this->domCssSelector = new sfDomCssSelector($this->dom); } From df2ec65dbe8729ef7495a8a7f45b44c823dc7e72 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 19:36:56 +0200 Subject: [PATCH 12/43] 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 --- lib/cache/sfFileCache.class.php | 6 +++- .../sfOutputEscaperObjectDecorator.class.php | 8 ++++-- lib/i18n/sfCultureInfo.class.php | 28 +++++++++---------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/lib/cache/sfFileCache.class.php b/lib/cache/sfFileCache.class.php index dcd03f345..2997d6c96 100644 --- a/lib/cache/sfFileCache.class.php +++ b/lib/cache/sfFileCache.class.php @@ -256,7 +256,11 @@ protected function read($path, $type = self::READ_DATA) fseek($fp, 0, SEEK_END); $length = ftell($fp) - 24; fseek($fp, 24); - $data[self::READ_DATA] = @fread($fp, $length); + if($length > 0) { + $data[self::READ_DATA] = @fread($fp, $length); + } else { + $data[self::READ_DATA] = ''; + } } } else diff --git a/lib/escaper/sfOutputEscaperObjectDecorator.class.php b/lib/escaper/sfOutputEscaperObjectDecorator.class.php index fe506d9c1..86d0ae71e 100644 --- a/lib/escaper/sfOutputEscaperObjectDecorator.class.php +++ b/lib/escaper/sfOutputEscaperObjectDecorator.class.php @@ -111,13 +111,17 @@ public function __isset($key) /** * Returns the size of the object if it implements Countable (is required by the Countable interface). * - * It returns 1 if other cases (which is the default PHP behavior in such a case). + * 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; } } diff --git a/lib/i18n/sfCultureInfo.class.php b/lib/i18n/sfCultureInfo.class.php index a14fd7c0f..aaf8d3bb7 100644 --- a/lib/i18n/sfCultureInfo.class.php +++ b/lib/i18n/sfCultureInfo.class.php @@ -92,11 +92,11 @@ class sfCultureInfo * @var sfNumberFormatInfo */ protected $numberFormat; - + /** * A list of properties that are accessable/writable. * @var array - */ + */ protected $properties = array(); /** @@ -191,9 +191,9 @@ public function __set($name, $value) } /** - * Initializes a new instance of the sfCultureInfo class based on the + * Initializes a new instance of the sfCultureInfo class based on the * culture specified by name. E.g. new sfCultureInfo('en_AU'); - * The culture indentifier must be of the form + * The culture indentifier must be of the form * "_(country/region/variant)". * * @param string $culture a culture name, e.g. "en_AU". @@ -323,7 +323,7 @@ protected function loadCultureData($culture) * this function. * * @param string $filename the ICU data filename - * @return array ICU data + * @return array ICU data */ protected function &getData($filename) { @@ -347,7 +347,7 @@ protected function &getData($filename) * Use merge=true to return the ICU including the parent culture. * E.g. The currency data for a variant, say "en_AU" contains one * entry, the currency for AUD, the other currency data are stored - * in the "en" data file. Thus to retrieve all the data regarding + * in the "en" data file. Thus to retrieve all the data regarding * currency for "en_AU", you need to use findInfo("Currencies,true);. * * @param string $path the data you want to find. @@ -429,9 +429,9 @@ protected function searchArray($info, $path = '/') } } } - + /** - * Gets the culture name in the format + * Gets the culture name in the format * "_(country/regioncode2)". * * @return string culture name. @@ -516,7 +516,7 @@ public function getEnglishName() $culture = $this->getInvariantCulture(); $language = $culture->findInfo("Languages/{$lang}"); - if (count($language) == 0) + if (is_array($language) && count($language) == 0) { return $this->culture; } @@ -547,7 +547,7 @@ static function getInvariantCulture() } /** - * Gets a value indicating whether the current sfCultureInfo + * Gets a value indicating whether the current sfCultureInfo * represents a neutral culture. Returns true if the culture * only contains two characters. * @@ -590,7 +590,7 @@ public function setNumberFormat($numberFormat) } /** - * Gets the sfCultureInfo that represents the parent culture of the + * Gets the sfCultureInfo that represents the parent culture of the * current sfCultureInfo * * @return sfCultureInfo parent culture information. @@ -606,14 +606,14 @@ public function getParent() } /** - * Gets the list of supported cultures filtered by the specified + * Gets the list of supported cultures filtered by the specified * culture type. This is an EXPENSIVE function, it needs to traverse * a list of ICU files in the data directory. * This function can be called statically. * * @param int $type culture type, sfCultureInfo::ALL, sfCultureInfo::NEUTRAL * or sfCultureInfo::SPECIFIC. - * @return array list of culture information available. + * @return array list of culture information available. */ static function getCultures($type = sfCultureInfo::ALL) { @@ -719,7 +719,7 @@ public function getLanguage($code) * * @param array $countries An array of countries used to restrict the returned array (null by default, which means all countries) * - * @return array a list of localized country names. + * @return array a list of localized country names. */ public function getCountries($countries = null) { From 42112ab7f22b6b5d4523d51e190511f1bb11912c Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 22:25:36 +0200 Subject: [PATCH 13/43] Fix Declaration of sfPearRestTest::downloadHttp($url, $lastmodified = null, $accept = false) must be compatible with sfPearRest::downloadHttp($url, $lastmodified = null, $accept = false, $channel = false) --- lib/plugin/sfPearRest.class.php | 4 ++-- test/unit/plugin/sfPearRestTest.class.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/plugin/sfPearRest.class.php b/lib/plugin/sfPearRest.class.php index f17b6deb3..72cb66960 100644 --- a/lib/plugin/sfPearRest.class.php +++ b/lib/plugin/sfPearRest.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. */ @@ -23,7 +23,7 @@ class sfPearRest extends PEAR_REST /** * @see PEAR_REST::downloadHttp() */ - public function downloadHttp($url, $lastmodified = null, $accept = false) + public function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false) { return parent::downloadHttp($url, $lastmodified, array_merge(false !== $accept ? $accept : array(), array("\r\nX-SYMFONY-VERSION: ".SYMFONY_VERSION))); } diff --git a/test/unit/plugin/sfPearRestTest.class.php b/test/unit/plugin/sfPearRestTest.class.php index 251f913fc..df3138708 100644 --- a/test/unit/plugin/sfPearRestTest.class.php +++ b/test/unit/plugin/sfPearRestTest.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. */ @@ -21,7 +21,7 @@ class sfPearRestTest extends sfPearRest /** * @see PEAR_REST::downloadHttp() */ - public function downloadHttp($url, $lastmodified = null, $accept = false) + public function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false) { try { From 29ab2a79aa8e25d1df2a430a86a01f528ff5d730 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 22:00:51 +0200 Subject: [PATCH 14/43] 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. --- lib/i18n/sfI18N.class.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/i18n/sfI18N.class.php b/lib/i18n/sfI18N.class.php index b64ebccb4..5478e6d73 100644 --- a/lib/i18n/sfI18N.class.php +++ b/lib/i18n/sfI18N.class.php @@ -271,6 +271,15 @@ public function getTimestampForCulture($dateTime, $culture = null) list($day, $month, $year) = $this->getDateForCulture($dateTime, null === $culture ? $this->culture : $culture); list($hour, $minute) = $this->getTimeForCulture($dateTime, null === $culture ? $this->culture : $culture); + // mktime behavior change with php8 + // $hour become not nullable + if (!$hour) { + $hour = 0; + } + // Before 8.0, $minutes value to null, was casted as (int)0 + if (!$minute) { + $minute = 0; + } return null === $day ? null : mktime($hour, $minute, 0, $month, $day, $year); } From 12f7b4caae6dd33a3b609ca6b9a4e5e0c671f5be Mon Sep 17 00:00:00 2001 From: Tybaze Date: Fri, 10 Jun 2022 08:53:35 +0200 Subject: [PATCH 15/43] Fix sfWebResponse->getContentType() return a string not an array --- lib/response/sfWebResponse.class.php | 2 +- test/unit/response/sfWebResponseTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/response/sfWebResponse.class.php b/lib/response/sfWebResponse.class.php index 9f25c50f3..af69e38e2 100644 --- a/lib/response/sfWebResponse.class.php +++ b/lib/response/sfWebResponse.class.php @@ -312,7 +312,7 @@ public function getCharset() /** * Gets response content type. * - * @return array + * @return string */ public function getContentType() { diff --git a/test/unit/response/sfWebResponseTest.php b/test/unit/response/sfWebResponseTest.php index 0697da8d8..916a8298c 100644 --- a/test/unit/response/sfWebResponseTest.php +++ b/test/unit/response/sfWebResponseTest.php @@ -132,7 +132,7 @@ public function normalizeHeaderName($name) $response->setContentType('text/xml'); $response->setContentType('text/html'); -$t->is(count($response->getHttpHeader('content-type')), 1, '->setContentType() overrides previous content type if replace is true'); +$t->is($response->getHttpHeader('content-type'), 'text/html; charset=ISO-8859-1', '->setContentType() overrides previous content type if replace is true'); // ->getTitle() ->setTitle() ->prependTitle $t->diag('->getTitle() ->setTitle() ->prependTitle()'); From cae793e1ac19124d1251420bb0833d840355ca63 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Fri, 10 Jun 2022 09:26:26 +0200 Subject: [PATCH 16/43] Fix sfDoctrineTester, string cannot be accessed as array --- .../sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php b/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php index 8ce1c985c..48fd0374b 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php @@ -65,7 +65,7 @@ public function check($model, $query, $value = true) } $operator = '='; - if ('!' == $condition[0]) + if (strlen($condition) && '!' == substr($condition,0,1)) { $operator = false !== strpos($condition, '%') ? 'NOT LIKE' : '!='; $condition = substr($condition, 1); @@ -103,7 +103,7 @@ public function check($model, $query, $value = true) /** * Outputs some debug information about queries run during the current request. - * + * * @param integer|string $limit Either an integer to return the last many queries, a regular expression or a substring to search for */ public function debug($limit = null) From 7341b43844efd3720c706f48e3c9341f7861e478 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Fri, 10 Jun 2022 12:52:25 +0200 Subject: [PATCH 17/43] 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 --- lib/yaml/sfYamlInline.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yaml/sfYamlInline.class.php b/lib/yaml/sfYamlInline.class.php index 2b7ccd6c5..840f3fa7a 100644 --- a/lib/yaml/sfYamlInline.class.php +++ b/lib/yaml/sfYamlInline.class.php @@ -99,7 +99,7 @@ static public function dump($value) return 'false'; case (is_string($value) && ctype_digit($value)): return is_string($value) ? "'$value'" : (int) $value; - case is_numeric($value): + case is_numeric($value) && false === strpbrk($value, "\f\n\r\t\v"): return is_infinite($value) ? str_ireplace('INF', '.Inf', (string) $value) : (is_string($value) ? "'$value'" : $value); case false !== strpos($value, "\n") || false !== strpos($value, "\r"): return sprintf('"%s"', str_replace(array('"', "\n", "\r"), array('\\"', '\n', '\r'), $value)); From b191cb8a43789dde46435b472edeff268f7642a2 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Fri, 10 Jun 2022 14:31:05 +0200 Subject: [PATCH 18/43] 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 --- lib/yaml/sfYamlParser.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yaml/sfYamlParser.class.php b/lib/yaml/sfYamlParser.class.php index 58aa6b8eb..ed5b179ee 100644 --- a/lib/yaml/sfYamlParser.class.php +++ b/lib/yaml/sfYamlParser.class.php @@ -474,7 +474,7 @@ protected function parseFoldedScalar($separator, $indicator = '', $indentation = if (preg_match('#^(?P {'.strlen($textIndent).',})(?P.+)$#u', $this->currentLine, $matches)) { - if (' ' == $separator && $previousIndent != $matches['indent']) + if (' ' == $separator && ($previousIndent && $previousIndent != $matches['indent'])) { $text = substr($text, 0, -1)."\n"; } From 956cb1aaef2543f56cfb18bf91f91cac66e00b4a Mon Sep 17 00:00:00 2001 From: Tybaze Date: Mon, 23 May 2022 13:00:35 +0200 Subject: [PATCH 19/43] PHP 8.1 > Change support to PHP 8.1 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 900179110..e5147ca4d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ All the enhancements and BC breaks are listed in the [WHATS_NEW](https://github. - [DIC](https://github.com/FriendsOfSymfony1/symfony1/wiki/ServiceContainer) - Composer support -- PHP 7.2 support +- PHP 8.1 support - performance boost - new widgets & validators - some tickets fixed from the symfony trac From b0cb92e75edcc8dd7e8186e7b31a67bd1768c675 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Fri, 10 Jun 2022 19:00:21 +0200 Subject: [PATCH 20/43] Fix UnitTest application/x-sharedlib /bin/ls can be reported as: - application/x-sharedlib - application/x-executable - application/x-pie-executable --- test/unit/validator/sfValidatorFileTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/validator/sfValidatorFileTest.php b/test/unit/validator/sfValidatorFileTest.php index 42463acfa..d7d101d6d 100755 --- a/test/unit/validator/sfValidatorFileTest.php +++ b/test/unit/validator/sfValidatorFileTest.php @@ -105,7 +105,7 @@ public function getMimeTypesFromCategory($category) $v = new testValidatorFile(); $t->is($v->guessFromFileBinary($tmpDir.'/test.txt'), 'text/plain', '->guessFromFileBinary() guesses the type of a given file'); $t->is($v->guessFromFileBinary($tmpDir.'/foo.txt'), null, '->guessFromFileBinary() returns null if the file type is not guessable'); -$t->is($v->guessFromFileBinary('/bin/ls'), (PHP_OS != 'Darwin') ? 'application/x-pie-executable' : 'application/octet-stream', '->guessFromFileBinary() returns correct type if file is guessable'); +$t->like($v->guessFromFileBinary('/bin/ls'), (PHP_OS != 'Darwin') ? '/^application\/x-(pie-executable|executable|sharedlib)$/' : '/^application/octet-stream$/', '->guessFromFileBinary() returns correct type if file is guessable'); $t->is($v->guessFromFileBinary('-test'), null, '->guessFromFileBinary() returns null if file path has leading dash'); // ->getMimeType() From bb221418824b1251d9ff5964ff3295285ede2f32 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Fri, 10 Jun 2022 19:26:51 +0200 Subject: [PATCH 21/43] PHP 8.1 > mysqli_report revert to off https://php.watch/versions/8.1/mysqli-error-mode --- lib/database/sfMySQLiDatabase.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/database/sfMySQLiDatabase.class.php b/lib/database/sfMySQLiDatabase.class.php index e4814794a..bdc8be447 100644 --- a/lib/database/sfMySQLiDatabase.class.php +++ b/lib/database/sfMySQLiDatabase.class.php @@ -29,6 +29,9 @@ class sfMySQLiDatabase extends sfMySQLDatabase */ protected function getConnectMethod($persistent) { + // PHP 8.1 Activate Exception per default, revert behavior to "return false" + mysqli_report(MYSQLI_REPORT_OFF); + return 'mysqli_connect'; } From d0d0d122e8bb2b5197be327ff89ab3a2291b0ca0 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 7 Jul 2022 11:13:16 +0200 Subject: [PATCH 22/43] Refactor code and apply Coding Style fixes --- lib/cache/sfFileCache.class.php | 8 ++++++-- lib/escaper/sfOutputEscaperObjectDecorator.class.php | 3 ++- lib/event/sfEvent.class.php | 2 +- lib/exception/sfException.class.php | 4 +++- lib/i18n/sfDateFormat.class.php | 3 +-- lib/i18n/sfI18N.class.php | 10 ++-------- lib/log/sfFileLogger.class.php | 7 ++++--- .../lib/test/sfTesterDoctrine.class.php | 2 +- lib/response/sfResponse.class.php | 3 ++- lib/routing/sfRoute.class.php | 3 ++- lib/test/sfTestFunctionalBase.class.php | 2 +- lib/test/sfTesterResponse.class.php | 5 +++-- lib/util/sfBrowserBase.class.php | 7 ++++--- lib/util/sfNamespacedParameterHolder.class.php | 2 +- lib/util/sfParameterHolder.class.php | 6 +++--- lib/vendor/lime/lime.php | 5 +++-- lib/view/sfViewParameterHolder.class.php | 2 +- lib/widget/sfWidgetFormDate.class.php | 2 +- lib/widget/sfWidgetFormTime.class.php | 2 +- lib/yaml/sfYamlParser.class.php | 2 +- 20 files changed, 43 insertions(+), 37 deletions(-) diff --git a/lib/cache/sfFileCache.class.php b/lib/cache/sfFileCache.class.php index 2997d6c96..f84be899f 100644 --- a/lib/cache/sfFileCache.class.php +++ b/lib/cache/sfFileCache.class.php @@ -256,9 +256,13 @@ protected function read($path, $type = self::READ_DATA) fseek($fp, 0, SEEK_END); $length = ftell($fp) - 24; fseek($fp, 24); - if($length > 0) { + + if ($length > 0) + { $data[self::READ_DATA] = @fread($fp, $length); - } else { + } + else + { $data[self::READ_DATA] = ''; } } diff --git a/lib/escaper/sfOutputEscaperObjectDecorator.class.php b/lib/escaper/sfOutputEscaperObjectDecorator.class.php index 86d0ae71e..ea4adcc57 100644 --- a/lib/escaper/sfOutputEscaperObjectDecorator.class.php +++ b/lib/escaper/sfOutputEscaperObjectDecorator.class.php @@ -119,7 +119,8 @@ public function __isset($key) 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) { + if (is_array($this->value) || $this->value instanceof Countable || $this->value instanceof ResourceBundle || $this->value instanceof SimpleXmlElement) + { return count($this->value); } return 1; diff --git a/lib/event/sfEvent.class.php b/lib/event/sfEvent.class.php index 750b28023..67415e7ee 100644 --- a/lib/event/sfEvent.class.php +++ b/lib/event/sfEvent.class.php @@ -83,7 +83,7 @@ public function getReturnValue() /** * Sets the processed flag. * - * @param boolean $processed The processed flag value + * @param bool $processed The processed flag value */ public function setProcessed($processed) { diff --git a/lib/exception/sfException.class.php b/lib/exception/sfException.class.php index fbd742596..9ade775db 100644 --- a/lib/exception/sfException.class.php +++ b/lib/exception/sfException.class.php @@ -367,9 +367,11 @@ static protected function formatArrayAsHtml($values) static protected function fileExcerpt($file, $line) { // $file can be null for RuntimeException - if($file === null) { + if (null === $file) + { return ''; } + if (is_readable($file)) { $content = preg_split('#
#', preg_replace('/^(.*)<\/code>$/s', '$1', highlight_file($file, true))); diff --git a/lib/i18n/sfDateFormat.class.php b/lib/i18n/sfDateFormat.class.php index 90b2aded3..91f827081 100644 --- a/lib/i18n/sfDateFormat.class.php +++ b/lib/i18n/sfDateFormat.class.php @@ -239,8 +239,7 @@ public function format($time, $pattern = 'F', $inputPattern = null, $charset = ' } else { - $function = $this->getFunctionName($pattern); - if ($function != null) + if (null !== $function = $this->getFunctionName($pattern)) { $function = ucfirst($function); $fName = 'get'.$function; diff --git a/lib/i18n/sfI18N.class.php b/lib/i18n/sfI18N.class.php index 5478e6d73..c236c9d2a 100644 --- a/lib/i18n/sfI18N.class.php +++ b/lib/i18n/sfI18N.class.php @@ -272,14 +272,8 @@ public function getTimestampForCulture($dateTime, $culture = null) list($hour, $minute) = $this->getTimeForCulture($dateTime, null === $culture ? $this->culture : $culture); // mktime behavior change with php8 - // $hour become not nullable - if (!$hour) { - $hour = 0; - } - // Before 8.0, $minutes value to null, was casted as (int)0 - if (!$minute) { - $minute = 0; - } + $hour = null !== $hour ? $hour : 0; + $minute = null !== $minute ? $minute : 0; return null === $day ? null : mktime($hour, $minute, 0, $month, $day, $year); } diff --git a/lib/log/sfFileLogger.class.php b/lib/log/sfFileLogger.class.php index eceb47255..35d269a5a 100644 --- a/lib/log/sfFileLogger.class.php +++ b/lib/log/sfFileLogger.class.php @@ -136,7 +136,8 @@ public function shutdown() */ public static function strftime($format) { - if (version_compare(PHP_VERSION, '8.1.0') < 0) { + if (version_compare(PHP_VERSION, '8.1.0') < 0) + { return strftime($format); } return date(self::_strftimeFormatToDateFormat($format)); @@ -160,8 +161,8 @@ public static function strftime($format) * * @return array|string|string[] */ - private static function _strftimeFormatToDateFormat($strftimeFormat) { - + private static function _strftimeFormatToDateFormat($strftimeFormat) + { // Missing %V %C %g %G $search = array( '%a', '%A', '%d', '%e', '%u', diff --git a/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php b/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php index 48fd0374b..f8392c7ae 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php @@ -65,7 +65,7 @@ public function check($model, $query, $value = true) } $operator = '='; - if (strlen($condition) && '!' == substr($condition,0,1)) + if (strlen($condition) && '!' == substr($condition, 0, 1)) { $operator = false !== strpos($condition, '%') ? 'NOT LIKE' : '!='; $condition = substr($condition, 1); diff --git a/lib/response/sfResponse.class.php b/lib/response/sfResponse.class.php index 905d07996..1c8e3d48c 100644 --- a/lib/response/sfResponse.class.php +++ b/lib/response/sfResponse.class.php @@ -177,7 +177,8 @@ public function unserialize($serialized) * * @return array */ - public function __serialize() { + public function __serialize() + { return array('content' => $this->content); } diff --git a/lib/routing/sfRoute.class.php b/lib/routing/sfRoute.class.php index a0093b18e..fd2ac0319 100644 --- a/lib/routing/sfRoute.class.php +++ b/lib/routing/sfRoute.class.php @@ -862,7 +862,8 @@ public function unserialize($serialized) * * @return array */ - public function __serialize() { + public function __serialize() + { // always serialize compiled routes $this->compile(); // sfPatternRouting will always re-set defaultParameters, so no need to serialize them diff --git a/lib/test/sfTestFunctionalBase.class.php b/lib/test/sfTestFunctionalBase.class.php index 97ac815a6..fc83df3b5 100644 --- a/lib/test/sfTestFunctionalBase.class.php +++ b/lib/test/sfTestFunctionalBase.class.php @@ -478,7 +478,7 @@ static public function handlePhpError($errno, $errstr, $errfile, $errline) /** * Exception handler for the current test browser instance. * - * @param Throwable $exception The exception + * @param Throwable|Exception $exception The exception */ function handleException($exception) { diff --git a/lib/test/sfTesterResponse.class.php b/lib/test/sfTesterResponse.class.php index 1a1c7a86a..7409dfc2d 100644 --- a/lib/test/sfTesterResponse.class.php +++ b/lib/test/sfTesterResponse.class.php @@ -49,8 +49,9 @@ public function initialize() } else { - if($this->response->getContent()) { - @$this->dom->loadHTML($this->response->getContent()); + if ($content = $this->response->getContent()) + { + @$this->dom->loadHTML($content); } } $this->domCssSelector = new sfDomCssSelector($this->dom); diff --git a/lib/util/sfBrowserBase.class.php b/lib/util/sfBrowserBase.class.php index 4ec39098a..535d8ac45 100755 --- a/lib/util/sfBrowserBase.class.php +++ b/lib/util/sfBrowserBase.class.php @@ -363,8 +363,9 @@ public function call($uri, $method = 'get', $parameters = array(), $changeStack } else { - if($response->getContent()) { - @$this->dom->loadHTML($response->getContent()); + if ($content = $response->getContent()) + { + @$this->dom->loadHTML($content); } } $this->domCssSelector = new sfDomCssSelector($this->dom); @@ -910,7 +911,7 @@ public function doClickElement(DOMElement $item, $arguments = array(), $options } else { - $queryString = (is_array($arguments)) ? http_build_query($arguments, null, '&') : ''; + $queryString = is_array($arguments) ? http_build_query($arguments, null, '&') : ''; $sep = false === strpos($url, '?') ? '?' : '&'; return array($url.($queryString ? $sep.$queryString : ''), 'get', array()); diff --git a/lib/util/sfNamespacedParameterHolder.class.php b/lib/util/sfNamespacedParameterHolder.class.php index 757d86edd..03008a030 100644 --- a/lib/util/sfNamespacedParameterHolder.class.php +++ b/lib/util/sfNamespacedParameterHolder.class.php @@ -395,7 +395,7 @@ public function __serialize() } /** - * Unserializes a sfParameterHolder instance. for PHP 7.4 + * Unserializes a sfParameterHolder instance for PHP 7.4+ * * @param array $data */ diff --git a/lib/util/sfParameterHolder.class.php b/lib/util/sfParameterHolder.class.php index aecd57435..b4d57b6d5 100644 --- a/lib/util/sfParameterHolder.class.php +++ b/lib/util/sfParameterHolder.class.php @@ -203,13 +203,13 @@ public function unserialize($serialized) * * @return Array */ - public function __serialize() { - + public function __serialize() + { return $this->parameters; } /** - * Unserializes a sfParameterHolder instance. for PHP 7.4 + * Unserializes a sfParameterHolder instance for PHP 7.4+ * * @param array $data */ diff --git a/lib/vendor/lime/lime.php b/lib/vendor/lime/lime.php index 5b3c16560..2d5f8986e 100644 --- a/lib/vendor/lime/lime.php +++ b/lib/vendor/lime/lime.php @@ -589,7 +589,7 @@ public function handle_error($code, $message, $file, $line, $context = null) } /** - * @param Throwable $exception only available on php7 + * @param Throwable|Exception $exception * @return bool */ public function handle_exception($exception) @@ -1103,7 +1103,8 @@ function lime_shutdown() $this->output->comment(sprintf(' at %s line %s', $this->get_relative_file($testsuite['tests'][$testcase]['file']).$this->extension, $testsuite['tests'][$testcase]['line'])); $this->output->info(' '.$testsuite['tests'][$testcase]['message']); - if(isset($testsuite['tests'][$testcase]['error'])) { + if (isset($testsuite['tests'][$testcase]['error'])) + { $this->output->echoln($testsuite['tests'][$testcase]['error'], null, false); } } diff --git a/lib/view/sfViewParameterHolder.class.php b/lib/view/sfViewParameterHolder.class.php index 4cc6d636c..3d8c63f18 100644 --- a/lib/view/sfViewParameterHolder.class.php +++ b/lib/view/sfViewParameterHolder.class.php @@ -193,7 +193,7 @@ public function __serialize() } /** - * Unserializes a sfParameterHolder instance. for PHP 7.4 + * Unserializes a sfParameterHolder instance for PHP 7.4+ * * @param array $data */ diff --git a/lib/widget/sfWidgetFormDate.class.php b/lib/widget/sfWidgetFormDate.class.php index c8ed674df..9c87946b7 100644 --- a/lib/widget/sfWidgetFormDate.class.php +++ b/lib/widget/sfWidgetFormDate.class.php @@ -70,7 +70,7 @@ public function render($name, $value = null, $attributes = array(), $errors = ar } else { - $value = (string) $value == (string) (integer) $value ? (integer) $value : strtotime( (string) $value); + $value = (string) $value == (string) (integer) $value ? (integer) $value : strtotime((string) $value); if (false === $value) { $value = $default; diff --git a/lib/widget/sfWidgetFormTime.class.php b/lib/widget/sfWidgetFormTime.class.php index 5917ed841..4a90d957b 100644 --- a/lib/widget/sfWidgetFormTime.class.php +++ b/lib/widget/sfWidgetFormTime.class.php @@ -72,7 +72,7 @@ public function render($name, $value = null, $attributes = array(), $errors = ar } else { - $value = ctype_digit( (string) $value) ? (integer) $value : strtotime( (string) $value); + $value = ctype_digit((string) $value) ? (integer) $value : strtotime((string) $value); if (false === $value) { $value = $default; diff --git a/lib/yaml/sfYamlParser.class.php b/lib/yaml/sfYamlParser.class.php index ed5b179ee..3cf5580b1 100644 --- a/lib/yaml/sfYamlParser.class.php +++ b/lib/yaml/sfYamlParser.class.php @@ -421,7 +421,7 @@ protected function parseValue($value) { $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : ''; - return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs((int) $modifiers)); + return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), abs((int) $modifiers)); } else { From 01fadb98ff556c2d66988941dddc5090d8e830d9 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Tue, 2 Aug 2022 14:34:54 +0200 Subject: [PATCH 23/43] PHP 8.1 > Better MYSQLI_REPORT_OFF implementations for php8.1 compat Thanks @mentalstring --- lib/database/sfMySQLiDatabase.class.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/database/sfMySQLiDatabase.class.php b/lib/database/sfMySQLiDatabase.class.php index bdc8be447..cb13c1edc 100644 --- a/lib/database/sfMySQLiDatabase.class.php +++ b/lib/database/sfMySQLiDatabase.class.php @@ -18,6 +18,18 @@ class sfMySQLiDatabase extends sfMySQLDatabase { + /** + * @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(); + } + /** * Returns the appropriate connect method. * @@ -29,9 +41,6 @@ class sfMySQLiDatabase extends sfMySQLDatabase */ protected function getConnectMethod($persistent) { - // PHP 8.1 Activate Exception per default, revert behavior to "return false" - mysqli_report(MYSQLI_REPORT_OFF); - return 'mysqli_connect'; } From 3bb8339eb0e7401f2ed3fed9de861b4b2ebd8064 Mon Sep 17 00:00:00 2001 From: Paulo Magalhaes Date: Fri, 12 Aug 2022 22:37:57 +0100 Subject: [PATCH 24/43] PHP 8.1 > remove full_path from uploads added on PHP v8.1 --- lib/request/sfWebRequest.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/request/sfWebRequest.class.php b/lib/request/sfWebRequest.class.php index bf35cbcb4..cf7549fad 100644 --- a/lib/request/sfWebRequest.class.php +++ b/lib/request/sfWebRequest.class.php @@ -872,6 +872,9 @@ static public function convertFileInformation(array $taintedFiles) */ static protected function fixPhpFilesArray(array $data) { + // remove full_path added on php8.1 + unset($data['full_path']); + $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type'); $keys = array_keys($data); sort($keys); From 77983281163bcab2969dbbf33ee5e2ee8bc86671 Mon Sep 17 00:00:00 2001 From: Paulo Magalhaes Date: Fri, 12 Aug 2022 23:40:02 +0200 Subject: [PATCH 25/43] Fix use of null on string parameter on multiple classes --- lib/generator/sfModelGenerator.class.php | 2 +- lib/util/sfBrowserBase.class.php | 2 +- lib/view/sfViewCacheManager.class.php | 4 ++-- test/unit/sfNoRouting.class.php | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/generator/sfModelGenerator.class.php b/lib/generator/sfModelGenerator.class.php index b52a2570a..e84a7e1fc 100644 --- a/lib/generator/sfModelGenerator.class.php +++ b/lib/generator/sfModelGenerator.class.php @@ -273,7 +273,7 @@ public function renderField($field) } else if ('Date' == $field->getType()) { - $html = sprintf("false !== strtotime($html) ? format_date(%s, \"%s\") : ' '", $html, $field->getConfig('date_format', 'f')); + $html = sprintf("is_string($html) && false !== strtotime($html) ? format_date(%s, \"%s\") : ' '", $html, $field->getConfig('date_format', 'f')); } else if ('Boolean' == $field->getType()) { diff --git a/lib/util/sfBrowserBase.class.php b/lib/util/sfBrowserBase.class.php index 535d8ac45..4267bb0a9 100755 --- a/lib/util/sfBrowserBase.class.php +++ b/lib/util/sfBrowserBase.class.php @@ -911,7 +911,7 @@ public function doClickElement(DOMElement $item, $arguments = array(), $options } else { - $queryString = is_array($arguments) ? http_build_query($arguments, null, '&') : ''; + $queryString = is_array($arguments) ? http_build_query($arguments, '', '&') : ''; $sep = false === strpos($url, '?') ? '?' : '&'; return array($url.($queryString ? $sep.$queryString : ''), 'get', array()); diff --git a/lib/view/sfViewCacheManager.class.php b/lib/view/sfViewCacheManager.class.php index f055e50f1..70198e10f 100644 --- a/lib/view/sfViewCacheManager.class.php +++ b/lib/view/sfViewCacheManager.class.php @@ -1005,8 +1005,8 @@ public function getCurrentCacheKey() if ($getParameters = $this->request->getGetParameters()) { - $cacheKey .= false === strpos($cacheKey, '?') ? '?' : '&'; - $cacheKey .= http_build_query($getParameters, null, '&'); + $cacheKey .= false === strpos((string) $cacheKey, '?') ? '?' : '&'; + $cacheKey .= http_build_query($getParameters, '', '&'); } return $cacheKey; diff --git a/test/unit/sfNoRouting.class.php b/test/unit/sfNoRouting.class.php index 2899cccb0..fc13704c4 100644 --- a/test/unit/sfNoRouting.class.php +++ b/test/unit/sfNoRouting.class.php @@ -29,7 +29,7 @@ public function getCurrentInternalUri($with_route_name = false) // other parameters unset($parameters['module'], $parameters['action']); ksort($parameters); - $parameters = count($parameters) ? '?'.http_build_query($parameters, null, '&') : ''; + $parameters = count($parameters) ? '?'.http_build_query($parameters, '', '&') : ''; return sprintf('%s%s', $action, $parameters); } @@ -49,7 +49,7 @@ public function generate($name, $params = array(), $absolute = false) unset($parameters['action']); } - $parameters = http_build_query($parameters, null, '&'); + $parameters = http_build_query($parameters, '', '&'); return $this->fixGeneratedUrl('/'.($parameters ? '?'.$parameters : ''), $absolute); } From 1e9b188eeccb5185d70e49d5737fd408ef79e6e8 Mon Sep 17 00:00:00 2001 From: thePanz Date: Fri, 25 Nov 2022 16:34:43 +0100 Subject: [PATCH 26/43] Github Actions: enable testing on PHP v8.0 and v8.1 (for PRs too) --- .github/workflows/continuous-integration.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 13d1bdfa7..78e07a5d0 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -1,6 +1,10 @@ name: "Continuous Integration" -on: [push] +on: + push: + branches: + - master + pull_request: env: fail-fast: true @@ -14,8 +18,8 @@ jobs: matrix: php-version: - "7.4" - # - "8.0" - # - "8.1" + - "8.0" + - "8.1" memcached-version: - "1.6" From fa161a1e93e8ec52064d7023861727d5a8168c46 Mon Sep 17 00:00:00 2001 From: "Thomas A. Hirsch" Date: Tue, 13 Dec 2022 19:52:34 +0100 Subject: [PATCH 27/43] test environment for php 8.2 --- .docker/{php74_81 => php74_82}/Dockerfile | 0 .github/workflows/continuous-integration.yml | 1 + docker-compose.yml | 15 ++++++++++++--- 3 files changed, 13 insertions(+), 3 deletions(-) rename .docker/{php74_81 => php74_82}/Dockerfile (100%) diff --git a/.docker/php74_81/Dockerfile b/.docker/php74_82/Dockerfile similarity index 100% rename from .docker/php74_81/Dockerfile rename to .docker/php74_82/Dockerfile diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 78e07a5d0..b27f75493 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -20,6 +20,7 @@ jobs: - "7.4" - "8.0" - "8.1" + - "8.2" memcached-version: - "1.6" diff --git a/docker-compose.yml b/docker-compose.yml index b18e91032..373560b09 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -129,7 +129,7 @@ services: php74: <<: *services_php54 build: - context: .docker/php74_81 + context: .docker/php74_82 args: PHP_VERSION: '7.4' MEMCACHE_VERSION: '4.0.5.2' @@ -139,7 +139,7 @@ services: php80: <<: *services_php54 build: - context: .docker/php74_81 + context: .docker/php74_82 args: PHP_VERSION: '8.0' MEMCACHE_VERSION: '8.0' @@ -149,12 +149,21 @@ services: php81: <<: *services_php54 build: - context: .docker/php74_81 + context: .docker/php74_82 args: PHP_VERSION: '8.1' MEMCACHE_VERSION: '8.0' APCU_VERSION: '' + php82: + <<: *services_php54 + build: + context: .docker/php74_82 + args: + PHP_VERSION: '8.2' + MEMCACHE_VERSION: '8.0' + APCU_VERSION: '' + db: image: mysql:5.5.62 From f6d779cc48d2295722366209dcaf4f956ad55ec9 Mon Sep 17 00:00:00 2001 From: "Thomas A. Hirsch" Date: Tue, 13 Dec 2022 19:54:03 +0100 Subject: [PATCH 28/43] PHP 8.2 > Using ${var} in strings is deprecated, use {$var} instead. --- lib/command/sfAnsiColorFormatter.class.php | 2 +- lib/task/help/sfHelpTask.class.php | 2 +- lib/task/help/sfListTask.class.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/command/sfAnsiColorFormatter.class.php b/lib/command/sfAnsiColorFormatter.class.php index 904da78b2..2f6c29e14 100644 --- a/lib/command/sfAnsiColorFormatter.class.php +++ b/lib/command/sfAnsiColorFormatter.class.php @@ -100,7 +100,7 @@ public function formatSection($section, $text, $size = null, $style = 'INFO') $style = array_key_exists($style, $this->styles) ? $style : 'INFO'; $width = 9 + strlen($this->format('', $style)); - return sprintf(">> %-${width}s %s", $this->format($section, $style), $this->excerpt($text, $size - 4 - (strlen($section) > 9 ? strlen($section) : 9))); + return sprintf(">> %-{$width}s %s", $this->format($section, $style), $this->excerpt($text, $size - 4 - (strlen($section) > 9 ? strlen($section) : 9))); } /** diff --git a/lib/task/help/sfHelpTask.class.php b/lib/task/help/sfHelpTask.class.php index 1f4ac9e21..b386bd3f7 100644 --- a/lib/task/help/sfHelpTask.class.php +++ b/lib/task/help/sfHelpTask.class.php @@ -96,7 +96,7 @@ protected function outputAsText(sfTask $task) foreach ($task->getArguments() as $argument) { $default = null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault())) ? $this->formatter->format(sprintf(' (default: %s)', is_array($argument->getDefault()) ? str_replace("\n", '', print_r($argument->getDefault(), true)): $argument->getDefault()), 'COMMENT') : ''; - $messages[] = sprintf(" %-${max}s %s%s", $this->formatter->format($argument->getName(), 'INFO'), $argument->getHelp(), $default); + $messages[] = sprintf(" %-{$max}s %s%s", $this->formatter->format($argument->getName(), 'INFO'), $argument->getHelp(), $default); } $messages[] = ''; diff --git a/lib/task/help/sfListTask.class.php b/lib/task/help/sfListTask.class.php index c167ae807..38354c33f 100644 --- a/lib/task/help/sfListTask.class.php +++ b/lib/task/help/sfListTask.class.php @@ -120,7 +120,7 @@ protected function outputAsText($namespace, $tasks) $aliases = $task->getAliases() ? $this->formatter->format(' ('.implode(', ', $task->getAliases()).')', 'COMMENT') : ''; - $messages[] = sprintf(" %-${width}s %s%s", $this->formatter->format(':'.$task->getName(), 'INFO'), $task->getBriefDescription(), $aliases); + $messages[] = sprintf(" %-{$width}s %s%s", $this->formatter->format(':'.$task->getName(), 'INFO'), $task->getBriefDescription(), $aliases); } $this->log($messages); From d89618fc27b3efa2a758a10a9f3ffd312300f583 Mon Sep 17 00:00:00 2001 From: "Thomas A. Hirsch" Date: Tue, 13 Dec 2022 19:57:10 +0100 Subject: [PATCH 29/43] PHP 8.2 > Creation of dynamic property Class::$property is deprecated --- .../lib/database/sfDoctrineConnectionListener.class.php | 4 ++++ lib/routing/sfRoute.class.php | 7 +++---- lib/task/sfBaseTask.class.php | 4 +++- lib/util/sfBrowser.class.php | 3 ++- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineConnectionListener.class.php b/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineConnectionListener.class.php index ad39b2aae..5129020ad 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineConnectionListener.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineConnectionListener.class.php @@ -20,6 +20,10 @@ */ class sfDoctrineConnectionListener extends Doctrine_EventListener { + protected + $connection, + $encoding; + public function __construct($connection, $encoding) { $this->connection = $connection; diff --git a/lib/routing/sfRoute.class.php b/lib/routing/sfRoute.class.php index fd2ac0319..f8a6ea7a5 100644 --- a/lib/routing/sfRoute.class.php +++ b/lib/routing/sfRoute.class.php @@ -15,9 +15,6 @@ * @subpackage routing * @author Fabien Potencier * @version SVN: $Id$ - * - * @property $firstOptional int - * @property $segments array */ class sfRoute implements Serializable { @@ -37,7 +34,9 @@ class sfRoute implements Serializable $defaults = array(), $requirements = array(), $tokens = array(), - $customToken = false; + $customToken = false, + $firstOptional = null, + $segments = array(); /** * Constructor. diff --git a/lib/task/sfBaseTask.class.php b/lib/task/sfBaseTask.class.php index 564a0be6c..247576054 100644 --- a/lib/task/sfBaseTask.class.php +++ b/lib/task/sfBaseTask.class.php @@ -21,7 +21,9 @@ abstract class sfBaseTask extends sfCommandApplicationTask protected $configuration = null, $pluginManager = null, - $statusStartTime = null; + $statusStartTime = null, + $filesystem = null, + $tokens = array(); /** * @see sfTask diff --git a/lib/util/sfBrowser.class.php b/lib/util/sfBrowser.class.php index ad45e1225..ec13e4460 100644 --- a/lib/util/sfBrowser.class.php +++ b/lib/util/sfBrowser.class.php @@ -21,7 +21,8 @@ class sfBrowser extends sfBrowserBase protected $listeners = array(), $context = null, - $currentException = null; + $currentException = null, + $rawConfiguration = array(); /** * Calls a request to a uri. From 89c24cf5cc518f13193b8940b40ccb5ed906fb9a Mon Sep 17 00:00:00 2001 From: "Thomas A. Hirsch" Date: Tue, 13 Dec 2022 20:03:00 +0100 Subject: [PATCH 30/43] PHP 8.0 > Uncaught ArgumentCountError: Too few arguments to function --- lib/task/project/sfProjectPermissionsTask.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/task/project/sfProjectPermissionsTask.class.php b/lib/task/project/sfProjectPermissionsTask.class.php index 72b3b7620..c5b5d9b0c 100644 --- a/lib/task/project/sfProjectPermissionsTask.class.php +++ b/lib/task/project/sfProjectPermissionsTask.class.php @@ -112,7 +112,7 @@ protected function chmod($file, $mode, $umask = 0000) * * @see http://www.php.net/set_error_handler */ - public function handleError($no, $string, $file, $line, $context) + public function handleError($no, $string, $file, $line, $context = null) { $this->failed[] = $this->current; } From 754c940232355aaed6f96f3d4bfb316a092d6294 Mon Sep 17 00:00:00 2001 From: "Thomas A. Hirsch" Date: Tue, 13 Dec 2022 20:09:26 +0100 Subject: [PATCH 31/43] PHP 8.0 > Trying to access array offset on value of type bool --- lib/yaml/sfYamlInline.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yaml/sfYamlInline.class.php b/lib/yaml/sfYamlInline.class.php index 840f3fa7a..0957595ac 100644 --- a/lib/yaml/sfYamlInline.class.php +++ b/lib/yaml/sfYamlInline.class.php @@ -168,7 +168,7 @@ static protected function dumpArray($value) */ static public function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true) { - if (in_array($scalar[$i], $stringDelimiters)) + if (is_string($scalar) && in_array($scalar[$i], $stringDelimiters)) { // quoted scalar $output = self::parseQuotedScalar($scalar, $i); From 13bfee2aa0bc140870159274ad5a7f2d42aa6115 Mon Sep 17 00:00:00 2001 From: "Thomas A. Hirsch" Date: Tue, 13 Dec 2022 20:10:13 +0100 Subject: [PATCH 32/43] PHP 8.0 > Passing null to parameter #1 ($haystack) of type string is deprecated --- lib/yaml/sfYamlInline.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yaml/sfYamlInline.class.php b/lib/yaml/sfYamlInline.class.php index 0957595ac..97d8c5b03 100644 --- a/lib/yaml/sfYamlInline.class.php +++ b/lib/yaml/sfYamlInline.class.php @@ -272,7 +272,7 @@ static protected function parseSequence($sequence, &$i = 0) $isQuoted = in_array($sequence[$i], array('"', "'")); $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i); - if (!$isQuoted && false !== strpos($value, ': ')) + if (!$isQuoted && false !== strpos((string) $value, ': ')) { // embedded mapping? try From 5d94af72bf06686fc92c0b3139d49893846689a7 Mon Sep 17 00:00:00 2001 From: "Thomas A. Hirsch" Date: Tue, 13 Dec 2022 13:15:52 +0100 Subject: [PATCH 33/43] set symfony version to 1.5.15-dev --- lib/autoload/sfCoreAutoload.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/autoload/sfCoreAutoload.class.php b/lib/autoload/sfCoreAutoload.class.php index 5e1604f79..00f558f8e 100755 --- a/lib/autoload/sfCoreAutoload.class.php +++ b/lib/autoload/sfCoreAutoload.class.php @@ -11,7 +11,7 @@ /** * The current symfony version. */ -define('SYMFONY_VERSION', '1.5.14-dev'); +define('SYMFONY_VERSION', '1.5.15-dev'); /** * sfCoreAutoload class. From 4820ada503deb3ee0e2257c8e95d668770e6dbac Mon Sep 17 00:00:00 2001 From: "Thomas A. Hirsch" Date: Tue, 13 Dec 2022 13:25:38 +0100 Subject: [PATCH 34/43] PHP 8.0 > Class name must be a valid object or a string in case the controller does not exist. --- lib/controller/sfController.class.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/controller/sfController.class.php b/lib/controller/sfController.class.php index 1d1deec76..6b69b857d 100644 --- a/lib/controller/sfController.class.php +++ b/lib/controller/sfController.class.php @@ -299,7 +299,10 @@ protected function getController($moduleName, $controllerName, $extension) $classSuffix = ucfirst(strtolower($extension)); if (!isset($this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix])) { - $this->controllerExists($moduleName, $controllerName, $extension, true); + if (!$this->controllerExists($moduleName, $controllerName, $extension, true)) + { + return null; + } } $class = $this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix]; From c55d53c0055f70e6ea109e9ddc7bc498d3d66a29 Mon Sep 17 00:00:00 2001 From: "Thomas A. Hirsch" Date: Tue, 13 Dec 2022 13:26:17 +0100 Subject: [PATCH 35/43] PHP 8.0 > Fix undefined array key --- lib/escaper/sfOutputEscaperArrayDecorator.class.php | 3 ++- lib/response/sfWebResponse.class.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/escaper/sfOutputEscaperArrayDecorator.class.php b/lib/escaper/sfOutputEscaperArrayDecorator.class.php index 6b87a4322..5cc37aaf6 100644 --- a/lib/escaper/sfOutputEscaperArrayDecorator.class.php +++ b/lib/escaper/sfOutputEscaperArrayDecorator.class.php @@ -124,7 +124,8 @@ public function offsetExists($offset) #[\ReturnTypeWillChange] public function offsetGet($offset) { - return sfOutputEscaper::escape($this->escapingMethod, $this->value[$offset]); + $value = isset($this->value[$offset]) ? $this->value[$offset] : null; + return sfOutputEscaper::escape($this->escapingMethod, $value); } /** diff --git a/lib/response/sfWebResponse.class.php b/lib/response/sfWebResponse.class.php index af69e38e2..3bdc87639 100644 --- a/lib/response/sfWebResponse.class.php +++ b/lib/response/sfWebResponse.class.php @@ -365,7 +365,8 @@ public function sendHttpHeaders() // cookies foreach ($this->cookies as $cookie) { - setrawcookie($cookie['name'], $cookie['value'], $cookie['expire'], $cookie['path'], $cookie['domain'], $cookie['secure'], $cookie['httpOnly']); + $expire = isset($cookie['expire']) ? $cookie['expire'] : 0; + setrawcookie($cookie['name'], $cookie['value'], $expire, $cookie['path'], $cookie['domain'], $cookie['secure'], $cookie['httpOnly']); if ($this->options['logging']) { From 8b81a568e1efaebe3455974ef17a0c0a2c4b7e7b Mon Sep 17 00:00:00 2001 From: "Thomas A. Hirsch" Date: Tue, 13 Dec 2022 13:27:15 +0100 Subject: [PATCH 36/43] PHP 8.1 > Fix some more null on string parameter --- lib/config/sfViewConfigHandler.class.php | 2 +- lib/request/sfWebRequest.class.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/config/sfViewConfigHandler.class.php b/lib/config/sfViewConfigHandler.class.php index f3b681bb0..8068fd57c 100644 --- a/lib/config/sfViewConfigHandler.class.php +++ b/lib/config/sfViewConfigHandler.class.php @@ -223,7 +223,7 @@ protected function addHtmlHead($viewName = '') foreach ($this->mergeConfigValue('metas', $viewName) as $name => $content) { - $data[] = sprintf(" \$response->addMeta('%s', '%s', false, false);", $name, str_replace('\'', '\\\'', preg_replace('/&(?=\w+;)/', '&', htmlspecialchars($content, ENT_QUOTES, sfConfig::get('sf_charset'))))); + $data[] = sprintf(" \$response->addMeta('%s', '%s', false, false);", $name, str_replace('\'', '\\\'', preg_replace('/&(?=\w+;)/', '&', htmlspecialchars((string) $content, ENT_QUOTES, sfConfig::get('sf_charset'))))); } return implode("\n", $data)."\n"; diff --git a/lib/request/sfWebRequest.class.php b/lib/request/sfWebRequest.class.php index cf7549fad..99f8616e3 100644 --- a/lib/request/sfWebRequest.class.php +++ b/lib/request/sfWebRequest.class.php @@ -192,7 +192,7 @@ public function getContentType($trim = true) { $contentType = $this->getHttpHeader('Content-Type', null); - if ($trim && false !== $pos = strpos($contentType, ';')) + if ($trim && false !== $pos = strpos((string) $contentType, ';')) { $contentType = substr($contentType, 0, $pos); } From e432434991623b076cb87d0d9a31d2e08f5ab4cd Mon Sep 17 00:00:00 2001 From: "Thomas A. Hirsch" Date: Tue, 10 Jan 2023 15:37:40 +0100 Subject: [PATCH 37/43] Prepared release 1.5.15 --- CHANGELOG.md | 18 ++++++++++++++++++ README.md | 2 +- lib/autoload/sfCoreAutoload.class.php | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33855aef2..432f8669a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,24 @@ CHANGELOG ========= +??/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 e5147ca4d..4b285a0b0 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ All the enhancements and BC breaks are listed in the [WHATS_NEW](https://github. - [DIC](https://github.com/FriendsOfSymfony1/symfony1/wiki/ServiceContainer) - Composer support -- PHP 8.1 support +- PHP 8.2 support - performance boost - new widgets & validators - some tickets fixed from the symfony trac diff --git a/lib/autoload/sfCoreAutoload.class.php b/lib/autoload/sfCoreAutoload.class.php index 00f558f8e..a8f15264c 100755 --- a/lib/autoload/sfCoreAutoload.class.php +++ b/lib/autoload/sfCoreAutoload.class.php @@ -11,7 +11,7 @@ /** * The current symfony version. */ -define('SYMFONY_VERSION', '1.5.15-dev'); +define('SYMFONY_VERSION', '1.5.15'); /** * sfCoreAutoload class. From 9945f3f27cdc5aac36f5e8c60485e5c9d5df86f2 Mon Sep 17 00:00:00 2001 From: thePanz Date: Thu, 12 Jan 2023 14:07:07 +0100 Subject: [PATCH 38/43] Add(changelog) Add v1.5.15 release date to Changelog file --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 432f8669a..48eafda6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ CHANGELOG ========= -??/01/2023: Version 1.5.15 +12/01/2023: Version 1.5.15 -------------------------- * Add support for PHP 8.2 by @thirsch in #274 From 31d2c602a51e6c43c4370791f6c96c7ee1fefff2 Mon Sep 17 00:00:00 2001 From: thePanz Date: Thu, 12 Jan 2023 14:15:04 +0100 Subject: [PATCH 39/43] Add(versioning) Add v1.5.16-dev as next release --- CHANGELOG.md | 4 ++++ lib/autoload/sfCoreAutoload.class.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48eafda6f..656732e6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ CHANGELOG ========= +xx/xx/xxxx: Version 1.5.16 +-------------------------- + + 12/01/2023: Version 1.5.15 -------------------------- diff --git a/lib/autoload/sfCoreAutoload.class.php b/lib/autoload/sfCoreAutoload.class.php index a8f15264c..ff6dfce1b 100755 --- a/lib/autoload/sfCoreAutoload.class.php +++ b/lib/autoload/sfCoreAutoload.class.php @@ -11,7 +11,7 @@ /** * The current symfony version. */ -define('SYMFONY_VERSION', '1.5.15'); +define('SYMFONY_VERSION', '1.5.16-dev'); /** * sfCoreAutoload class. From 2c5a4d625d1853cb207dfbb73817505831874371 Mon Sep 17 00:00:00 2001 From: Emanuele Panzeri Date: Fri, 13 Jan 2023 15:02:03 +0100 Subject: [PATCH 40/43] Fix(deprecations) Fix deprecations in sfMessageSource_Aggregate (#277) * Fix(deprecations) Fix deprecations in sfMessageSource_Aggregate, add return types from implemented sfIMessageSource --- CHANGELOG.md | 1 + lib/i18n/sfMessageSource_Aggregate.class.php | 69 +++++++++++++++++++- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 656732e6d..20c65db4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ CHANGELOG ========= +======= xx/xx/xxxx: Version 1.5.16 -------------------------- diff --git a/lib/i18n/sfMessageSource_Aggregate.class.php b/lib/i18n/sfMessageSource_Aggregate.class.php index 14c89aeea..3270f76d9 100644 --- a/lib/i18n/sfMessageSource_Aggregate.class.php +++ b/lib/i18n/sfMessageSource_Aggregate.class.php @@ -18,8 +18,7 @@ */ class sfMessageSource_Aggregate extends sfMessageSource { - protected - $messageSources = array(); + protected $messageSources = array(); /** * Constructor. @@ -46,6 +45,12 @@ public function setCulture($culture) } } + /** + * Gets the last modified unix-time for this particular catalogue+variant. + * + * @param string $source catalogue+variant + * @return int last modified in unix-time format. + */ protected function getLastModified($sources) { $lastModified = time(); @@ -60,6 +65,12 @@ protected function getLastModified($sources) return $lastModified; } + /** + * Determines if the source is valid. + * + * @param string $source catalogue+variant + * @return boolean true if valid, false otherwise. + */ public function isValidSource($sources) { foreach ($sources as $source) @@ -75,6 +86,12 @@ public function isValidSource($sources) return false; } + /** + * Gets the source, this could be a filename or database ID. + * + * @param string $variant catalogue+variant + * @return string the resource key + */ public function getSource($variant) { $sources = array(); @@ -86,6 +103,12 @@ public function getSource($variant) return $sources; } + /** + * Loads the message for a particular catalogue+variant. + * This methods needs to implemented by subclasses. + * + * @return array of translation messages. + */ public function &loadData($sources) { $messages = array(); @@ -106,6 +129,13 @@ public function &loadData($sources) return $messages; } + /** + * Gets all the variants of a particular catalogue. + * This method must be implemented by subclasses. + * + * @param string $catalogue catalogue name + * @return array list of all variants for this catalogue. + */ public function getCatalogueList($catalogue) { $variants = array(); @@ -120,6 +150,12 @@ public function getCatalogueList($catalogue) return $variants; } + /** + * Adds a untranslated message to the source. Need to call save() + * to save the messages to source. + * + * @param string $message message to add + */ public function append($message) { // Append to the first message source only @@ -129,6 +165,15 @@ public function append($message) } } + /** + * Updates the translation. + * + * @param string $text the source string. + * @param string $target the new translation string. + * @param string $comments comments + * @param string $catalogue the catalogue of the translation. + * @return boolean true if translation was updated, false otherwise. + */ public function update($text, $target, $comments, $catalogue = 'messages') { // Only update one message source @@ -143,6 +188,13 @@ public function update($text, $target, $comments, $catalogue = 'messages') return false; } + /** + * Deletes a particular message from the specified catalogue. + * + * @param string $message the source message to delete. + * @param string $catalogue the catalogue to delete from. + * @return boolean true if deleted, false otherwise. + */ public function delete($message, $catalogue = 'messages') { $retval = false; @@ -157,6 +209,14 @@ public function delete($message, $catalogue = 'messages') return $retval; } + /** + * Saves the list of untranslated blocks to the translation source. + * If the translation was not found, you should add those + * strings to the translation source via the append() method. + * + * @param string $catalogue the catalogue to add to + * @return boolean true if saved successfuly, false otherwise. + */ public function save($catalogue = 'messages') { $retval = false; @@ -182,6 +242,11 @@ public function getId() return md5($id); } + /** + * Returns a list of catalogue as key and all it variants as value. + * + * @return array list of catalogues + */ public function catalogues() { throw new sfException('The "catalogues()" method is not implemented for this message source.'); From ffbbce6eff0f0f92397c85eb66f255e877def2cc Mon Sep 17 00:00:00 2001 From: Karoly Gossler Date: Tue, 10 Jan 2023 17:59:53 +0100 Subject: [PATCH 41/43] Add(linting) Add code linting to GitHub workflow, use php-cs-fixer --- .github/workflows/lint.yml | 31 +++++++++++++++++++++++++++++++ .gitignore | 1 + .php-cs-fixer.dist.php | 29 +++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 .github/workflows/lint.yml create mode 100644 .php-cs-fixer.dist.php diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 000000000..3f797cef8 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,31 @@ +name: "Code Linting" +on: + push: + branches: + - master + pull_request: + +jobs: + php-cs-fixer: + name: 'PHP-CS-Fixer' + runs-on: 'ubuntu-latest' + steps: + - uses: 'actions/checkout@v3' + + - name: 'Setup PHP' + uses: 'shivammathur/setup-php@v2' + with: + php-version: '8.1' + tools: php-cs-fixer, cs2pr + + - uses: 'actions/cache@v3' + with: + path: '.php-cs-fixer.cache' + key: '${{ github.repository }}-8.1-phpcsfixer-${{ github.ref_name }}' + restore-keys: | + ${{ github.repository }}-8.1-phpcsfixer-main + ${{ github.repository }}-8.1-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..3c17d4767 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ lib/plugins/sfDoctrinePlugin/test/functional/fixtures/log/ /vendor /composer.lock +.php-cs-fixer.cache diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 000000000..f5e11f987 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,29 @@ +ignoreVCSIgnored(true) + ->in(__DIR__.'/lib') + ->in(__DIR__.'/data/bin') + ->in(__DIR__.'/test') + ->append(array(__FILE__)) + // Exclude PHP classes templates/generators, which are not valid PHP files + ->exclude('task/generator/skeleton/') + ->exclude('plugins/sfDoctrinePlugin/data/generator/') + // 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(array( + '@PhpCsFixer' => true, + '@Symfony' => true, + 'array_syntax' => array( + 'syntax' => 'long', + ), +)) + ->setCacheFile('.php-cs-fixer.cache') + ->setFinder($finder) +; + +return $config; From 2cbd557118d92e0d5517129aab24f29fe0b86c2e Mon Sep 17 00:00:00 2001 From: thePanz Date: Mon, 20 Feb 2023 22:53:56 +0100 Subject: [PATCH 42/43] Fix(php-cs) Fix php-cs styles according to configuration --- .editorconfig | 2 +- data/bin/changelog.php | 31 +- data/bin/check_configuration.php | 77 +- data/bin/release.php | 90 +- data/bin/sandbox_installer.php | 14 +- lib/action/sfAction.class.php | 953 +++--- 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 | 27 +- lib/addon/sfData.class.php | 180 +- lib/addon/sfPager.class.php | 1147 ++++--- lib/autoload/sfAutoload.class.php | 350 +-- lib/autoload/sfAutoloadAgain.class.php | 182 +- lib/autoload/sfCoreAutoload.class.php | 972 +++--- lib/autoload/sfSimpleAutoload.class.php | 497 ++- lib/cache/sfAPCCache.class.php | 305 +- lib/cache/sfCache.class.php | 427 ++- lib/cache/sfEAcceleratorCache.class.php | 283 +- lib/cache/sfFileCache.class.php | 531 ++-- lib/cache/sfFunctionCache.class.php | 158 +- lib/cache/sfMemcacheCache.class.php | 465 ++- lib/cache/sfNoCache.class.php | 131 +- lib/cache/sfSQLiteCache.class.php | 507 ++-- lib/cache/sfXCacheCache.class.php | 323 +- lib/command/cli.php | 46 +- lib/command/sfAnsiColorFormatter.class.php | 179 +- lib/command/sfCommandApplication.class.php | 1161 ++++--- 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 | 1131 ++++--- lib/config/sfAutoloadConfigHandler.class.php | 273 +- lib/config/sfCacheConfigHandler.class.php | 171 +- lib/config/sfCompileConfigHandler.class.php | 118 +- lib/config/sfConfig.class.php | 132 +- lib/config/sfConfigCache.class.php | 584 ++-- lib/config/sfConfigHandler.class.php | 189 +- lib/config/sfDatabaseConfigHandler.class.php | 209 +- ...sfDefineEnvironmentConfigHandler.class.php | 217 +- lib/config/sfFactoryConfigHandler.class.php | 464 +-- lib/config/sfFilterConfigHandler.class.php | 315 +- lib/config/sfGeneratorConfigHandler.class.php | 118 +- 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 | 72 +- lib/config/sfServiceConfigHandler.class.php | 88 +- .../sfSimpleYamlConfigHandler.class.php | 53 +- lib/config/sfViewConfigHandler.class.php | 504 ++-- 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 | 318 +- lib/database/sfDatabase.class.php | 287 +- lib/database/sfDatabaseManager.class.php | 183 +- lib/database/sfMySQLDatabase.class.php | 154 +- lib/database/sfMySQLiDatabase.class.php | 88 +- lib/database/sfPDODatabase.class.php | 137 +- lib/database/sfPostgreSQLDatabase.class.php | 85 +- lib/debug/sfDebug.class.php | 414 ++- 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 | 102 +- lib/debug/sfWebDebugPanelLogs.class.php | 160 +- 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 | 567 ++-- lib/escaper/sfOutputEscaper.class.php | 379 ++- .../sfOutputEscaperArrayDecorator.class.php | 336 +-- .../sfOutputEscaperGetterDecorator.class.php | 61 +- ...sfOutputEscaperIteratorDecorator.class.php | 254 +- .../sfOutputEscaperObjectDecorator.class.php | 185 +- 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 | 141 +- 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 | 150 +- lib/form/sfForm.class.php | 2661 ++++++++--------- 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 | 476 ++- lib/helper/CacheHelper.php | 63 +- lib/helper/DateHelper.php | 214 +- lib/helper/DebugHelper.php | 7 +- lib/helper/EscapingHelper.php | 34 +- lib/helper/HelperHelper.php | 8 +- lib/helper/I18NHelper.php | 61 +- lib/helper/JavascriptBaseHelper.php | 138 +- lib/helper/NumberHelper.php | 31 +- lib/helper/PartialHelper.php | 319 +- lib/helper/TagHelper.php | 140 +- lib/helper/TextHelper.php | 351 +-- lib/helper/UrlHelper.php | 630 ++-- lib/i18n/Gettext/MO.php | 152 +- lib/i18n/Gettext/PO.php | 71 +- lib/i18n/Gettext/TGettext.class.php | 154 +- .../sfI18nApplicationExtract.class.php | 100 +- lib/i18n/extract/sfI18nExtract.class.php | 346 ++- .../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 | 1512 +++++----- lib/i18n/sfDateFormat.class.php | 1451 ++++----- lib/i18n/sfDateTimeFormatInfo.class.php | 993 +++--- lib/i18n/sfI18N.class.php | 718 +++-- lib/i18n/sfIMessageSource.class.php | 189 +- lib/i18n/sfMessageFormat.class.php | 372 ++- lib/i18n/sfMessageSource.class.php | 502 ++-- lib/i18n/sfMessageSource_Aggregate.class.php | 395 ++- lib/i18n/sfMessageSource_Database.class.php | 302 +- lib/i18n/sfMessageSource_File.class.php | 313 +- lib/i18n/sfMessageSource_MySQL.class.php | 631 ++-- lib/i18n/sfMessageSource_SQLite.class.php | 522 ++-- lib/i18n/sfMessageSource_SQLite3.class.php | 541 ++-- 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 | 1326 ++++---- lib/log/sfAggregateLogger.class.php | 154 +- lib/log/sfConsoleLogger.class.php | 27 +- lib/log/sfEventLogger.class.php | 45 +- lib/log/sfFileLogger.class.php | 295 +- lib/log/sfLogger.class.php | 507 ++-- lib/log/sfLoggerInterface.class.php | 17 +- lib/log/sfLoggerWrapper.class.php | 46 +- lib/log/sfNoLogger.class.php | 41 +- lib/log/sfPsrLoggerAdapter.class.php | 252 +- lib/log/sfStreamLogger.class.php | 100 +- lib/log/sfVarLogger.class.php | 283 +- lib/log/sfWebDebugLogger.class.php | 288 +- lib/mailer/sfMailer.class.php | 525 ++-- .../sfMailerMessageLoggerPlugin.class.php | 110 +- lib/mailer/sfNoMailer.class.php | 104 +- lib/plugin/sfPearConfig.class.php | 15 +- lib/plugin/sfPearDownloader.class.php | 27 +- lib/plugin/sfPearEnvironment.class.php | 403 ++- lib/plugin/sfPearFrontendPlugin.class.php | 72 +- lib/plugin/sfPearRest.class.php | 22 +- lib/plugin/sfPearRest10.class.php | 24 +- lib/plugin/sfPearRest11.class.php | 24 +- lib/plugin/sfPearRestPlugin.class.php | 338 +-- .../sfPluginDependencyException.class.php | 5 +- lib/plugin/sfPluginException.class.php | 5 +- lib/plugin/sfPluginManager.class.php | 788 +++-- ...uginRecursiveDependencyException.class.php | 5 +- lib/plugin/sfPluginRestException.class.php | 5 +- lib/plugin/sfSymfonyPluginManager.class.php | 370 ++- .../sfDoctrinePluginConfiguration.class.php | 143 +- .../lib/cli/sfDoctrineCli.class.php | 94 +- .../sfDoctrineConnectionListener.class.php | 32 +- .../sfDoctrineConnectionProfiler.class.php | 314 +- .../lib/database/sfDoctrineDatabase.class.php | 226 +- .../debug/sfWebDebugPanelDoctrine.class.php | 236 +- .../lib/form/sfFormDoctrine.class.php | 663 ++-- .../lib/form/sfFormFilterDoctrine.class.php | 490 ++- .../lib/generator/sfDoctrineColumn.class.php | 608 ++-- .../sfDoctrineFormFilterGenerator.class.php | 618 ++-- .../sfDoctrineFormGenerator.class.php | 1206 ++++---- .../generator/sfDoctrineGenerator.class.php | 433 ++- .../lib/mailer/Swift_DoctrineSpool.class.php | 192 +- .../lib/pager/sfDoctrinePager.class.php | 365 ++- .../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 | 437 ++- .../lib/task/sfDoctrineBuildDbTask.class.php | 81 +- .../task/sfDoctrineBuildFiltersTask.class.php | 88 +- .../task/sfDoctrineBuildFormsTask.class.php | 101 +- .../task/sfDoctrineBuildModelTask.class.php | 162 +- .../task/sfDoctrineBuildSchemaTask.class.php | 64 +- .../lib/task/sfDoctrineBuildSqlTask.class.php | 64 +- .../lib/task/sfDoctrineBuildTask.class.php | 405 ++- .../sfDoctrineCleanModelFilesTask.class.php | 170 +- .../lib/task/sfDoctrineCompileTask.class.php | 91 +- .../sfDoctrineConfigureDatabaseTask.class.php | 93 +- .../sfDoctrineCreateModelTablesTask.class.php | 115 +- .../lib/task/sfDoctrineDataDumpTask.class.php | 101 +- .../lib/task/sfDoctrineDataLoadTask.class.php | 96 +- .../sfDoctrineDeleteModelFilesTask.class.php | 207 +- .../lib/task/sfDoctrineDqlTask.class.php | 244 +- .../lib/task/sfDoctrineDropDbTask.class.php | 115 +- .../sfDoctrineGenerateAdminTask.class.php | 275 +- .../sfDoctrineGenerateMigrationTask.class.php | 109 +- ...DoctrineGenerateMigrationsDbTask.class.php | 71 +- ...ctrineGenerateMigrationsDiffTask.class.php | 69 +- ...rineGenerateMigrationsModelsTask.class.php | 63 +- ...ctrineGenerateModuleForRouteTask.class.php | 136 +- .../sfDoctrineGenerateModuleTask.class.php | 305 +- .../task/sfDoctrineInsertSqlTask.class.php | 60 +- .../lib/task/sfDoctrineMigrateTask.class.php | 185 +- .../lib/test/sfTesterDoctrine.class.php | 250 +- .../sfValidatorDoctrineChoice.class.php | 177 +- .../sfValidatorDoctrineUnique.class.php | 236 +- .../sfWidgetFormDoctrineArrayChoice.class.php | 113 +- .../sfWidgetFormDoctrineChoice.class.php | 176 +- .../sfDoctrinePlugin/test/bin/coverage.php | 7 +- .../sfDoctrinePlugin/test/bin/prove.php | 15 +- .../test/bootstrap/functional.php | 42 +- .../sfDoctrinePlugin/test/bootstrap/unit.php | 8 +- .../test/functional/ActionRedirectTest.php | 15 +- .../test/functional/AdminGenBrowser.class.php | 487 ++- .../test/functional/AdminGenTest.php | 10 +- .../test/functional/EnvironmentSetupTest.php | 21 +- .../test/functional/FormGeneratorTest.php | 32 +- .../test/functional/FormTest.php | 73 +- .../test/functional/I18nTest.php | 288 +- .../test/functional/PagerTest.php | 19 +- .../test/functional/RouteTest.php | 91 +- .../test/functional/SchemaMergeTest.php | 15 +- .../test/functional/Ticket/5269Test.php | 22 +- .../test/functional/Ticket/7774Test.php | 10 +- .../test/functional/UniqueTest.php | 13 +- .../test/functional/UploadTest.php | 43 +- .../config/backendConfiguration.class.php | 6 +- .../actions/actions.class.php | 25 +- .../templates/indexSuccess.php | 4 +- .../my_articles/actions/actions.class.php | 4 +- ...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 | 94 +- .../doctrine/ArticleFormFilter.class.php | 10 +- .../ArticleTranslationFormFilter.class.php | 10 +- .../doctrine/AttachmentFormFilter.class.php | 9 +- .../doctrine/AuthorFormFilter.class.php | 10 +- ...horInheritanceConcreteFormFilter.class.php | 9 +- .../AuthorInheritanceFormFilter.class.php | 10 +- .../doctrine/BaseFormFilterDoctrine.class.php | 10 +- .../doctrine/BlogArticleFormFilter.class.php | 17 +- ...BlogArticleTranslationFormFilter.class.php | 9 +- .../doctrine/BlogAuthorFormFilter.class.php | 17 +- .../doctrine/CamelCaseFormFilter.class.php | 10 +- .../DefaultValueTestFormFilter.class.php | 9 +- .../FormGeneratorTest2FormFilter.class.php | 10 +- .../filter/doctrine/GroupFormFilter.class.php | 10 +- .../doctrine/PermissionFormFilter.class.php | 10 +- .../doctrine/ProfileFormFilter.class.php | 10 +- .../doctrine/ResourceTypeFormFilter.class.php | 9 +- .../SettingFormFilter.class.php | 9 +- .../doctrine/SubscriptionFormFilter.class.php | 10 +- .../doctrine/UniqueTestFormFilter.class.php | 10 +- .../filter/doctrine/UserFormFilter.class.php | 10 +- .../fixtures/lib/form/BaseForm.class.php | 5 +- .../lib/form/doctrine/ArticleForm.class.php | 12 +- .../doctrine/ArticleTranslationForm.class.php | 10 +- .../form/doctrine/AttachmentForm.class.php | 40 +- .../lib/form/doctrine/AuthorForm.class.php | 10 +- .../AuthorInheritanceConcreteForm.class.php | 17 +- .../doctrine/AuthorInheritanceForm.class.php | 10 +- .../form/doctrine/BaseFormDoctrine.class.php | 9 +- .../form/doctrine/BlogArticleForm.class.php | 17 +- .../BlogArticleTranslationForm.class.php | 9 +- .../form/doctrine/BlogAuthorForm.class.php | 17 +- .../lib/form/doctrine/CamelCaseForm.class.php | 10 +- .../doctrine/DefaultValueTestForm.class.php | 9 +- .../doctrine/FormGeneratorTestForm.class.php | 10 +- .../lib/form/doctrine/GroupForm.class.php | 10 +- .../form/doctrine/PermissionForm.class.php | 10 +- .../lib/form/doctrine/ProfileForm.class.php | 10 +- .../form/doctrine/ResourceTypeForm.class.php | 9 +- .../SettingsPlugin/SettingForm.class.php | 9 +- .../form/doctrine/SubscriptionForm.class.php | 10 +- .../form/doctrine/UniqueTestForm.class.php | 10 +- .../lib/form/doctrine/UserForm.class.php | 16 +- .../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/sfDoctrineRecordTest.php | 9 +- .../test/unit/form/sfFormDoctrineTest.php | 49 +- .../unit/form/sfFormFilterDoctrineTest.php | 107 +- .../test/unit/pager/sfDoctrinePagerTest.php | 11 +- .../test/unit/record/sfDoctrineRecordTest.php | 22 +- .../test/unit/sfDoctrineColumnTest.php | 47 +- .../test/unit/sfDoctrineDatabaseTest.php | 18 +- .../sfValidatorDoctrineChoiceTest.php | 1 + .../sfWidgetFormDoctrineArrayChoiceTest.php | 1 + .../widget/sfWidgetFormDoctrineChoiceTest.php | 1 + lib/request/sfRequest.class.php | 620 ++-- lib/request/sfWebRequest.class.php | 1747 +++++------ lib/response/sfResponse.class.php | 326 +- lib/response/sfWebResponse.class.php | 1656 +++++----- lib/routing/sfObjectRoute.class.php | 338 +-- lib/routing/sfObjectRouteCollection.class.php | 354 ++- lib/routing/sfPatternRouting.class.php | 889 +++--- lib/routing/sfRequestRoute.class.php | 143 +- lib/routing/sfRoute.class.php | 1425 +++++---- lib/routing/sfRouteCollection.class.php | 165 +- lib/routing/sfRouting.class.php | 509 ++-- 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 | 506 ++-- .../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 | 495 ++- .../sfDatabaseSessionStorage.class.php | 325 +- lib/storage/sfMySQLSessionStorage.class.php | 354 ++- lib/storage/sfMySQLiSessionStorage.class.php | 109 +- 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 | 236 +- lib/task/cache/sfCacheClearTask.class.php | 340 +-- .../configure/sfConfigureAuthorTask.class.php | 77 +- .../generator/sfGenerateAppTask.class.php | 215 +- .../generator/sfGenerateModuleTask.class.php | 127 +- .../generator/sfGenerateProjectTask.class.php | 206 +- .../generator/sfGenerateTaskTask.class.php | 147 +- .../generator/sfGeneratorBaseTask.class.php | 5 +- lib/task/help/sfHelpTask.class.php | 180 +- lib/task/help/sfListTask.class.php | 255 +- lib/task/i18n/sfI18nExtractTask.class.php | 152 +- lib/task/i18n/sfI18nFindTask.class.php | 204 +- lib/task/log/sfLogClearTask.class.php | 44 +- lib/task/log/sfLogRotateTask.class.php | 248 +- .../plugin/sfPluginAddChannelTask.class.php | 56 +- lib/task/plugin/sfPluginBaseTask.class.php | 5 +- lib/task/plugin/sfPluginInstallTask.class.php | 114 +- lib/task/plugin/sfPluginListTask.class.php | 49 +- .../sfPluginPublishAssetsTask.class.php | 129 +- .../plugin/sfPluginUninstallTask.class.php | 72 +- lib/task/plugin/sfPluginUpgradeTask.class.php | 62 +- .../sfProjectClearControllersTask.class.php | 57 +- .../project/sfProjectDeployTask.class.php | 239 +- .../project/sfProjectDisableTask.class.php | 85 +- .../project/sfProjectEnableTask.class.php | 93 +- .../project/sfProjectOptimizeTask.class.php | 277 +- .../sfProjectPermissionsTask.class.php | 162 +- .../project/sfProjectSendEmailsTask.class.php | 53 +- .../project/sfProjectValidateTask.class.php | 116 +- .../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 | 871 +++--- lib/task/sfCommandApplicationTask.class.php | 379 ++- lib/task/sfFilesystem.class.php | 774 +++-- lib/task/sfTask.class.php | 1111 ++++--- lib/task/symfony/lime_symfony.php | 18 +- lib/task/symfony/sfSymfonyTestTask.class.php | 189 +- lib/task/test/sfLimeHarness.class.php | 38 +- lib/task/test/sfTestAllTask.class.php | 127 +- lib/task/test/sfTestBaseTask.class.php | 70 +- lib/task/test/sfTestCoverageTask.class.php | 131 +- lib/task/test/sfTestFunctionalTask.class.php | 141 +- lib/task/test/sfTestPluginTask.class.php | 74 +- lib/task/test/sfTestUnitTask.class.php | 137 +- lib/test/sfTestBrowser.class.php | 51 +- lib/test/sfTestFunctional.class.php | 89 +- lib/test/sfTestFunctionalBase.class.php | 844 +++--- 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 | 763 +++-- lib/test/sfTesterUser.class.php | 161 +- lib/test/sfTesterViewCache.class.php | 173 +- lib/user/sfBasicSecurityUser.class.php | 442 ++- lib/user/sfSecurityUser.class.php | 77 +- lib/user/sfUser.class.php | 553 ++-- lib/util/sfBrowser.class.php | 272 +- lib/util/sfBrowserBase.class.php | 1732 +++++------ lib/util/sfCallable.class.php | 75 +- lib/util/sfClassManipulator.class.php | 498 ++- lib/util/sfContext.class.php | 1196 ++++---- lib/util/sfDomCssSelector.class.php | 980 +++--- lib/util/sfFinder.class.php | 1202 ++++---- lib/util/sfInflector.class.php | 180 +- .../sfNamespacedParameterHolder.class.php | 615 ++-- lib/util/sfParameterHolder.class.php | 354 ++- lib/util/sfToolkit.class.php | 959 +++--- .../sfValidatorI18nChoiceCountry.class.php | 59 +- .../sfValidatorI18nChoiceLanguage.class.php | 59 +- .../sfValidatorI18nChoiceTimezone.class.php | 33 +- lib/validator/sfValidatedFile.class.php | 1234 ++++---- lib/validator/sfValidatorAnd.class.php | 248 +- lib/validator/sfValidatorBase.class.php | 880 +++--- lib/validator/sfValidatorBoolean.class.php | 73 +- lib/validator/sfValidatorCSRFToken.class.php | 45 +- lib/validator/sfValidatorCallback.class.php | 57 +- lib/validator/sfValidatorChoice.class.php | 252 +- lib/validator/sfValidatorDate.class.php | 427 ++- lib/validator/sfValidatorDateRange.class.php | 82 +- lib/validator/sfValidatorDateTime.class.php | 22 +- lib/validator/sfValidatorDecorator.class.php | 296 +- lib/validator/sfValidatorEmail.class.php | 24 +- lib/validator/sfValidatorEqual.class.php | 81 +- lib/validator/sfValidatorError.class.php | 286 +- .../sfValidatorErrorSchema.class.php | 579 ++-- lib/validator/sfValidatorFile.class.php | 529 ++-- lib/validator/sfValidatorFileMulti.class.php | 24 +- .../sfValidatorFromDescription.class.php | 610 ++-- lib/validator/sfValidatorInteger.class.php | 94 +- lib/validator/sfValidatorIp.class.php | 151 +- lib/validator/sfValidatorNumber.class.php | 92 +- lib/validator/sfValidatorOr.class.php | 203 +- lib/validator/sfValidatorPass.class.php | 37 +- lib/validator/sfValidatorRegex.class.php | 93 +- lib/validator/sfValidatorSchema.class.php | 648 ++-- .../sfValidatorSchemaCompare.class.php | 277 +- .../sfValidatorSchemaFilter.class.php | 97 +- lib/validator/sfValidatorString.class.php | 89 +- lib/validator/sfValidatorTime.class.php | 218 +- lib/validator/sfValidatorUrl.class.php | 55 +- lib/view/sfPHPView.class.php | 280 +- lib/view/sfPartialView.class.php | 234 +- lib/view/sfView.class.php | 1010 +++---- lib/view/sfViewCacheManager.class.php | 1740 +++++------ lib/view/sfViewParameterHolder.class.php | 341 ++- .../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 | 75 +- .../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 | 735 +++-- .../sfWidgetFormSchemaFormatter.class.php | 530 ++-- .../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 | 247 +- lib/yaml/sfYamlDumper.class.php | 66 +- lib/yaml/sfYamlInline.class.php | 755 ++--- lib/yaml/sfYamlParser.class.php | 974 +++--- test/bin/coverage.php | 12 +- test/bin/loc.php | 33 +- test/bootstrap/functional.php | 59 +- test/bootstrap/task.php | 11 +- test/bootstrap/unit.php | 47 +- test/functional/authTest.php | 71 +- test/functional/autoloadTest.php | 5 +- test/functional/cacheTest.php | 646 ++-- test/functional/escapingTest.php | 27 +- test/functional/filterTest.php | 7 +- .../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 | 10 +- .../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 | 7 +- test/functional/genericTest.php | 5 +- test/functional/httpcacheTest.php | 7 +- test/functional/i18nFormTest.php | 7 +- test/functional/i18nTest.php | 45 +- test/functional/prodTest.php | 7 +- test/functional/sfTestBrowserTest.php | 56 +- .../fixtures/task/myPluginTask.class.php | 22 +- test/other/fixtures/test/unit/testTest.php | 2 +- test/other/tasksTest.php | 110 +- test/unit/action/sfComponentTest.php | 20 +- test/unit/addon/sfPagerTest.php | 89 +- test/unit/autoload/sfCoreAutoloadTest.php | 2 +- test/unit/autoload/sfSimpleAutoloadTest.php | 2 +- test/unit/cache/sfAPCCacheTest.php | 28 +- test/unit/cache/sfCacheDriverTests.class.php | 331 +- test/unit/cache/sfCacheTest.php | 43 +- test/unit/cache/sfEAcceleratorCacheTest.php | 20 +- test/unit/cache/sfFileCacheTest.php | 21 +- test/unit/cache/sfFunctionCacheTest.php | 107 +- test/unit/cache/sfMemcacheCacheTest.php | 59 +- test/unit/cache/sfNoCacheTest.php | 2 +- test/unit/cache/sfSQLiteCacheTest.php | 43 +- test/unit/cache/sfXCacheCacheTest.php | 20 +- .../unit/command/sfCommandArgumentSetTest.php | 69 +- test/unit/command/sfCommandArgumentTest.php | 47 +- test/unit/command/sfCommandManagerTest.php | 92 +- test/unit/command/sfCommandOptionSetTest.php | 102 +- test/unit/command/sfCommandOptionTest.php | 49 +- .../config/sfCompileConfigHandlerTest.php | 6 +- test/unit/config/sfConfigHandlerTest.php | 16 +- test/unit/config/sfConfigTest.php | 4 +- .../sfDefineEnvironmentConfigHandlerTest.php | 8 +- .../unit/config/sfFilterConfigHandlerTest.php | 68 +- .../config/sfGeneratorConfigHandlerTest.php | 89 +- .../unit/config/sfPluginConfigurationTest.php | 10 +- .../config/sfProjectConfigurationTest.php | 61 +- .../config/sfSimpleYamlConfigHandlerTest.php | 12 +- test/unit/config/sfViewConfigHandlerTest.php | 380 +-- test/unit/config/sfYamlConfigHandlerTest.php | 74 +- test/unit/controller/sfControllerTest.php | 13 +- test/unit/controller/sfWebControllerTest.php | 280 +- test/unit/database/sfDatabaseTest.php | 18 +- test/unit/debug/sfDebugTest.php | 4 +- test/unit/debug/sfTimerTest.php | 4 +- test/unit/debug/sfWebDebugTest.php | 19 +- .../sfOutputEscaperArrayDecoratorTest.php | 90 +- .../sfOutputEscaperObjectDecoratorTest.php | 75 +- test/unit/escaper/sfOutputEscaperSafeTest.php | 28 +- test/unit/escaper/sfOutputEscaperTest.php | 91 +- test/unit/event/sfEventDispatcherTest.php | 71 +- test/unit/event/sfEventTest.php | 15 +- test/unit/exception/sfExceptionsTest.php | 31 +- test/unit/filter/sfFilterTest.php | 17 +- test/unit/form/addon/sfFormSymfonyTest.php | 48 +- test/unit/form/sfFormFieldSchemaTest.php | 62 +- test/unit/form/sfFormFieldTest.php | 80 +- test/unit/form/sfFormTest.php | 814 ++--- test/unit/generator/sfGeneratorTest.php | 8 +- ...sfModelGeneratorConfigurationFieldTest.php | 2 +- test/unit/helper/AssetHelperTest.php | 281 +- test/unit/helper/DateHelperTest.php | 43 +- test/unit/helper/EscapingHelperTest.php | 8 +- test/unit/helper/JavascriptBaseHelperTest.php | 22 +- test/unit/helper/NumberHelperTest.php | 13 +- test/unit/helper/PartialHelperTest.php | 34 +- test/unit/helper/TagHelperTest.php | 15 +- test/unit/helper/TestObject.php | 66 +- test/unit/helper/TextHelperTest.php | 81 +- test/unit/helper/UrlHelperTest.php | 97 +- test/unit/i18n/dataTest.php | 42 +- test/unit/i18n/extract/sfI18nExtractTest.php | 33 +- .../i18n/extract/sfI18nPhpExtractorTest.php | 20 +- .../sfI18nYamlGeneratorExtractorTest.php | 28 +- .../sfI18nYamlValidateExtractorTest.php | 14 +- test/unit/i18n/sfChoiceFormatTest.php | 124 +- test/unit/i18n/sfCultureInfoTest.php | 128 +- test/unit/i18n/sfI18NTest.php | 37 +- test/unit/i18n/sfMessageSourceTest.php | 33 +- .../i18n/sfMessageSource_AggregateTest.php | 10 +- test/unit/i18n/sfMessageSource_FileTest.php | 28 +- test/unit/i18n/sfMessageSource_SQLiteTest.php | 76 +- test/unit/i18n/sfMessageSource_XLIFFTest.php | 4 +- test/unit/i18n/sfNumberFormatInfoTest.php | 132 +- test/unit/log/sfAggregateLoggerTest.php | 11 +- test/unit/log/sfConsoleLoggerTest.php | 4 +- test/unit/log/sfFileLoggerTest.php | 41 +- test/unit/log/sfLoggerTest.php | 72 +- test/unit/log/sfLoggerWrapperTest.php | 22 +- test/unit/log/sfStreamLoggerTest.php | 4 +- test/unit/log/sfVarLoggerTest.php | 4 +- test/unit/log/sfWebDebugLoggerTest.php | 3 +- .../mailer/fixtures/TestMailMessage.class.php | 12 +- .../fixtures/TestMailerTransport.class.php | 108 +- test/unit/mailer/fixtures/TestSpool.class.php | 76 +- test/unit/mailer/sfMailerTest.php | 94 +- .../plugin/sfPearDownloaderTest.class.php | 49 +- test/unit/plugin/sfPearEnvironmentTest.php | 48 +- test/unit/plugin/sfPearRestPluginTest.php | 24 +- test/unit/plugin/sfPearRestTest.class.php | 53 +- test/unit/plugin/sfPluginManagerTest.php | 176 +- test/unit/plugin/sfPluginTestHelper.class.php | 34 +- test/unit/request/sfRequestTest.php | 27 +- test/unit/request/sfWebRequestTest.php | 140 +- test/unit/response/sfResponseTest.php | 23 +- test/unit/response/sfWebResponseTest.php | 69 +- .../routing/fixtures/config_routing.yml.php | 1 + .../routing/sfObjectRouteCollectionTest.php | 92 +- test/unit/routing/sfObjectRouteTest.php | 30 +- test/unit/routing/sfPatternRoutingTest.php | 179 +- test/unit/routing/sfRequestRouteTest.php | 4 +- test/unit/routing/sfRouteTest.php | 66 +- .../fixtures/containers/container8.php | 6 +- .../fixtures/containers/container9.php | 6 +- .../service/fixtures/includes/classes.php | 32 +- test/unit/service/fixtures/includes/foo.php | 50 +- .../service/sfServiceContainerBuilderTest.php | 89 +- .../sfServiceContainerDumperGraphvizTest.php | 15 +- .../sfServiceContainerDumperPhpTest.php | 17 +- .../service/sfServiceContainerDumperTest.php | 16 +- .../sfServiceContainerLoaderArrayTest.php | 36 +- .../service/sfServiceContainerLoaderTest.php | 26 +- test/unit/service/sfServiceContainerTest.php | 80 +- test/unit/service/sfServiceDefinitionTest.php | 2 +- 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 | 166 +- test/unit/sfParameterHolderTest.class.php | 79 +- .../storage/sfCacheSessionStorageTest.php | 29 +- test/unit/storage/sfMySQLStorageTest.php | 98 +- test/unit/storage/sfMySQLiStorageTest.php | 96 +- test/unit/storage/sfNoStorageTest.php | 4 +- test/unit/storage/sfPDOSessionStorageTest.php | 67 +- test/unit/storage/sfSessionStorageTest.php | 21 +- test/unit/storage/sfStorageTest.php | 28 +- test/unit/task/cache/sfCacheClearTaskTest.php | 4 +- test/unit/task/sfBaseTaskTest.php | 111 +- test/unit/task/sfFilesystemTest.php | 24 +- test/unit/task/sfTaskTest.php | 83 +- test/unit/test/limeTestTest.php | 2 +- test/unit/test/sfTestFunctionalTest.php | 49 +- test/unit/user/sfBasicSecurityUserTest.php | 14 +- test/unit/user/sfUserTest.php | 18 +- test/unit/util/sfBrowserTest.php | 144 +- test/unit/util/sfCallableTest.php | 34 +- test/unit/util/sfClassManipulatorTest.php | 89 +- test/unit/util/sfContextTest.php | 35 +- test/unit/util/sfDomCssSelectorTest.php | 34 +- test/unit/util/sfFinderTest.php | 124 +- test/unit/util/sfInflectorTest.php | 10 +- .../util/sfNamespacedParameterHolderTest.php | 4 +- test/unit/util/sfParameterHolderTest.php | 8 +- test/unit/util/sfToolkitTest.php | 150 +- .../i18n/sfValidatorI18nChoiceCountryTest.php | 15 +- .../sfValidatorI18nChoiceLanguageTest.php | 15 +- .../sfValidatorI18nChoiceTimezoneTest.php | 2 +- test/unit/validator/sfValidatorAndTest.php | 128 +- test/unit/validator/sfValidatorBaseTest.php | 156 +- .../unit/validator/sfValidatorBooleanTest.php | 41 +- .../validator/sfValidatorCSRFTokenTest.php | 33 +- .../validator/sfValidatorCallbackTest.php | 43 +- test/unit/validator/sfValidatorChoiceTest.php | 96 +- .../validator/sfValidatorDateRangeTest.php | 59 +- test/unit/validator/sfValidatorDateTest.php | 210 +- .../validator/sfValidatorDateTimeTest.php | 2 +- .../validator/sfValidatorDecoratorTest.php | 84 +- test/unit/validator/sfValidatorEmailTest.php | 43 +- test/unit/validator/sfValidatorEqualTest.php | 80 +- .../validator/sfValidatorErrorSchemaTest.php | 75 +- test/unit/validator/sfValidatorErrorTest.php | 55 +- .../validator/sfValidatorFileMultiTest.php | 6 +- test/unit/validator/sfValidatorFileTest.php | 258 +- .../sfValidatorFromDescriptionTest.php | 129 +- .../unit/validator/sfValidatorIntegerTest.php | 102 +- test/unit/validator/sfValidatorIpTest.php | 352 +-- test/unit/validator/sfValidatorNumberTest.php | 77 +- test/unit/validator/sfValidatorOrTest.php | 84 +- test/unit/validator/sfValidatorPassTest.php | 2 +- test/unit/validator/sfValidatorRegexTest.php | 65 +- .../sfValidatorSchemaCompareTest.php | 154 +- .../validator/sfValidatorSchemaFilterTest.php | 49 +- test/unit/validator/sfValidatorSchemaTest.php | 380 ++- test/unit/validator/sfValidatorStringTest.php | 83 +- test/unit/validator/sfValidatorTimeTest.php | 137 +- test/unit/validator/sfValidatorUrlTest.php | 64 +- test/unit/view/sfViewCacheManagerTest.php | 229 +- test/unit/view/sfViewParameterHolderTest.php | 49 +- test/unit/view/sfViewTest.php | 48 +- .../sfWidgetFormI18nChoiceCountryTest.php | 18 +- .../sfWidgetFormI18nChoiceCurrencyTest.php | 18 +- .../sfWidgetFormI18nChoiceLanguageTest.php | 18 +- .../sfWidgetFormI18nChoiceTimezoneTest.php | 4 +- .../widget/i18n/sfWidgetFormI18nDateTest.php | 17 +- .../i18n/sfWidgetFormI18nDateTimeTest.php | 4 +- .../widget/i18n/sfWidgetFormI18nTimeTest.php | 4 +- test/unit/widget/sfWidgetFormChoiceTest.php | 46 +- .../unit/widget/sfWidgetFormDateRangeTest.php | 34 +- test/unit/widget/sfWidgetFormDateTest.php | 27 +- test/unit/widget/sfWidgetFormDateTimeTest.php | 47 +- .../widget/sfWidgetFormFilterDateTest.php | 33 +- .../widget/sfWidgetFormFilterInputTest.php | 19 +- .../widget/sfWidgetFormInputCheckboxTest.php | 3 +- .../sfWidgetFormInputFileEditableTest.php | 47 +- .../widget/sfWidgetFormInputFileMultiTest.php | 4 +- .../unit/widget/sfWidgetFormInputFileTest.php | 2 +- .../widget/sfWidgetFormInputHiddenTest.php | 2 +- .../widget/sfWidgetFormInputPasswordTest.php | 2 +- .../unit/widget/sfWidgetFormInputReadTest.php | 2 +- .../unit/widget/sfWidgetFormInputTextTest.php | 2 +- .../sfWidgetFormSchemaDecoratorTest.php | 22 +- .../sfWidgetFormSchemaFormatterListTest.php | 6 +- .../sfWidgetFormSchemaFormatterTableTest.php | 6 +- .../sfWidgetFormSchemaFormatterTest.php | 102 +- test/unit/widget/sfWidgetFormSchemaTest.php | 250 +- .../widget/sfWidgetFormSelectCheckboxTest.php | 41 +- .../widget/sfWidgetFormSelectManyTest.php | 4 +- .../widget/sfWidgetFormSelectRadioTest.php | 39 +- test/unit/widget/sfWidgetFormSelectTest.php | 33 +- test/unit/widget/sfWidgetFormTest.php | 20 +- test/unit/widget/sfWidgetFormTextareaTest.php | 2 +- test/unit/widget/sfWidgetFormTimeTest.php | 25 +- test/unit/widget/sfWidgetTest.php | 80 +- test/unit/yaml/sfYamlDumperTest.php | 83 +- test/unit/yaml/sfYamlInlineTest.php | 198 +- test/unit/yaml/sfYamlParserTest.php | 71 +- 907 files changed, 67547 insertions(+), 73034 deletions(-) diff --git a/.editorconfig b/.editorconfig index 4a7ea3036..779f99a12 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 diff --git a/data/bin/changelog.php b/data/bin/changelog.php index 55d3c1c6f..4eaf5868a 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(); @@ -37,13 +37,12 @@ $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], + $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..10b10adc8 100644 --- a/data/bin/check_configuration.php +++ b/data/bin/check_configuration.php @@ -2,25 +2,28 @@ function is_cli() { - return !isset($_SERVER['HTTP_HOST']); + return !isset($_SERVER['HTTP_HOST']); } /** * Checks a configuration. + * + * @param mixed $boolean + * @param mixed $message + * @param mixed $help + * @param mixed $fatal */ 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"); + } } - } } /** @@ -30,17 +33,15 @@ function check($boolean, $message, $help = '', $fatal = false) */ 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,18 +52,16 @@ 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
@@ -72,10 +71,9 @@ function get_ini_path()
 // 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);
@@ -85,10 +83,8 @@ function get_ini_path()
 
 $accelerator =
   (function_exists('apc_store') && ini_get('apc.enabled'))
-  ||
-  function_exists('eaccelerator_put') && ini_get('eaccelerator.enable')
-  ||
-  function_exists('xcache_set')
+  || 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);
 
@@ -99,7 +95,6 @@ function_exists('xcache_set')
 
 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..df6dec94f 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'); @@ -80,21 +74,19 @@ $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"; - } +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, + 'SYMFONY_VERSION' => $version, + 'CURRENT_DATE' => date('Y-m-d'), + 'CLASS_FILES' => $xml_classes, + 'STABILITY' => $stability, )); list($results) = $filesystem->execute('pear package'); diff --git a/data/bin/sandbox_installer.php b/data/bin/sandbox_installer.php index c45891174..576b28c01 100644 --- a/data/bin/sandbox_installer.php +++ b/data/bin/sandbox_installer.php @@ -24,12 +24,10 @@ $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; +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/lib/action/sfAction.class.php b/lib/action/sfAction.class.php index f796cd30d..5fdcc49c9 100644 --- a/lib/action/sfAction.class.php +++ b/lib/action/sfAction.class.php @@ -12,533 +12,514 @@ /** * 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 = array(); + + /** + * 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) + { + 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() { - require($file); + return $this->redirect('/'.sfConfig::get('sf_error_404_module').'/'.sfConfig::get('sf_error_404_action')); } - } - - /** - * 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) + + /** + * 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) { - throw new sfError404Exception($this->get404Message($message)); + if (sfConfig::get('sf_logging_enabled')) { + $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Forward to action "%s/%s"', $module, $action)))); + } + + $this->getController()->forward($module, $action); + + throw new sfStopException(); } - } - - /** - * 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) + + /** + * 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) { - throw new sfError404Exception($this->get404Message($message)); + if ($condition) { + $this->forward($module, $action); + } } - } - - /** - * 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')) + + /** + * 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) { - $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Forward to action "%s/%s"', $module, $action)))); + if (!$condition) { + $this->forward($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) + /** + * 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) { - $this->forward($module, $action); + // compatibility with url_for2() style signature + if (is_object($statusCode) || is_array($statusCode)) { + $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->getController()->redirect($url, 0, $statusCode); + + throw new sfStopException(); } - } - - /** - * 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) + + /** + * 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) { - $this->forward($module, $action); + if ($condition) { + // compatibility with url_for2() style signature + $arguments = func_get_args(); + call_user_func_array(array($this, 'redirect'), array_slice($arguments, 1)); + } } - } - - /** - * 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)) + + /** + * 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) { - $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; + if (!$condition) { + // compatibility with url_for2() style signature + $arguments = func_get_args(); + call_user_func_array(array($this, 'redirect'), array_slice($arguments, 1)); + } } - $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 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) { - // compatibility with url_for2() style signature - $arguments = func_get_args(); - call_user_func_array(array($this, 'redirect'), array_slice($arguments, 1)); + $this->getResponse()->setContent($this->getResponse()->getContent().$text); + + return sfView::NONE; } - } - - /** - * 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) + + /** + * 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) { - // compatibility with url_for2() style signature - $arguments = func_get_args(); - call_user_func_array(array($this, 'redirect'), array_slice($arguments, 1)); + $this->getResponse()->setContentType('application/json'); + $this->getResponse()->setContent(json_encode($data)); + + return sfView::NONE; } - } - - /** - * 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])) + + /** + * 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) { - return $this->security[$actionName][$name]; + $this->getContext()->getConfiguration()->loadHelpers('Partial'); + + $vars = null !== $vars ? $vars : $this->varHolder->getAll(); + + return get_partial($templateName, $vars); } - if (isset($this->security['all'][$name])) + /** + * 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->security['all'][$name]; + return $this->renderText($this->getPartial($templateName, $vars)); } - 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')) + /** + * 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->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Change template to "%s/%s"', null === $module ? 'CURRENT' : $module, $name)))); + $this->getContext()->getConfiguration()->loadHelpers('Partial'); + + $vars = null !== $vars ? $vars : $this->varHolder->getAll(); + + return get_component($moduleName, $componentName, $vars); } - if (null !== $module) + /** + * 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) { - $dir = $this->context->getConfiguration()->getTemplateDir($module, $name.sfView::SUCCESS.'.php'); - $name = $dir.'/'.$name; + return $this->renderText($this->getComponent($moduleName, $componentName, $vars)); } - 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')) + /** + * Returns the security configuration for this module. + * + * @return string Current security configuration as an array + */ + public function getSecurityConfiguration() { - $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Change layout to "%s"', $name)))); + return $this->security; } - 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; - } + /** + * 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])) { + return $this->security[$actionName][$name]; + } + + if (isset($this->security['all'][$name])) { + return $this->security['all'][$name]; + } + + 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')) { + $this->dispatcher->notify(new sfEvent($this, 'application.log', array(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); + } + + /** + * 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', array(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..41c17e228 100644 --- a/lib/action/sfActionStack.class.php +++ b/lib/action/sfActionStack.class.php @@ -13,108 +13,103 @@ * 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 = 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) { - $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; } - 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])) + /** + * 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 = $this->stack[0]; + $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 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; + /** + * 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])) + if (isset($this->stack[0])) { + $retval = $this->stack[0]; + } + + return $retval; + } + + /** + * 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..1624e710b 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,81 @@ /** * 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..2a2de62da 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,47 @@ /** * 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(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)); + } - // run action - return $this->$actionToRun($request); - } + if (sfConfig::get('sf_logging_enabled')) { + $this->dispatcher->notify(new sfEvent($this, 'application.log', array(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..b933f9a83 100644 --- a/lib/action/sfComponent.class.php +++ b/lib/action/sfComponent.class.php @@ -11,415 +11,418 @@ /** * 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 = array(), $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->dispatcher->notify(new sfEvent($this, 'application.log', array($message, 'priority' => constant('sfLogger::'.strtoupper($priority))))); + $this->varHolder->remove($name); } - } - - /** - * 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()) + + /** + * 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()) { + 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) { - throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method)); + return $this->getServiceContainer()->getService($id); } - return $event->getReturnValue(); - } + /** + * 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', array($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) + { + 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 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() + { + 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 bool $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 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..967d7cbff 100644 --- a/lib/action/sfComponents.class.php +++ b/lib/action/sfComponents.class.php @@ -11,22 +11,23 @@ /** * 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 + * + * @return mixed + * + * @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..b03a4a55e 100644 --- a/lib/addon/sfData.class.php +++ b/lib/addon/sfData.class.php @@ -12,119 +12,107 @@ * 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 = array(); - /** - * 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 = array(); + 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 = array(); + $this->maps = array(); - 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..9709060d7 100644 --- a/lib/addon/sfPager.class.php +++ b/lib/addon/sfPager.class.php @@ -11,611 +11,574 @@ /** * 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 = array(); + 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 = 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 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 + * + * @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; + } + + 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 $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 bool + */ + 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 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 + * + * @return mixed + */ + 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 5f68f8039..f3e238e27 100644 --- a/lib/autoload/sfAutoload.class.php +++ b/lib/autoload/sfAutoload.class.php @@ -14,229 +14,195 @@ * 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)) - { - self::$instance = new sfAutoload(); - } + protected static $freshCache = false; + protected static $instance; - 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'))) - { - throw new sfException(sprintf('Unable to register %s::autoload as an autoloading method.', get_class(self::getInstance()))); - } - } - - /** - * 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) - { - return false; - } + protected $overriden = array(); + protected $classes = array(); - $configuration = sfProjectConfiguration::getActive(); - if (!$configuration || !$configuration instanceof sfApplicationConfiguration) + protected function __construct() { - return false; } - self::$freshCache = true; - if (is_file($configuration->getConfigCache()->getCacheName('config/autoload.yml'))) + /** + * Retrieves the singleton instance of this class. + * + * @return sfAutoload a sfAutoload implementation instance + */ + public static function getInstance() { - self::$freshCache = false; - if ($force) - { - if (file_exists($configuration->getConfigCache()->getCacheName('config/autoload.yml'))) - { - unlink($configuration->getConfigCache()->getCacheName('config/autoload.yml')); + if (!isset(self::$instance)) { + self::$instance = new sfAutoload(); } - } - } - $file = $configuration->getConfigCache()->checkConfig('config/autoload.yml'); + return self::$instance; + } - if ($force && defined('HHVM_VERSION')) + /** + * Register sfAutoload in spl autoloader. + * + * @throws sfException + */ + public static function register() { - // workaround for https://github.com/facebook/hhvm/issues/1447 - $this->classes = eval(str_replace('classes = include $file; + spl_autoload_unregister(array(self::getInstance(), 'autoload')); } - foreach ($this->overriden as $class => $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) { - $this->classes[$class] = $path; + $class = strtolower($class); + + $this->overriden[$class] = $path; + + $this->classes[$class] = $path; } - 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) + /** + * 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) { - self::reloadClasses(); + $class = strtolower($class); + + 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; + if (is_file($configuration->getConfigCache()->getCacheName('config/autoload.yml'))) { + self::$freshCache = false; + if ($force) { + if (file_exists($configuration->getConfigCache()->getCacheName('config/autoload.yml'))) { + unlink($configuration->getConfigCache()->getCacheName('config/autoload.yml')); + } + } + } + + $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); - return false; - } + // 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; + } } diff --git a/lib/autoload/sfAutoloadAgain.class.php b/lib/autoload/sfAutoloadAgain.class.php index 6d61df830..edf0c9461 100644 --- a/lib/autoload/sfAutoloadAgain.class.php +++ b/lib/autoload/sfAutoloadAgain.class.php @@ -10,123 +10,111 @@ /** * 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(array(__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(array($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(array($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 ff6dfce1b..2b711629c 100755 --- a/lib/autoload/sfCoreAutoload.class.php +++ b/lib/autoload/sfCoreAutoload.class.php @@ -8,9 +8,7 @@ * file that was distributed with this source code. */ -/** - * The current symfony version. - */ +// The current symfony version. define('SYMFONY_VERSION', '1.5.16-dev'); /** @@ -19,529 +17,515 @@ * 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 * + * @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 = 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', + '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_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(array(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(array(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', - '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_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', - ); + $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..05c3983c7 100755 --- a/lib/autoload/sfSimpleAutoload.class.php +++ b/lib/autoload/sfSimpleAutoload.class.php @@ -14,329 +14,288 @@ * 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 = array(); + protected $files = array(); + protected $classes = array(); + protected $overriden = array(); + + 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(array(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(array(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(array(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(array($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 = array(); + $this->cacheLoaded = false; + + foreach ($this->dirs as $dir) { + $this->addDirectory($dir); + } + + foreach ($this->files as $file) { + $this->addFile($file); } - else - { - $this->dirs[] = $dir; + + 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 index 78376490b..41b65505c 100644 --- a/lib/cache/sfAPCCache.class.php +++ b/lib/cache/sfAPCCache.class.php @@ -11,210 +11,189 @@ /** * 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) + protected $enabled; + + /** + * Initializes this sfCache instance. + * + * Available options: + * + * * see sfCache for options available for all drivers + * + * @see sfCache + * {@inheritdoc} + */ + public function initialize($options = array()) { - return $default; - } - - $value = $this->fetch($this->getOption('prefix').$key, $has); + parent::initialize($options); - return $has ? $value : $default; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function has($key) - { - if (!$this->enabled) - { - return false; + $this->enabled = function_exists('apc_store') && ini_get('apc.enabled'); } - $this->fetch($this->getOption('prefix').$key, $has); + /** + * @see sfCache + * {@inheritdoc} + */ + public function get($key, $default = null) + { + if (!$this->enabled) { + return $default; + } - return $has; - } + $value = $this->fetch($this->getOption('prefix').$key, $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; + return $has ? $value : $default; } - else + + /** + * @see sfCache + * {@inheritdoc} + */ + public function has($key) { - $success = $value !== false; - } + if (!$this->enabled) { + return false; + } - return $value; - } + $this->fetch($this->getOption('prefix').$key, $has); + return $has; + } - /** - * @see sfCache - * @inheritdoc - */ - public function set($key, $data, $lifetime = null) - { - if (!$this->enabled) + /** + * @see sfCache + * {@inheritdoc} + */ + public function set($key, $data, $lifetime = null) { - return true; - } + if (!$this->enabled) { + return true; + } - return apc_store($this->getOption('prefix').$key, $data, $this->getLifetime($lifetime)); - } + return apc_store($this->getOption('prefix').$key, $data, $this->getLifetime($lifetime)); + } - /** - * @see sfCache - * @inheritdoc - */ - public function remove($key) - { - if (!$this->enabled) + /** + * @see sfCache + * {@inheritdoc} + */ + public function remove($key) { - return true; - } + if (!$this->enabled) { + return true; + } - return apc_delete($this->getOption('prefix').$key); - } + return apc_delete($this->getOption('prefix').$key); + } - /** - * @see sfCache - * @inheritdoc - */ - public function clean($mode = sfCache::ALL) - { - if (!$this->enabled) + /** + * @see sfCache + * {@inheritdoc} + */ + public function clean($mode = sfCache::ALL) { - return true; + if (!$this->enabled) { + return true; + } + + if (sfCache::ALL === $mode) { + return apc_clear_cache('user'); + } } - if (sfCache::ALL === $mode) + /** + * @see sfCache + * {@inheritdoc} + */ + public function getLastModified($key) { - return apc_clear_cache('user'); + if ($info = $this->getCacheInfo($key)) { + return $info['creation_time'] + $info['ttl'] > time() ? $info['mtime'] : 0; + } + + return 0; } - } - - /** - * @see sfCache - * @inheritdoc - */ - public function getLastModified($key) - { - if ($info = $this->getCacheInfo($key)) + + /** + * @see sfCache + * {@inheritdoc} + */ + public function getTimeout($key) { - return $info['creation_time'] + $info['ttl'] > time() ? $info['mtime'] : 0; - } + if ($info = $this->getCacheInfo($key)) { + return $info['creation_time'] + $info['ttl'] > time() ? $info['creation_time'] + $info['ttl'] : 0; + } - return 0; - } + return 0; + } - /** - * @see sfCache - * @inheritdoc - */ - public function getTimeout($key) - { - if ($info = $this->getCacheInfo($key)) + /** + * @see sfCache + * {@inheritdoc} + */ + public function removePattern($pattern) { - return $info['creation_time'] + $info['ttl'] > time() ? $info['creation_time'] + $info['ttl'] : 0; - } + if (!$this->enabled) { + return true; + } - return 0; - } + $infos = apc_cache_info('user'); + if (!is_array($infos['cache_list'])) { + return; + } - /** - * @see sfCache - * @inheritdoc - */ - public function removePattern($pattern) - { - if (!$this->enabled) - { - return true; + $regexp = self::patternToRegexp($this->getOption('prefix').$pattern); + + foreach ($infos['cache_list'] as $info) { + if (preg_match($regexp, $info['info'])) { + apc_delete($info['info']); + } + } } - $infos = apc_cache_info('user'); - if (!is_array($infos['cache_list'])) + /** + * Gets the cache info. + * + * @param string $key The cache key + * + * @return string + */ + protected function getCacheInfo($key) { - return; - } + if (!$this->enabled) { + return false; + } - $regexp = self::patternToRegexp($this->getOption('prefix').$pattern); + $infos = apc_cache_info('user'); - 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; - } + if (is_array($infos['cache_list'])) { + foreach ($infos['cache_list'] as $info) { + if ($this->getOption('prefix').$key == $info['info']) { + return $info; + } + } + } - $infos = apc_cache_info('user'); + return null; + } - if (is_array($infos['cache_list'])) + private function fetch($key, &$success) { - foreach ($infos['cache_list'] as $info) - { - if ($this->getOption('prefix').$key == $info['info']) - { - return $info; + $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 = false !== $value; } - } - } - return null; - } + return $value; + } } diff --git a/lib/cache/sfCache.class.php b/lib/cache/sfCache.class.php index 3be0e55c6..4668af3b5 100644 --- a/lib/cache/sfCache.class.php +++ b/lib/cache/sfCache.class.php @@ -11,227 +11,224 @@ /** * 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 = 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 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 = array(); + 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) { - $data[$key] = $this->get($key); + return null === $lifetime ? $this->getOption('lifetime') : $lifetime; } - 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.'$#'; - } + /** + * 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.'$#'; + } } diff --git a/lib/cache/sfEAcceleratorCache.class.php b/lib/cache/sfEAcceleratorCache.class.php index ab08da295..88342cdbc 100644 --- a/lib/cache/sfEAcceleratorCache.class.php +++ b/lib/cache/sfEAcceleratorCache.class.php @@ -11,182 +11,167 @@ /** * 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)) + /** + * 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()) { - $regexp = self::patternToRegexp($this->getOption('prefix').$pattern); + parent::initialize($options); - foreach ($infos as $info) - { - if (preg_match($regexp, $info['name'])) - { - eaccelerator_rm($this->getOption('prefix').$key); + 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 - * @inheritdoc - */ - public function clean($mode = sfCache::ALL) - { - if (sfCache::OLD === $mode) + + /** + * @see sfCache + * + * @param string $key + * @param mixed $default + * + * @return string|null + */ + public function get($key, $default = null) { - return eaccelerator_gc(); + $value = eaccelerator_get($this->getOption('prefix').$key); + + return null === $value ? $default : $value; } - $infos = eaccelerator_list_keys(); - if (is_array($infos)) + /** + * @see sfCache + * + * @param string $key + * + * @return bool + */ + public function has($key) { - 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 null !== eaccelerator_get($this->getOption('prefix'.$key)); } - return true; - } + /** + * @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 getLastModified($key) - { - if ($info = $this->getCacheInfo($key)) + /** + * @see sfCache + * {@inheritdoc} + */ + public function remove($key) { - return $info['created']; + return eaccelerator_rm($this->getOption('prefix').$key); } - return 0; - } + /** + * @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 getTimeout($key) - { - if ($info = $this->getCacheInfo($key)) + /** + * @see sfCache + * {@inheritdoc} + */ + public function clean($mode = sfCache::ALL) { - return -1 == $info['ttl'] ? 0 : $info['created'] + $info['ttl']; + 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; } - return 0; - } + /** + * @see sfCache + * {@inheritdoc} + */ + public function getLastModified($key) + { + if ($info = $this->getCacheInfo($key)) { + return $info['created']; + } - protected function getCacheInfo($key) - { - $infos = eaccelerator_list_keys(); + return 0; + } - if (is_array($infos)) + /** + * @see sfCache + * {@inheritdoc} + */ + public function getTimeout($key) { - foreach ($infos as $info) - { - if ($this->getOption('prefix').$key == $info['name']) - { - return $info; + if ($info = $this->getCacheInfo($key)) { + return -1 == $info['ttl'] ? 0 : $info['created'] + $info['ttl']; } - } + + return 0; } - return null; - } + 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..9be20aadc 100644 --- a/lib/cache/sfFileCache.class.php +++ b/lib/cache/sfFileCache.class.php @@ -11,343 +11,310 @@ /** * 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 + * {@inheritdoc} + */ + public function initialize($options = array()) { - 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 = 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; + } + } + } 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); + } + } } - } - - /** - * @see sfCache - * @inheritdoc - */ - public function clean($mode = sfCache::ALL) - { - if (!is_dir($this->getOption('cache_dir'))) + + /** + * @see sfCache + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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..08da5f124 100644 --- a/lib/cache/sfFunctionCache.class.php +++ b/lib/cache/sfFunctionCache.class.php @@ -11,104 +11,98 @@ /** * 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; - - /** - * 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); + protected $cache; - $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 = array()) { - $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 = array(); - 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']; + } + + /** + * 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 = array()) - { - return md5(serialize($callable).serialize($arguments)); - } + /** + * 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)); + } } diff --git a/lib/cache/sfMemcacheCache.class.php b/lib/cache/sfMemcacheCache.class.php index de611e9ed..be29229d9 100644 --- a/lib/cache/sfMemcacheCache.class.php +++ b/lib/cache/sfMemcacheCache.class.php @@ -11,297 +11,270 @@ /** * 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 + * {@inheritdoc} + */ + public function initialize($options = array()) { - 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + public function clean($mode = sfCache::ALL) { - return 0; + if (sfCache::ALL === $mode) { + return $this->memcache->flush(); + } } - return $retval['lastModified']; - } - - /** - * @see sfCache - * @inheritdoc - */ - public function getTimeout($key) - { - if (false === ($retval = $this->getMetadata($key))) + /** + * @see sfCache + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + * + * @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')))); + } + } } - } - - /** - * @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 + * {@inheritdoc} + */ + public function getMany($keys) { - $values[str_replace($prefix, '', $key)] = $value; + $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) { + $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, array('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 = array(); + } + + 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 array(); + } - return $keys; - } + return $keys; + } } diff --git a/lib/cache/sfNoCache.class.php b/lib/cache/sfNoCache.class.php index 9891a98e4..8b08e5eba 100644 --- a/lib/cache/sfNoCache.class.php +++ b/lib/cache/sfNoCache.class.php @@ -11,82 +11,81 @@ /** * 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 + * {@inheritdoc} + */ + public function get($key, $default = null) + { + return $default; + } - /** - * @see sfCache - * @inheritdoc - */ - public function has($key) - { - return false; - } + /** + * @see sfCache + * {@inheritdoc} + */ + public function has($key) + { + return false; + } - /** - * @see sfCache - * @inheritdoc - */ - public function set($key, $data, $lifetime = null) - { - return true; - } + /** + * @see sfCache + * {@inheritdoc} + */ + public function set($key, $data, $lifetime = null) + { + return true; + } - /** - * @see sfCache - * @inheritdoc - */ - public function remove($key) - { - return true; - } + /** + * @see sfCache + * {@inheritdoc} + */ + public function remove($key) + { + return true; + } - /** - * @see sfCache - * @inheritdoc - */ - public function removePattern($pattern) - { - return true; - } + /** + * @see sfCache + * {@inheritdoc} + */ + public function removePattern($pattern) + { + return true; + } - /** - * @see sfCache - * @inheritdoc - */ - public function clean($mode = self::ALL) - { - return true; - } + /** + * @see sfCache + * {@inheritdoc} + */ + public function clean($mode = self::ALL) + { + return true; + } - /** - * @see sfCache - * @inheritdoc - */ - public function getLastModified($key) - { - return 0; - } + /** + * @see sfCache + * {@inheritdoc} + */ + public function getLastModified($key) + { + return 0; + } - /** - * @see sfCache - * @inheritdoc - */ - public function getTimeout($key) - { - return 0; - } + /** + * @see sfCache + * {@inheritdoc} + */ + public function getTimeout($key) + { + return 0; + } } diff --git a/lib/cache/sfSQLiteCache.class.php b/lib/cache/sfSQLiteCache.class.php index 093e0a0db..fb81e4a4b 100644 --- a/lib/cache/sfSQLiteCache.class.php +++ b/lib/cache/sfSQLiteCache.class.php @@ -11,341 +11,312 @@ /** * 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 + * {@inheritdoc} + */ + public function initialize($options = array()) { - 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 + * {@inheritdoc} + */ + 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 = 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']; + } + } + + 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 = array(); + 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', array($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 = array( + '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 = version_compare(PHP_VERSION, '5.3', '>') ? 3 : 2; + } + + return $this->sqlLiteVersion; + } } diff --git a/lib/cache/sfXCacheCache.class.php b/lib/cache/sfXCacheCache.class.php index 5d2642270..9e8427364 100644 --- a/lib/cache/sfXCacheCache.class.php +++ b/lib/cache/sfXCacheCache.class.php @@ -11,219 +11,198 @@ /** * 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')) + /** + * Initializes this sfCache instance. + * + * Available options: + * + * * see sfCache for options available for all drivers + * + * @see sfCache + * {@inheritdoc} + */ + public function initialize($options = array()) { - throw new sfInitializationException('You must have XCache installed and enabled to use sfXCacheCache class.'); + 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.'); + } } - if (!ini_get('xcache.var_size')) + /** + * @see sfCache + * {@inheritdoc} + */ + public function get($key, $default = null) { - throw new sfInitializationException('You must set the "xcache.var_size" variable to a value greater than 0 to use sfXCacheCache class.'); - } - } + $set = $this->getBaseValue($key); - /** - * @see sfCache - * @inheritdoc - */ - public function get($key, $default = null) - { + if (!is_array($set) || !array_key_exists('data', $set)) { + return $default; + } - $set = $this->getBaseValue($key); + return $set['data']; + } - if (!is_array($set) || !array_key_exists('data', $set)) + /** + * @see sfCache + * {@inheritdoc} + */ + public function has($key) { - - return $default; + return xcache_isset($this->getOption('prefix').$key); } - 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) + /** + * @see sfCache + * {@inheritdoc} + */ + public function set($key, $data, $lifetime = null) { - return true; - } + $lifetime = $this->getLifetime($lifetime); - $this->checkAuth(); + $set = array( + 'timeout' => time() + $lifetime, + 'data' => $data, + 'ctime' => time(), + ); + + return xcache_set($this->getOption('prefix').$key, $set, $lifetime); + } - for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++) + /** + * @see sfCache + * {@inheritdoc} + */ + public function remove($key) { - if (false === xcache_clear_cache(XC_TYPE_VAR, $i)) - { - return false; - } + return xcache_unset($this->getOption('prefix').$key); } - return true; - } + /** + * @see sfCache + * {@inheritdoc} + */ + public function clean($mode = sfCache::ALL) + { + if (sfCache::ALL !== $mode) { + return true; + } - /** - * @see sfCache - * @inheritdoc - */ - public function getLastModified($key) - { - $set = $this->getBaseValue($key); + $this->checkAuth(); - if (!is_array($set) || !array_key_exists('ctime', $set)) - { + for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; ++$i) { + if (false === xcache_clear_cache(XC_TYPE_VAR, $i)) { + return false; + } + } - return 0; + return true; } - return $set['ctime']; - } + /** + * @see sfCache + * {@inheritdoc} + */ + public function getLastModified($key) + { + $set = $this->getBaseValue($key); - /** - * @see sfCache - * @inheritdoc - */ - public function getTimeout($key) - { + if (!is_array($set) || !array_key_exists('ctime', $set)) { + return 0; + } - $set = $this->getBaseValue($key); + return $set['ctime']; + } - if (!is_array($set) || !array_key_exists('timeout', $set)) + /** + * @see sfCache + * {@inheritdoc} + */ + public function getTimeout($key) { + $set = $this->getBaseValue($key); + + if (!is_array($set) || !array_key_exists('timeout', $set)) { + return 0; + } - return 0; + return $set['timeout']; } - 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++) + /** + * @param string $key + * + * @return mixed|null + */ + public function getBaseValue($key) { - $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']); - } - } + return xcache_isset($this->getOption('prefix').$key) ? xcache_get($this->getOption('prefix').$key) : null; } - } - /** - * @param string $key - * @return array|null - */ - public function getCacheInfo($key) - { - $this->checkAuth(); - - for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++) + /** + * @see sfCache + * {@inheritdoc} + */ + public function removePattern($pattern) { - $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; - } + $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']); + } + } } - } } - return null; - } + /** + * @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; + } + } + } + } - protected function checkAuth() - { - if (ini_get('xcache.admin.enable_auth')) + return null; + } + + protected function checkAuth() { - throw new sfConfigurationException('To use all features of the "sfXCacheCache" class, you must set "xcache.admin.enable_auth" to "Off" in your php.ini.'); + 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..8b423443c 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, array('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 2f6c29e14..bae2f2406 100644 --- a/lib/command/sfAnsiColorFormatter.class.php +++ b/lib/command/sfAnsiColorFormatter.class.php @@ -11,120 +11,109 @@ /** * 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); - - /** - * 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; - } + 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), + ); + protected $options = array('bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8); + protected $foreground = array('black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37); + protected $background = array('black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47); - /** - * 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 = array()) { - 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 = array()) { - $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 = 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; + } + } + + 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; + } - $subsize = floor(($size - 3) / 2); + if (strlen($text) < $size) { + return $text; + } - return substr($text, 0, $subsize).$this->format('...', 'INFO').substr($text, -$subsize); - } + $subsize = floor(($size - 3) / 2); + + 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 8a46d7db1..7d05b0eec 100644 --- a/lib/command/sfCommandApplication.class.php +++ b/lib/command/sfCommandApplication.class.php @@ -11,698 +11,655 @@ /** * 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-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) - { - $r = new ReflectionClass($class); + /** @var bool */ + protected $nowrite = false; - if ($r->isSubclassOf('sfTask') && !$r->isAbstract()) - { - $tasks[] = new $class($this->dispatcher, $this->formatter); - } - } + /** @var string */ + protected $name = 'UNKNOWN'; - 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])) - { - throw new sfCommandException(sprintf('The task "%s" does not exist.', $name)); - } + /** @var string */ + protected $version = 'UNKNOWN'; - 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) - { - $messages[] = sprintf(' %-24s %s %s', - $this->formatter->format('--'.$option->getName(), 'INFO'), - $option->getShortcut() ? $this->formatter->format('-'.$option->getShortcut(), 'INFO') : ' ', - $option->getHelp() - ); - } + /** @var array */ + protected $tasks = array(); + + /** @var sfTask */ + protected $currentTask; - $this->dispatcher->notify(new sfEvent($this, 'command.log', $messages)); - } + /** @var sfEventDispatcher */ + protected $dispatcher; - /** - * 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; + /** @var array */ + protected $options = array(); - // the order of option processing matters + /** @var sfFormatter */ + protected $formatter; - if ($this->commandManager->getOptionSet()->hasOption('color') && false !== $this->commandManager->getOptionValue('color')) + /** @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->setFormatter(new sfAnsiColorFormatter()); + $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-debug', '', sfCommandOption::PARAMETER_NONE, 'Disable debug'), + )); + $this->commandManager = new sfCommandManager($argumentSet, $optionSet); + + $this->configure(); + + $this->registerTasks(); } - if ($this->commandManager->getOptionSet()->hasOption('quiet') && false !== $this->commandManager->getOptionValue('quiet')) + /** + * 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) { - $this->verbose = false; + return isset($this->options[$name]) ? $this->options[$name] : null; } - if ($this->commandManager->getOptionSet()->hasOption('no-debug') && false !== $this->commandManager->getOptionValue('no-debug')) + /** + * Returns the formatter instance. + * + * @return sfFormatter The formatter instance + */ + public function getFormatter() { - $this->debug = false; + return $this->formatter; } - if ($this->commandManager->getOptionSet()->hasOption('trace') && false !== $this->commandManager->getOptionValue('trace')) + /** + * Sets the formatter instance. + * + * @param sfFormatter $formatter The formatter instance + */ + public function setFormatter(sfFormatter $formatter) { - $this->verbose = true; - $this->trace = true; + $this->formatter = $formatter; + + foreach ($this->getTasks() as $task) { + $task->setFormatter($formatter); + } } - if ($this->commandManager->getOptionSet()->hasOption('help') && false !== $this->commandManager->getOptionValue('help')) + public function clearTasks() { - $this->help(); - exit(0); + $this->tasks = array(); } - if ($this->commandManager->getOptionSet()->hasOption('version') && false !== $this->commandManager->getOptionValue('version')) + /** + * 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) { - echo $this->getLongVersion(); - exit(0); + if (null === $tasks) { + $tasks = $this->autodiscoverTasks(); + } + + foreach ($tasks as $task) { + $this->registerTask($task); + } } - } - - /** - * 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) + + /** + * Registers a task object. + * + * @param sfTask $task An sfTask object + * + * @throws sfCommandException + */ + public function registerTask(sfTask $task) { - $lines[] = sprintf(' %s ', $line); - $len = max($this->strlen($line) + 4, $len); - } + 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()]))); + } - $messages = array(str_repeat(' ', $len)); + $this->tasks[$task->getFullName()] = $task; - if ($this->trace) - { - $messages[] = $title.str_repeat(' ', $len - $this->strlen($title)); + 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; + } } - foreach ($lines as $line) + /** + * Autodiscovers task classes. + * + * @return array An array of tasks instances + */ + public function autodiscoverTasks() { - $messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); - } + $tasks = array(); + foreach (get_declared_classes() as $class) { + $r = new ReflectionClass($class); - $messages[] = str_repeat(' ', $len); + if ($r->isSubclassOf('sfTask') && !$r->isAbstract()) { + $tasks[] = new $class($this->dispatcher, $this->formatter); + } + } - fwrite(STDERR, "\n"); - foreach ($messages as $message) - { - fwrite(STDERR, $this->formatter->format($message, 'ERROR', STDERR)."\n"); + return $tasks; } - fwrite(STDERR, "\n"); - if (null !== $this->currentTask && $e instanceof sfCommandArgumentsException) + /** + * Returns all registered tasks. + * + * @return array An array of sfTask objects + */ + public function getTasks() { - fwrite(STDERR, $this->formatter->format(sprintf($this->currentTask->getSynopsis(), $this->getName()), 'INFO', STDERR)."\n"); - fwrite(STDERR, "\n"); + return $this->tasks; } - if ($this->trace) + /** + * 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) { - 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"); + if (!isset($this->tasks[$name])) { + throw new sfCommandException(sprintf('The task "%s" does not exist.', $name)); + } + + return $this->tasks[$name]; } - $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, ':')) + /** + * 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) { - $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]; - } + $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; } - else + + /** + * Gets the name of the application. + * + * @return string The application name + */ + public function getName() { - $namespace = ''; + return $this->name; } - // name - $tasks = array(); - foreach ($this->tasks as $taskName => $task) + /** + * Sets the application name. + * + * @param string $name The application name + */ + public function setName($name) { - if ($taskName == $task->getFullName() && $task->getNamespace() == $namespace) - { - $tasks[] = $task->getName(); - } + $this->name = $name; } - $abbrev = $this->getAbbreviations($tasks); - if (isset($abbrev[$name]) && count($abbrev[$name]) == 1) + /** + * Gets the application version. + * + * @return string The application version + */ + public function getVersion() { - return $this->getTask($namespace ? $namespace.':'.$abbrev[$name][0] : $abbrev[$name][0]); + return $this->version; } - // aliases - $aliases = array(); - foreach ($this->tasks as $taskName => $task) + /** + * Sets the application version. + * + * @param string $version The application version + */ + public function setVersion($version) { - if ($taskName == $task->getFullName()) - { - foreach ($task->getAliases() as $alias) - { - $aliases[] = $alias; - } - } + $this->version = $version; } - $abbrev = $this->getAbbreviations($aliases); - $fullName = $namespace ? $namespace.':'.$name : $name; - if (!isset($abbrev[$fullName])) + /** + * Returns the long version of the application. + * + * @return string The long application version + */ + public function getLongVersion() { - throw new sfCommandException(sprintf('Task "%s" is not defined.', $fullName)); + return sprintf('%s version %s', $this->getName(), $this->formatter->format($this->getVersion(), 'INFO'))."\n"; } - else if (count($abbrev[$fullName]) > 1) + + /** + * Returns whether the application must be verbose. + * + * @return bool true if the application must be verbose, false otherwise + */ + public function isVerbose() { - throw new sfCommandException(sprintf('Task "%s" is ambiguous (%s).', $fullName, implode(', ', $abbrev[$fullName]))); + return $this->verbose; } - else + + /** + * Returns whether the application must activate the trace. + * + * @return bool true if the application must activate the trace, false otherwise + */ + public function withTrace() { - return $this->getTask($abbrev[$fullName][0]); + return $this->trace; } - } - protected function strlen($string) - { - if (!function_exists('mb_strlen')) { - return strlen($string); + /** + * Returns whether the application must be verbose. + * + * @return bool true if the application is in debug mode, false otherwise + */ + public function isDebug() + { + return $this->debug; } - if (false === $encoding = mb_detect_encoding($string)) { - return strlen($string); + /** + * 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) { + $messages[] = sprintf( + ' %-24s %s %s', + $this->formatter->format('--'.$option->getName(), 'INFO'), + $option->getShortcut() ? $this->formatter->format('-'.$option->getShortcut(), 'INFO') : ' ', + $option->getHelp() + ); + } + + $this->dispatcher->notify(new sfEvent($this, 'command.log', $messages)); } - 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) + /** + * Renders an exception. + * + * @param Exception $e An exception object + */ + public function renderException($e) { - @ob_end_flush(); - } + $title = sprintf(' [%s] ', get_class($e)); + $len = $this->strlen($title); + $lines = array(); + foreach (explode("\n", $e->getMessage()) as $line) { + $lines[] = sprintf(' %s ', $line); + $len = max($this->strlen($line) + 4, $len); + } + + $messages = array(str_repeat(' ', $len)); - ob_implicit_flush(true); + if ($this->trace) { + $messages[] = $title.str_repeat(' ', $len - $this->strlen($title)); + } - // PHP ini settings - set_time_limit(0); - ini_set('track_errors', true); - ini_set('html_errors', false); - ini_set('magic_quotes_runtime', false); + foreach ($lines as $line) { + $messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); + } - if (false === strpos(PHP_SAPI, 'cgi')) - { - return; - } + $messages[] = str_repeat(' ', $len); - // define stream constants - define('STDIN', fopen('php://stdin', 'r')); - define('STDOUT', fopen('php://stdout', 'w')); - define('STDERR', fopen('php://stderr', 'w')); + fwrite(STDERR, "\n"); + foreach ($messages as $message) { + fwrite(STDERR, $this->formatter->format($message, 'ERROR', STDERR)."\n"); + } + fwrite(STDERR, "\n"); - // change directory - if (isset($_SERVER['PWD'])) - { - chdir($_SERVER['PWD']); + if (null !== $this->currentTask && $e instanceof sfCommandArgumentsException) { + fwrite(STDERR, $this->formatter->format(sprintf($this->currentTask->getSynopsis(), $this->getName()), 'INFO', STDERR)."\n"); + fwrite(STDERR, "\n"); + } + + if ($this->trace) { + fwrite(STDERR, $this->formatter->format("Exception trace:\n", 'COMMENT')); + + // exception related properties + $trace = $e->getTrace(); + array_unshift($trace, array( + 'function' => '', + 'file' => null != $e->getFile() ? $e->getFile() : 'n/a', + 'line' => null != $e->getLine() ? $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->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 = 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)); + } + 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 = array(); + 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 = array(); + 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('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 = array(); + $table = array(); + + 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] = array($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] = array($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..380590e80 100644 --- a/lib/command/sfCommandArgument.class.php +++ b/lib/command/sfCommandArgument.class.php @@ -11,128 +11,118 @@ /** * 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 = array(); + } 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..b641a8603 100644 --- a/lib/command/sfCommandArgumentSet.class.php +++ b/lib/command/sfCommandArgumentSet.class.php @@ -11,173 +11,160 @@ /** * 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 = array(); + protected $requiredCount = 0; + protected $hasAnArrayArgument = false; + protected $hasOptional = false; + + /** + * Constructor. + * + * @param array $arguments An array of sfCommandArgument objects + */ + public function __construct($arguments = array()) { - 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 = array()) { - throw new sfCommandException(sprintf('An argument with name "%s" already exist.', $argument->getName())); + $this->arguments = array(); + $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 = array()) { - 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 = array(); + 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..0dff151aa 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,9 +11,8 @@ /** * 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..5b7627482 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,9 +11,8 @@ /** * 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..b81347180 100644 --- a/lib/command/sfCommandLogger.class.php +++ b/lib/command/sfCommandLogger.class.php @@ -3,59 +3,54 @@ /* * 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 = array()) { - $subject = $event->getSubject(); - $subject = is_object($subject) ? get_class($subject) : (is_string($subject) ? $subject : 'main'); + $dispatcher->connect('command.log', array($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..7d148ada3 100644 --- a/lib/command/sfCommandManager.class.php +++ b/lib/command/sfCommandManager.class.php @@ -11,383 +11,346 @@ /** * 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 = array(); + + /** @var sfCommandOptionSet */ + protected $optionSet; + + /** @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) { - $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 = array(); + $this->errors = array(); + + while (!in_array($argument = array_shift($this->arguments), array('', 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; + } } - else - { - $this->argumentValues[$argument->getName()] = $this->parsedArgumentValues[$position]; + + $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; + } + + $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..43e1f91d3 100644 --- a/lib/command/sfCommandOption.class.php +++ b/lib/command/sfCommandOption.class.php @@ -11,180 +11,166 @@ /** * 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) + { + 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); + } + + /** + * Returns the shortcut. + * + * @return string The shortcut + */ + public function getShortcut() + { + return $this->shortcut; + } + + /** + * Returns the name. + * + * @return string The name + */ + public function getName() { - $name = substr($name, 2); + return $this->name; } - if (empty($shortcut)) + /** + * Returns true if the option accept a parameter. + * + * @return bool true if parameter mode is not self::PARAMETER_NONE, false otherwise + */ + public function acceptParameter() { - $shortcut = null; + return $this->isParameterRequired() || $this->isParameterOptional(); } - if (null !== $shortcut) + /** + * Returns true if the option requires a parameter. + * + * @return bool true if parameter mode is self::PARAMETER_REQUIRED, false otherwise + */ + public function isParameterRequired() { - if ('-' == $shortcut[0]) - { - $shortcut = substr($shortcut, 1); - } + return self::PARAMETER_REQUIRED === (self::PARAMETER_REQUIRED & $this->mode); } - if (null === $mode) + /** + * Returns true if the option takes an optional parameter. + * + * @return bool true if parameter mode is self::PARAMETER_OPTIONAL, false otherwise + */ + public function isParameterOptional() { - $mode = self::PARAMETER_NONE; + return self::PARAMETER_OPTIONAL === (self::PARAMETER_OPTIONAL & $this->mode); } - else if (is_string($mode) || $mode > 15) + + /** + * Returns true if the option can take multiple values. + * + * @return bool true if mode is self::IS_ARRAY, false otherwise + */ + public function isArray() { - throw new sfCommandException(sprintf('Option mode "%s" is not valid.', $mode)); + return self::IS_ARRAY === (self::IS_ARRAY & $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) + /** + * Sets the default value. + * + * @param mixed $default The default value + * + * @throws sfCommandException + */ + public function setDefault($default = null) { - throw new sfCommandException('Cannot set a default value when using sfCommandOption::PARAMETER_NONE mode.'); + 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 = array(); + } elseif (!is_array($default)) { + throw new sfCommandException('A default value for an array option must be an array.'); + } + } + + $this->default = $this->acceptParameter() ? $default : false; } - if ($this->isArray()) + /** + * Returns the default value. + * + * @return mixed The default value + */ + public function getDefault() { - 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 $this->default; } - $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; - } + /** + * 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..49792f5db 100644 --- a/lib/command/sfCommandOptionSet.class.php +++ b/lib/command/sfCommandOptionSet.class.php @@ -11,174 +11,165 @@ /** * 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 = array(); + protected $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) { + $this->addOption($option); + } + } + + /** + * Add a sfCommandOption objects. + * + * @param sfCommandOption $option A sfCommandOption object + * + * @throws sfCommandException + */ + public function addOption(sfCommandOption $option) { - $this->addOption($option); + 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(); + } } - } - - /** - * Add a sfCommandOption objects. - * - * @param sfCommandOption $option A sfCommandOption object - * - * @throws sfCommandException - */ - public function addOption(sfCommandOption $option) - { - if (isset($this->options[$option->getName()])) + + /** + * 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('An option named "%s" already exist.', $option->getName())); + if (!$this->hasOption($name)) { + throw new sfCommandException(sprintf('The "--%s" option does not exist.', $name)); + } + + return $this->options[$name]; } - else if (isset($this->shortcuts[$option->getShortcut()])) + + /** + * 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) { - throw new sfCommandException(sprintf('An option with shortcut "%s" already exist.', $option->getShortcut())); + return isset($this->options[$name]); } - $this->options[$option->getName()] = $option; - if ($option->getShortcut()) + /** + * Gets the array of sfCommandOption objects. + * + * @return sfCommandOption[] An array of sfCommandOption objects + */ + public function getOptions() { - $this->shortcuts[$option->getShortcut()] = $option->getName(); + return $this->options; } - } - - /** - * 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 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) { - throw new sfCommandException(sprintf('The "--%s" option does not exist.', $name)); + return isset($this->shortcuts[$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) + /** + * Gets an option by shortcut. + * + * @param string $shortcut + * + * @return sfCommandOption A sfCommandOption object + */ + public function getOptionForShortcut($shortcut) { - $values[$option->getName()] = $option->getDefault(); + return $this->getOption($this->shortcutToName($shortcut)); } - 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 an array of default values. + * + * @return array An array of all default values + */ + public function getDefaults() { - throw new sfCommandException(sprintf('The "-%s" option does not exist.', $shortcut)); + $values = array(); + foreach ($this->options as $option) { + $values[$option->getName()] = $option->getDefault(); + } + + return $values; } - return $this->shortcuts[$shortcut]; - } + /** + * 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..c5b776ff0 100644 --- a/lib/command/sfFormatter.class.php +++ b/lib/command/sfFormatter.class.php @@ -11,110 +11,101 @@ /** * 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; - } - } + 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; + } + } - $this->size = $maxLineSize; - } - - /** - * 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 = array()) + { + } - /** - * 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 = array()) { - $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..11caf20f8 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,131 @@ /** * 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 = array(); + + /** + * 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 = array(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(array($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(array($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 9c401e189..f89b42735 100644 --- a/lib/config/sfApplicationConfiguration.class.php +++ b/lib/config/sfApplicationConfiguration.class.php @@ -11,691 +11,634 @@ /** * 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 = array(); + + protected $configCache; + protected $application; + protected $environment; + protected $debug = false; + protected $config = array(); + 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', array($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 + ini_set('display_errors', $this->isDebug() ? 'on' : 'off'); + 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 = 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; + } + } + + exit(1); + } } - // error settings - ini_set('display_errors', $this->isDebug() ? 'on' : 'off'); - 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(array( + '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(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', + )); } - } - - /** - * 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 + * + * @param mixed $cacheDir + */ + public function setCacheDir($cacheDir) { - $config = $configuration->filterAutoloadConfig($event, $config); + 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', + )); } - 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 = array(); + + $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 = 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 - 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 = 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; } - 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 = array(); - $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, + 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 + ); + } - $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 array(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 = array(); + + // 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 = array(); + + // 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 = array( + $this->getSymfonyLibDir().'/config/'.$globalConfigPath, // symfony + ); + + foreach ($this->getPluginPaths() as $path) { + if (is_file($file = $path.'/'.$globalConfigPath)) { + $files[] = $file; // plugins + } + } + + $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) { + if (is_file($file = $path.'/'.$configPath)) { + $files[] = $file; // plugins + } + } + + $files[] = sfConfig::get('sf_app_dir').'/'.$configPath; // module + + $configs = array(); + 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(array('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..ece3fea65 100755 --- a/lib/config/sfAutoloadConfigHandler.class.php +++ b/lib/config/sfAutoloadConfigHandler.class.php @@ -10,180 +10,161 @@ */ /** - * - * @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(array('required_categories' => array('autoload'))); - // compile data - return sprintf("parse($configFiles) as $mapping) - { - foreach ($mapping as $class => $file) - { - $mappings[$class] = $file; - } - } + $data = array(); + 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 = array(); + 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 = 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) { + $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 + * {@inheritdoc} + */ + 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 = array(); + + // 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 = array(); + foreach ($config['autoload'] as $name => $entry) { + $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); + } + + // 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..4e64bf451 100644 --- a/lib/config/sfCacheConfigHandler.class.php +++ b/lib/config/sfCacheConfigHandler.class.php @@ -11,105 +11,110 @@ /** * 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 = 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) { - if ($actionName == 'all') - { - continue; - } - - $data[] = $this->addCache($actionName); - - $first = false; + // parse the yaml + $this->yamlConfig = static::getConfiguration($configFiles); + + // iterate through all action names + $data = array(); + $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 + * {@inheritdoc} + */ + 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, '0'); - // 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, array()); + if (!is_array($vary)) { + $vary = array($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..149156991 100644 --- a/lib/config/sfCompileConfigHandler.class.php +++ b/lib/config/sfCompileConfigHandler.class.php @@ -13,82 +13,80 @@ * 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, array('/^\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(array('/\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 = array(); - /** - * 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 = array()) + { + 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 = array(); + } } diff --git a/lib/config/sfConfigCache.class.php b/lib/config/sfConfigCache.class.php index 7486bf06d..975eae7e2 100644 --- a/lib/config/sfConfigCache.class.php +++ b/lib/config/sfConfigCache.class.php @@ -14,379 +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 = array(); + protected $userHandlers = array(); + + /** + * 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) ? array($configPath) : array(); } - } - } - 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(array('\\', '/', ' '), '_', $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 = array()) { - // 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, 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 (!$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 = array('.', '..', '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 = array('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); + } + } + + chmod($cache, 0666); + umask($current_umask); } - chmod($cache, 0666); - 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(); - } + /** + * 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..728033f8f 100644 --- a/lib/config/sfConfigHandler.class.php +++ b/lib/config/sfConfigHandler.class.php @@ -14,122 +14,113 @@ * 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; - - /** - * 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); + /** @var sfParameterHolder */ + protected $parameterHolder; - /** - * 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..027d861d4 100644 --- a/lib/config/sfDatabaseConfigHandler.class.php +++ b/lib/config/sfDatabaseConfigHandler.class.php @@ -14,137 +14,128 @@ * 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); - } - - foreach ($data as $name => $database) - { - $data[$name] = sprintf("\n'%s' => new %s(%s),", $name, $database[0], var_export($database[1], true)); - } + list($includes, $data) = $this->parse($configFiles); - // 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 = array(); + 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 + * {@inheritdoc} + */ + 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'])); - } + $config = static::replaceConstants(static::flattenConfigurationWithEnvironment(static::parseYamls($configFiles))); - // append our data - $includes[] = $dbConfig['file']; - } - - // 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 = array(); + $databases = array(); + $includes = array(); + + // 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 = array(); + if (isset($dbConfig['param'])) { + $parameters = $dbConfig['param']; + } + $parameters['name'] = $name; + + // append new data + $data[$name] = array($dbConfig['class'], $parameters); + } - return $config; - } + return array($includes, $data); + } } diff --git a/lib/config/sfDefineEnvironmentConfigHandler.class.php b/lib/config/sfDefineEnvironmentConfigHandler.class.php index 224dc2525..9fe7c7e19 100644 --- a/lib/config/sfDefineEnvironmentConfigHandler.class.php +++ b/lib/config/sfDefineEnvironmentConfigHandler.class.php @@ -9,141 +9,130 @@ */ /** - * - * @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)) - { - $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 = array(); - foreach ($config as $category => $keys) + /** + * 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) { - $values = array_merge($values, $this->getValues($prefix, $category, $keys)); + // 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 = array(); + 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 = " $value) + /** + * @see sfConfigHandler + * {@inheritdoc} + */ + public static function getConfiguration(array $configFiles) { - $data .= sprintf(" '%s' => %s,\n", $key, var_export($value, true)); + return static::replaceConstants(static::flattenConfigurationWithEnvironment(static::parseYamls($configFiles))); } - // compile data - $retval = ''; - if ($values) + /** + * 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) { - $retval = "fixCategoryValue($prefix.strtolower($category), '', $keys); - 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); + return array($key => $value); + } - return array($key => $value); - } + $values = array(); - $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 array($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..8e0ddc3c6 100644 --- a/lib/config/sfFactoryConfigHandler.class.php +++ b/lib/config/sfFactoryConfigHandler.class.php @@ -13,257 +13,265 @@ * 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 = 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) { + // see if the factory exists for this controller + $keys = $config[$factory]; - $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'])) - { + 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)); } - unset($parameters['loggers']); - } + $class = $keys['class']; - $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; + 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']); + } + + // 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])); + } + + $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 = 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'])) { + // 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) + ); - case 'service_container': - $instances[] = ( + break; + + 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 + * {@inheritdoc} + */ + 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..2eccac23b 100644 --- a/lib/config/sfFilterConfigHandler.class.php +++ b/lib/config/sfFilterConfigHandler.class.php @@ -12,149 +12,178 @@ /** * 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 = array(); + $includes = array(); + + $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 = 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; } - 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 +191,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..e79827ff9 100644 --- a/lib/config/sfGeneratorConfigHandler.class.php +++ b/lib/config/sfGeneratorConfigHandler.class.php @@ -11,83 +11,77 @@ /** * 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 (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)); + } + } - // 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'] : array()); - // 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 + * {@inheritdoc} + */ + 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..babc1c5f1 100644 --- a/lib/config/sfPluginConfiguration.class.php +++ b/lib/config/sfPluginConfiguration.class.php @@ -11,222 +11,204 @@ /** * 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() { - $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 + + /** + * Configures the plugin. + * + * This method is called before the plugin's classes have been added to sfAutoload. + */ + public function configure() { - $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'])) + /** + * 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() { - $config['autoload'] = array_merge(array( - $this->name.'_lib' => array( - 'path' => $this->rootDir.'/lib', - 'recursive' => true, - ), - ), $config['autoload']); } - if (!isset($config['autoload'][$this->name.'_module_libs'])) + /** + * Returns the plugin root directory. + * + * @return string + */ + public function getRootDir() { - $config['autoload'] = array_merge(array( - $this->name.'_module_libs' => array( - 'path' => $this->rootDir.'/modules/*/lib', - 'recursive' => true, - 'prefix' => 1, - ), - ), $config['autoload']); + return $this->rootDir; } - 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) + /** + * Returns the plugin name. + * + * @return string + */ + public function getName() { - $directory = $this->rootDir.'/test'; - $names = array(); + return $this->name; } - else if ($task instanceof sfTestFunctionalTask) + + /** + * 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/functional'; - $names = $event['arguments']['controller']; + $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', array($this, 'filterAutoloadConfig')); + $autoload->loadConfiguration(array($file)); + $this->configuration->getEventDispatcher()->disconnect('autoload.filter_config', array($this, 'filterAutoloadConfig')); + } else { + $autoload->addDirectory($this->rootDir.'/lib'); + } + + $autoload->register(); } - else if ($task instanceof sfTestUnitTask) + + /** + * Filters sfAutoload configuration values. + * + * @return array + */ + public function filterAutoloadConfig(sfEvent $event, array $config) { - $directory = $this->rootDir.'/test/unit'; - $names = $event['arguments']['name']; + // 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(array( + $this->name.'_lib' => array( + 'path' => $this->rootDir.'/lib', + 'recursive' => true, + ), + ), $config['autoload']); + } + + if (!isset($config['autoload'][$this->name.'_module_libs'])) { + $config['autoload'] = array_merge(array( + $this->name.'_module_libs' => array( + 'path' => $this->rootDir.'/modules/*/lib', + 'recursive' => true, + 'prefix' => 1, + ), + ), $config['autoload']); + } + + return $config; } - if (!count($names)) + /** + * Connects the current plugin's tests to the "test:*" tasks. + */ + public function connectTests() { - $names = array('*'); + $this->dispatcher->connect('task.test.filter_test_files', array($this, 'filterTestFiles')); } - foreach ($names as $name) + /** + * 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) { - $finder = sfFinder::type('file')->follow_link()->name(basename($name).'Test.php'); - $files = array_merge($files, $finder->in($directory.'/'.dirname($name))); + $task = $event->getSubject(); + + if ($task instanceof sfTestAllTask) { + $directory = $this->rootDir.'/test'; + $names = array(); + } 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 = array('*'); + } + + 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); } - 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 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); + } } diff --git a/lib/config/sfPluginConfigurationGeneric.class.php b/lib/config/sfPluginConfigurationGeneric.class.php index 127210c13..d7d9eff99 100644 --- a/lib/config/sfPluginConfigurationGeneric.class.php +++ b/lib/config/sfPluginConfigurationGeneric.class.php @@ -11,18 +11,17 @@ /** * 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..0f8c12fed 100644 --- a/lib/config/sfProjectConfiguration.class.php +++ b/lib/config/sfProjectConfiguration.class.php @@ -11,635 +11,600 @@ /** * 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 = array(); + + /** @var array */ + protected $pluginPaths = array(); + + /** @var array */ + protected $overriddenPluginPaths = array(); + + /** @var sfPluginConfiguration[] */ + protected $pluginConfigurations = array(); + + /** @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', array('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(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'); + } - /** - * 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(array( + '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 + array(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( + 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) + ); } - $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( + 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) + ); } - 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 = array( + $this->getSymfonyLibDir().'/config/'.$globalConfigPath, // symfony + ); + + foreach ($this->getPluginPaths() as $path) { + if (is_file($file = $path.'/'.$globalConfigPath)) { + $files[] = $file; // plugins + } + } + + $files = array_merge($files, array( + $this->getRootDir().'/'.$globalConfigPath, // project + $this->getRootDir().'/'.$configPath, // project + )); - $this->pluginPaths = array(); - } + foreach ($this->getPluginPaths() as $path) { + if (is_file($file = $path.'/'.$configPath)) { + $files[] = $file; // plugins + } + } + + $configs = array(); + foreach (array_unique($files) as $file) { + if (is_readable($file)) { + $configs[] = $file; + } + } - /** - * 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)) + 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 = array(); } - $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 = array($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 = array($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 = array(); } - 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 = array()) { - 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] = array(); + $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[''] = array(); + 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 = 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) { + $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..e4837cae6 100644 --- a/lib/config/sfRootConfigHandler.class.php +++ b/lib/config/sfRootConfigHandler.class.php @@ -12,102 +12,97 @@ * 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 = array(); + $includes = array(); - // 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..ac82d5cc9 100644 --- a/lib/config/sfRoutingConfigHandler.class.php +++ b/lib/config/sfRoutingConfigHandler.class.php @@ -9,109 +9,105 @@ */ /** - * @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 = array(); + 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 : 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)); + } + } + + return sprintf( + "parse($configFiles); - protected function getOptions() - { - $config = sfFactoryConfigHandler::getConfiguration(sfContext::getInstance()->getConfiguration()->getConfigPaths('config/factories.yml')); - return $config['routing']['param']; - } + $routes = array(); + 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); + + // collect routes + $routes = array(); + 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'] : array(); + $options['name'] = $name; + $options['requirements'] = isset($params['requirements']) ? $params['requirements'] : array(); - return $routes; - } + $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(), + )); + } + } - /** - * @see sfConfigHandler - */ - static public function getConfiguration(array $configFiles) - { - return static::parseYamls($configFiles); - } + return $routes; + } } diff --git a/lib/config/sfSecurityConfigHandler.class.php b/lib/config/sfSecurityConfigHandler.class.php index 57efcfb27..6c4dccb01 100644 --- a/lib/config/sfSecurityConfigHandler.class.php +++ b/lib/config/sfSecurityConfigHandler.class.php @@ -11,49 +11,51 @@ /** * 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 + * {@inheritdoc} + */ + 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..55e3935bb 100644 --- a/lib/config/sfServiceConfigHandler.class.php +++ b/lib/config/sfServiceConfigHandler.class.php @@ -11,59 +11,61 @@ /** * 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(array( + '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 = array(); - $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 = array(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 = array(); - /** - * 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((string) $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 = array(); - /** - * 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'] : array(), isset($config['all']['stylesheets']) && is_array($config['all']['stylesheets']) ? $config['all']['stylesheets'] : array()); + 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'] : array(), isset($config['all']['javascripts']) && is_array($config['all']['javascripts']) ? $config['all']['javascripts'] : array()); + 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'] : array(), + isset($config['all']) && is_array($config['all']) ? $config['all'] : array() + ); - $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 = array(); + 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 = array(); + } + + if ('-*' == $key) { + $tmp = array(); + } 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..c2993a80f 100644 --- a/lib/config/sfYamlConfigHandler.class.php +++ b/lib/config/sfYamlConfigHandler.class.php @@ -12,147 +12,137 @@ * 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 = array(); + foreach ($configFiles as $configFile) { + // 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 = 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 ? array() : $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'] : array(), + isset($config['all']) && is_array($config['all']) ? $config['all'] : array() + ); + + 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'] : 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 $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 = array(); + + 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..5dfa30554 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,51 @@ /** * 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..1898f65a8 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..1f76fbff2 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..919af7520 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..b50638f39 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..f1b5c7e0e 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..b4dc0bdcd 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..3151ff665 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..c654d3e38 100644 --- a/lib/controller/sfController.class.php +++ b/lib/controller/sfController.class.php @@ -12,515 +12,481 @@ /** * 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 = array(); + + /** @var int */ + protected $renderMode = sfView::RENDER_CLIENT; - $this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix] = $moduleName.$classSuffix.'s'; - return true; - } + /** @var int */ + protected $maxForwards = 5; + + /** + * 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', array('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', array(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); - 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)); - } + // include module configuration + $viewClass = sfConfig::get('mod_'.strtolower($moduleName).'_view_class', false); - $this->forward($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', array('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->dispatcher->notify(new sfEvent($this, 'controller.page_not_found', array('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', array(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); + + // get raw content + $presentation = &$actionEntry->getPresentation(); + + // put render mode back + $this->setRenderMode($renderMode); + + // remove the action entry + $nb = $actionStack->getSize() - $index; + while ($nb-- > 0) { + $actionEntry = $actionStack->popEntry(); - // grab the action entry from this forward - $actionEntry = $actionStack->getEntry($index); + 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.'); + } + } - // get raw content - $presentation =& $actionEntry->getPresentation(); + // remove viewName + if ($viewName) { + sfConfig::set('mod_'.strtolower($module).'_view_class', $currentViewName); + } - // put render mode back - $this->setRenderMode($renderMode); + return $presentation; + } - // remove the action entry - $nb = $actionStack->getSize() - $index; - while ($nb-- > 0) + /** + * 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; + } + } - return; + // send an exception if debug + if ($throwExceptions && sfConfig::get('sf_debug')) { + $dirs = array_map(array('sfDebug', 'shortenFilePath'), array_keys($dirs)); + + throw new sfControllerException(sprintf('Controller "%s/%s" does not exist in: %s.', $moduleName, $controllerName, implode(', ', $dirs))); + } + + 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..5e2becdd5 100644 --- a/lib/controller/sfFrontWebController.class.php +++ b/lib/controller/sfFrontWebController.class.php @@ -14,47 +14,40 @@ * 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 = array(); - // 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); - } - catch (sfException $e) - { - $e->printStackTrace(); - } - catch (Exception $e) - { - sfException::createFromException($e)->printStackTrace(); + // make the first request + $this->forward($moduleName, $actionName); + } 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 ebf54500f..b4ca30b67 100644 --- a/lib/controller/sfWebController.class.php +++ b/lib/controller/sfWebController.class.php @@ -12,137 +12,116 @@ /** * 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)) - { - // 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] == '/') + /** + * 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 = array(), $absolute = false) { - $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 = 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); + } + + // 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,61 +129,56 @@ 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)); - } - } - - 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.'); - } + foreach ($matches as $match) { + $params[urldecode($match[1][0])] = urldecode($match[2][0]); + } - $url = $this->genUrl($url, true); - // see #8083 - $url = str_replace('&', '&', $url); + // check that all string is matched + if (!$matched) { + throw new sfParseException(sprintf('Unable to parse query string "%s".', $queryString)); + } + } - if (sfConfig::get('sf_logging_enabled')) - { - $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Redirect to "%s"', $url)))); + return array($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); + + if (sfConfig::get('sf_logging_enabled')) { + $this->dispatcher->notify(new sfEvent($this, 'application.log', array(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..9034b2e27 100644 --- a/lib/database/sfDatabase.class.php +++ b/lib/database/sfDatabase.class.php @@ -13,162 +13,157 @@ * 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 = array()) + { + $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 = array()) + { + $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..d1313aeae 100644 --- a/lib/database/sfDatabaseManager.class.php +++ b/lib/database/sfDatabaseManager.class.php @@ -14,127 +14,114 @@ * 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(); - - /** - * Class constructor. - * - * @see initialize() - * - * @param sfProjectConfiguration $configuration - * @param array $options - */ - public function __construct(sfProjectConfiguration $configuration, $options = array()) - { - $this->initialize($configuration); + /** @var sfProjectConfiguration */ + protected $configuration; + protected $databases = array(); - if (!isset($options['auto_shutdown']) || $options['auto_shutdown']) + /** + * Class constructor. + * + * @see initialize() + * + * @param array $options + */ + public function __construct(sfProjectConfiguration $configuration, $options = array()) { - register_shutdown_function(array($this, 'shutdown')); + $this->initialize($configuration); + + if (!isset($options['auto_shutdown']) || $options['auto_shutdown']) { + register_shutdown_function(array($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(array($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 index a72260a47..fac1ccd9f 100644 --- a/lib/database/sfMySQLDatabase.class.php +++ b/lib/database/sfMySQLDatabase.class.php @@ -20,105 +20,93 @@ * # password - [none] - The database password. * # persistent - [No] - Indicates that the connection should be persistent. * - * @package symfony - * @subpackage database * @author Fabien Potencier * @author Sean Kerr + * * @version SVN: $Id$ */ 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 ($password == null) - { - if ($username == null) - { - $this->connection = @$connect($host); - } - else - { - $this->connection = @$connect($host, $username); - } - } - else + /** + * Connects to the database. + * + * @throws sfDatabaseException If a connection could not be created + */ + public function connect() { - $this->connection = @$connect($host, $username, $password); - } + $database = $this->getParameter('database'); + $host = $this->getParameter('host', 'localhost'); + $password = $this->getParameter('password'); + $username = $this->getParameter('username'); + $encoding = $this->getParameter('encoding'); - // make sure the connection went through - if ($this->connection === false) - { - // the connection's foobar'd - throw new sfDatabaseException('Failed to create a MySQLDatabase connection.'); + // 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; } - // select our database - if ($this->selectDatabase($database)) + /** + * Execute the shutdown procedure. + * + * @throws sfDatabaseException If an error occurs while shutting down this database + */ + public function shutdown() { - // can't select the database - throw new sfDatabaseException(sprintf('Failed to select MySQLDatabase "%s".', $database)); + if (null != $this->connection) { + @mysql_close($this->connection); + } } - // set encoding if specified - if ($encoding) + /** + * 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) { - @mysql_query("SET NAMES '".$encoding."'", $this->connection); + return $persistent ? 'mysql_pconnect' : 'mysql_connect'; } - // since we're not an abstraction layer, we copy the connection - // to the resource - $this->resource = $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 ($database != null && !@mysql_select_db($database, $this->connection)); - } - - /** - * Execute the shutdown procedure - * - * @return void - * - * @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) { - @mysql_close($this->connection); + 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..3fb6554e8 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..b648a6ee2 100644 --- a/lib/database/sfPDODatabase.class.php +++ b/lib/database/sfPDODatabase.class.php @@ -12,103 +12,88 @@ /** * sfPDODatabase provides connectivity for the PDO database abstraction layer. * - * @package symfony - * @subpackage database * @author Daniel Swarbrick (daniel@pressure.net.nz) * @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 + * + * @return mixed + */ + public function __call($method, $arguments) { - // missing required dsn parameter - throw new sfDatabaseException('Database configuration is missing the "dsn" parameter.'); + return call_user_func_array(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 ? array(PDO::ATTR_PERSISTENT => true) : array(); - } - catch (PDOException $e) - { - throw new sfDatabaseException($e->getMessage()); - } + $this->connection = new $pdo_class($dsn, $username, $password, $options); + } 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); - } + // 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); + } - // compatability - $compatability = $this->getParameter('compat'); - if ($compatability) - { - $this->connection->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); - } - - // 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..3ebe5e30c 100644 --- a/lib/database/sfPostgreSQLDatabase.class.php +++ b/lib/database/sfPostgreSQLDatabase.class.php @@ -21,62 +21,59 @@ * # 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..4a564d140 100644 --- a/lib/debug/sfDebug.class.php +++ b/lib/debug/sfDebug.class.php @@ -11,262 +11,238 @@ /** * 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 array( + '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 = array( + '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 = array(); + foreach (array('cookie', 'server', 'get', 'post', 'files', 'env', 'session') as $name) { + if (!isset($GLOBALS['_'.strtoupper($name)])) { + continue; + } + + $values[$name] = array(); + 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 array(); + } - return $data; - } + return array( + '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 array(); } - ksort($values[$ns]); - } + + 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(), + ); } - 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 array(); + } + + $data = array( + 'options' => $user->getOptions(), + 'attributeHolder' => self::flattenParameterHolder($user->getAttributeHolder(), true), + 'culture' => $user->getCulture(), + ); + + if ($user instanceof sfBasicSecurityUser) { + $data = array_merge($data, array( + '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 = array(); + if ($parameterHolder instanceof sfNamespacedParameterHolder) { + foreach ($parameterHolder->getNamespaces() as $ns) { + $values[$ns] = array(); + foreach ($parameterHolder->getAll($ns) as $key => $value) { + $values[$ns][$key] = $value; + } + ksort($values[$ns]); + } + } else { + foreach ($parameterHolder->getAll() as $key => $value) { + $values[$key] = $value; + } + } + + if ($removeObjects) { + $values = self::removeObjects($values); + } - ksort($values); + ksort($values); - return $values; - } + return $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) + /** + * 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 (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; - } - } + $nvalues = array(); + 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 $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) + /** + * Shortens a file path by replacing symfony directory constants. + * + * @param string $file + * + * @return string + */ + public static function shortenFilePath($file) { - if (0 === strpos($file, $value = sfConfig::get($key))) - { - $file = str_replace($value, strtoupper($key), $file); - break; - } - } + foreach (array('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; - } + return $file; + } } diff --git a/lib/debug/sfTimer.class.php b/lib/debug/sfTimer.class.php index a08037784..8b85e0e9a 100644 --- a/lib/debug/sfTimer.class.php +++ b/lib/debug/sfTimer.class.php @@ -11,74 +11,71 @@ /** * 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; - - /** - * Creates a new sfTimer instance. - * - * @param string $name The name of the timer - */ - public function __construct($name = '') - { - $this->name = $name; - $this->startTimer(); - } + protected $startTime; + protected $totalTime; + protected $name = ''; + protected $calls = 0; - /** - * 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..110939ca8 100644 --- a/lib/debug/sfTimerManager.class.php +++ b/lib/debug/sfTimerManager.class.php @@ -11,57 +11,53 @@ /** * 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 = array(); - /** - * 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 = array(); + } } diff --git a/lib/debug/sfWebDebug.class.php b/lib/debug/sfWebDebug.class.php index e7b7eea82..5f6a71508 100644 --- a/lib/debug/sfWebDebug.class.php +++ b/lib/debug/sfWebDebug.class.php @@ -11,222 +11,205 @@ /** * 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 = array(); + protected $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->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'] = array(); + } - $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 $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'; } - else - { - $titles[] = sprintf('
  • %s
  • ', $title); + + if (false !== $pos = $posFunction($content, '')) { + $styles = ''; + $content = $substrFunction($content, 0, $pos).$styles.$substrFunction($content, $pos); } - } + + $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 = array(); + $panels = array(); + 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 +225,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, array('%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..ba8fb9805 100644 --- a/lib/debug/sfWebDebugPanelCache.class.php +++ b/lib/debug/sfWebDebugPanelCache.class.php @@ -12,38 +12,34 @@ * 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..c0bee63e4 100644 --- a/lib/debug/sfWebDebugPanelConfig.class.php +++ b/lib/debug/sfWebDebugPanelConfig.class.php @@ -11,71 +11,69 @@ /** * 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 = 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', + ); - return $html; - } + $html = '
      '; + foreach ($config as $key => $value) { + $html .= '
    • '.$key.'
    • '; + } + $html .= '
    '; - /** - * 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)); + $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()); - return ' + return $html; + } + + /** + * 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 805b89a5e..58802582c 100644 --- a/lib/debug/sfWebDebugPanelLogs.class.php +++ b/lib/debug/sfWebDebugPanelLogs.class.php @@ -11,65 +11,62 @@ /** * 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; - foreach ($logs as $log) + public function getTitle() { - $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, - ''.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 .= '
    #typemessage
    %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; + foreach ($logs as $log) { + $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, + ''.ucfirst($priority).'', + class_exists($log['type'], false) ? $this->formatFileLink($log['type']) : $log['type'], + $this->formatLogLine($log['message']), + $this->getToggleableDebugStack($log['debug_backtrace']) + ); + } + $html .= '
    #typemessage
    %s%s %s%s %s
    '; + + $types = array(); + foreach ($this->webDebug->getLogger()->getTypes() as $type) { + $types[] = ''.$type.''; + } + + return '
    • [all]
    • [none]
    • @@ -80,46 +77,43 @@ 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 (array('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); + // escape HTML + $logLine = htmlspecialchars($logLine, ENT_QUOTES, sfConfig::get('sf_charset')); - $logLine = sfToolkit::pregtr($logLine, array('/"(.+?)"/s' => '"\\1"', - '/^(.+?)\(\)\:/S' => '\\1():', - '/line (\d+)$/' => 'line \\1')); + // replace constants value with constant name + $logLine = str_replace(array_keys($constants), array_values($constants), $logLine); - // special formatting for SQL lines - $logLine = $this->formatSql($logLine); + $logLine = sfToolkit::pregtr($logLine, array('/"(.+?)"/s' => '"\\1"', + '/^(.+?)\(\)\:/S' => '\\1():', + '/line (\d+)$/' => 'line \\1')); - // 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..ab31b24be 100644 --- a/lib/debug/sfWebDebugPanelMailer.class.php +++ b/lib/debug/sfWebDebugPanelMailer.class.php @@ -11,96 +11,89 @@ /** * 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', array($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(); + + if (!$logger || !$messages = $logger->getMessages()) { + return false; + } - // configuration information - $strategy = $this->mailer->getDeliveryStrategy(); - $html[] = '

    Configuration

    '; - $html[] = 'Delivery strategy: '.$strategy; + $html = array(); - if (sfMailer::SINGLE_ADDRESS == $strategy) - { - $html[] = ' - all emails are delivered to: '.$this->mailer->getDeliveryAddress(); + // 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 = array(); + $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..dc1ffe2b9 100644 --- a/lib/debug/sfWebDebugPanelMemory.class.php +++ b/lib/debug/sfWebDebugPanelMemory.class.php @@ -11,25 +11,24 @@ /** * 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..e97bbd8ee 100644 --- a/lib/debug/sfWebDebugPanelSymfonyVersion.class.php +++ b/lib/debug/sfWebDebugPanelSymfonyVersion.class.php @@ -11,23 +11,22 @@ /** * 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..dc932edc5 100644 --- a/lib/debug/sfWebDebugPanelTimer.class.php +++ b/lib/debug/sfWebDebugPanelTimer.class.php @@ -11,80 +11,74 @@ /** * 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', array($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 = array(); + 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..3ff51c3a6 100644 --- a/lib/debug/sfWebDebugPanelView.class.php +++ b/lib/debug/sfWebDebugPanelView.class.php @@ -11,356 +11,321 @@ /** * 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 = array(); + protected $partials = array(); + + /** + * 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', array($this, 'listenForChangeAction')); + $this->webDebug->getEventDispatcher()->connect('template.filter_parameters', array($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 = array(); + $this->partials = array(); } - } - - /** - * @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 = array('parameters' => $parameters); + + if ('action' == $parameters['sf_type'] && $file = $this->getLastTemplate()) { + $this->actions[] = $entry + array('file' => $file); + } elseif ('partial' == $parameters['sf_type'] && $file = $this->getLastTemplate('sfPartialView')) { + $this->partials[] = $entry + array('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 = array(); + + 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 = array(); + $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', array('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 + * @param mixed $parameter + * + * @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 = array(); + $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 = 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[] = '
  • '; + } + } + + return implode("\n", $html); } - if (null === $typeFormat) + /** + * Formats information about a parameter as HTML. + * + * @param string $name + * @param mixed $parameter + * @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 = array(); + + 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..4ff181c4a 100644 --- a/lib/escaper/sfOutputEscaper.class.php +++ b/lib/escaper/sfOutputEscaper.class.php @@ -11,233 +11,214 @@ /** * 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. + * + * @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; + + protected static $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) { - 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(array($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 5cc37aaf6..d4d483b98 100644 --- a/lib/escaper/sfOutputEscaperArrayDecorator.class.php +++ b/lib/escaper/sfOutputEscaperArrayDecorator.class.php @@ -12,177 +12,177 @@ * 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) - { - $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]; - } + /** + * 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) + { + $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..e3cac0665 100644 --- a/lib/escaper/sfOutputEscaperGetterDecorator.class.php +++ b/lib/escaper/sfOutputEscaperGetterDecorator.class.php @@ -12,43 +12,42 @@ * 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..3712f626e 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..c063a4dbc 100644 --- a/lib/escaper/sfOutputEscaperObjectDecorator.class.php +++ b/lib/escaper/sfOutputEscaperObjectDecorator.class.php @@ -13,116 +13,111 @@ * 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(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. + * + * @param mixed $key + * + * @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(array($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..788c02574 100644 --- a/lib/escaper/sfOutputEscaperSafe.class.php +++ b/lib/escaper/sfOutputEscaperSafe.class.php @@ -11,68 +11,65 @@ /** * 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; - - /** - * Constructor. - * - * @param mixed $value The value to mark as safe - */ - public function __construct($value) - { - $this->value = $value; + protected $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(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..018b74cc5 100644 --- a/lib/event/sfEvent.class.php +++ b/lib/event/sfEvent.class.php @@ -11,156 +11,153 @@ /** * 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 = 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() { - throw new InvalidArgumentException(sprintf('The event "%s" has no "%s" parameter.', $this->name, $name)); + return $this->value; } - 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]); - } + /** + * 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; + } + + /** + * 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..8a00dda1a 100644 --- a/lib/event/sfEventDispatcher.class.php +++ b/lib/event/sfEventDispatcher.class.php @@ -13,145 +13,134 @@ * * @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 = 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) { - $this->listeners[$name] = array(); - } + if (!isset($this->listeners[$name])) { + $this->listeners[$name] = array(); + } - $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, array($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] = array(); + } + + 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 array(); + } - 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..fc6951883 100644 --- a/lib/exception/data/error.json.php +++ b/lib/exception/data/error.json.php @@ -1,5 +1,7 @@ - array( - 'code' => $code, - 'message' => $text, -))) ?> + array( + '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')); ?>