diff --git a/.docker/php53/Dockerfile b/.docker/php53/Dockerfile new file mode 100644 index 000000000..fa7261082 --- /dev/null +++ b/.docker/php53/Dockerfile @@ -0,0 +1,48 @@ +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 + +CMD ["php", "-a"] diff --git a/.docker/php54/Dockerfile b/.docker/php54/Dockerfile new file mode 100644 index 000000000..91baa8c85 --- /dev/null +++ b/.docker/php54/Dockerfile @@ -0,0 +1,5 @@ +FROM php:5.4-cli + +RUN docker-php-ext-install pdo +RUN docker-php-ext-install pdo_mysql +RUN docker-php-ext-install mbstring diff --git a/.docker/php55_71/Dockerfile b/.docker/php55_71/Dockerfile new file mode 100644 index 000000000..7c901b83a --- /dev/null +++ b/.docker/php55_71/Dockerfile @@ -0,0 +1,6 @@ +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 diff --git a/.docker/php72_73/Dockerfile b/.docker/php72_73/Dockerfile new file mode 100644 index 000000000..1cc2965f5 --- /dev/null +++ b/.docker/php72_73/Dockerfile @@ -0,0 +1,22 @@ +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 + +# 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_82/Dockerfile b/.docker/php74_82/Dockerfile new file mode 100644 index 000000000..7d13d7c82 --- /dev/null +++ b/.docker/php74_82/Dockerfile @@ -0,0 +1,34 @@ +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 + +# 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/.gitattributes b/.gitattributes index 884d89b58..bf85d2fd1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,8 @@ +/.docker export-ignore /.gitattributes export-ignore /.gitignore export-ignore -/.travis.yml export-ignore -/build.properties.dev export-ignore -/build.xml export-ignore +/.github export-ignore + +/docker-compose.yml /tests export-ignore /tools export-ignore diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 000000000..26b4f3b23 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,65 @@ +name: "Continuous Integration" + +on: + pull_request: + branches: + - master + paths: + - .github/workflows/continuous-integration.yml + - composer.* + - lib/** + - tests/** + + push: + branches: + - master + paths: + - .github/workflows/continuous-integration.yml + - composer.* + - lib/** + - tests/** + +env: + fail-fast: true + +jobs: + tests: + name: "Doctrine1 Tests" + runs-on: "ubuntu-latest" + + strategy: + matrix: + php-version: + - "7.4" + - "8.0" + - "8.1" + - "8.2" + - "8.3" + + 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: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --prefer-dist + + - name: Run Tests + run: cd tests && php run.php diff --git a/.gitignore b/.gitignore index 7cdc81d2a..4a2fca764 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ tests/DoctrineTest/doctrine_tests/* -*TestCase.php \ No newline at end of file +*TestCase.php +/composer.lock +/tests/tmp +/tests/foo.sq3 +/vendor/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1f4ceac7b..000000000 --- a/.travis.yml +++ /dev/null @@ -1,35 +0,0 @@ -os: linux -dist: xenial -language: php - -php: - - 7.0 - - 7.1 - - 7.2 - - 7.3 - - 7.4 - - nightly - -cache: - directories: - - $HOME/.composer/cache - -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 - -install: - - composer install --prefer-dist --no-progress --no-suggest -o - -script: - - php -dshort_open_tag=Off -dmagic_quotes_gpc=Off tests/index.php diff --git a/README.md b/README.md new file mode 100644 index 000000000..27f085e1b --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +Doctrine1 +========= + +About this version +------------------ + +This is a community driven fork of doctrine 1, as official support has been interrupted long time ago. + +**Do not use it for new projects: this version is great to improve existing symfony1 applications using doctrine1, but [Doctrine2](https://www.doctrine-project.org/projects/orm.html) is the way to go today.** + + +Requirements +------------ + +PHP 5.3 and up. + + +Installation +------------ + +Using [Composer](http://getcomposer.org/doc/00-intro.md) as dependency management: + + composer require friendsofsymfony1/doctrine1 "1.4.*" + composer install + + + +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? + + tests/bin/test + +### When you finish your work day, do not forget to clean up your desk + + docker-compose down + + +Documentation +------------- + +Read the official [doctrine1 documentation](https://web.archive.org/web/20171008235327/http://docs.doctrine-project.org:80/projects/doctrine1/en/latest/en/manual/index.html) + + +Contributing +------------ + +You can send pull requests or create an issue. diff --git a/build.properties.dev b/build.properties.dev deleted file mode 100644 index e7f708229..000000000 --- a/build.properties.dev +++ /dev/null @@ -1,11 +0,0 @@ -version=1.2.3 -stability=stable -build.dir=build -dist.dir=dist -report.dir=reports -log.archive.dir=logs -test.phpunit_configuration_file= -test.phpunit_generate_coverage=0 -test.pmd_reports=0 -test.pdepend_exec= -test.phpmd_exec= \ No newline at end of file diff --git a/build.xml b/build.xml deleted file mode 100644 index 5ff0aea54..000000000 --- a/build.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Doctrine - PHP5 Database ORM - pear.doctrine-project.org - -Doctrine is an ORM (object relational mapper) for PHP 5.2.x+ that sits on top of -a powerful DBAL (database abstraction layer). One of its key features is the -ability to optionally write database queries in an OO (object oriented) -SQL-dialect called DQL inspired by Hibernates HQL. This provides developers with -a powerful alternative to SQL that maintains a maximum of flexibility without -requiring needless code duplication. - - - LGPL - - - - - - - - - - - - - \ No newline at end of file diff --git a/composer.json b/composer.json index 2e29c2419..41a390007 100644 --- a/composer.json +++ b/composer.json @@ -20,9 +20,11 @@ } ], "require": { - "php": ">=5.3", + "php": "^7.4 || ^8.0", + "ext-iconv": "*", "ext-mbstring": "*", - "ext-pdo": "*" + "ext-pdo": "*", + "ext-zlib": "*" }, "support": { "issues": "https://github.com/FriendsOfSymfony1/doctrine1/issues", @@ -37,5 +39,8 @@ "branch-alias": { "dev-master": "1.4-dev" } + }, + "config": { + "sort-packages": true } } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..9c36afacc --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,145 @@ +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/tests + 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"' + } | tee -a /usr/local/lib/php.ini + + exec tail -f /dev/null + + php54: &services_php54 + build: + context: .docker/php54 + working_dir: /app/tests + 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"' + } | tee -a /usr/local/etc/php/php.ini + + exec tail -f /dev/null + depends_on: + - db + + php55: + <<: *services_php54 + build: + context: .docker/php55_71 + args: + PHP_TAG: '5.5-cli' + + php56: + <<: *services_php54 + build: + context: .docker/php55_71 + args: + PHP_TAG: '5.6-cli-jessie' + + php70: + <<: *services_php54 + build: + context: .docker/php55_71 + args: + PHP_TAG: '7.0-cli-jessie' + + php71: + <<: *services_php54 + build: + context: .docker/php55_71 + args: + PHP_TAG: '7.1-cli-jessie' + + php72: + <<: *services_php54 + build: + context: .docker/php72_73 + args: + PHP_VERSION: '7.2' + + php73: + <<: *services_php54 + build: + context: .docker/php72_73 + args: + PHP_VERSION: '7.3' + + php74: + <<: *services_php54 + build: + context: .docker/php74_82 + args: + PHP_VERSION: '7.4' + + php80: + <<: *services_php54 + build: + context: .docker/php74_82 + args: + PHP_VERSION: '8.0' + + php81: + <<: *services_php54 + build: + context: .docker/php74_82 + args: + PHP_VERSION: '8.1' + + php82: + <<: *services_php54 + build: + context: .docker/php74_82 + args: + PHP_VERSION: '8.2' + + 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 diff --git a/lib/Doctrine/Access.php b/lib/Doctrine/Access.php index 572ff7ff0..f066e7f4a 100644 --- a/lib/Doctrine/Access.php +++ b/lib/Doctrine/Access.php @@ -89,29 +89,25 @@ public function __isset($name) * @param string $name * @return void */ + #[\ReturnTypeWillChange] public function __unset($name) { return $this->remove($name); } /** - * Check if an offset axists - * - * @param mixed $offset - * @return boolean Whether or not this object contains $offset + * @return bool */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return $this->contains($offset); } /** - * An alias of get() - * - * @see get, __get - * @param mixed $offset * @return mixed */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { // array notation with no index was causing 'undefined variable: $offset' notices in php7, @@ -124,13 +120,9 @@ public function offsetGet($offset) } /** - * Sets $offset to $value - * - * @see set, __set - * @param mixed $offset - * @param mixed $value * @return void */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { if ( ! isset($offset)) { @@ -141,21 +133,19 @@ public function offsetSet($offset, $value) } /** - * Unset a given offset - * - * @see set, offsetSet, __set - * @param mixed $offset + * @return void */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { - return $this->remove($offset); + $this->remove($offset); } /** * Remove the element with the specified offset * * @param mixed $offset The offset to remove - * @return boolean True if removed otherwise false + * @return bool True if removed otherwise false */ public function remove($offset) { @@ -186,8 +176,8 @@ public function set($offset, $value) } /** - * Check if the specified offset exists - * + * Check if the specified offset exists + * * @param mixed $offset The offset to check * @return boolean True if exists otherwise false */ @@ -197,9 +187,9 @@ public function contains($offset) } /** - * Add the value - * - * @param mixed $value The value to add + * Add the value + * + * @param mixed $value The value to add * @return void */ public function add($value) diff --git a/lib/Doctrine/Adapter/Mock.php b/lib/Doctrine/Adapter/Mock.php index 61a987e91..fddce61df 100644 --- a/lib/Doctrine/Adapter/Mock.php +++ b/lib/Doctrine/Adapter/Mock.php @@ -238,6 +238,7 @@ public function lastInsertId() * * @return integer $count */ + #[\ReturnTypeWillChange] public function count() { return count($this->_queries); diff --git a/lib/Doctrine/Cli/AnsiColorFormatter.php b/lib/Doctrine/Cli/AnsiColorFormatter.php index b3d1aa444..cca3afb7d 100644 --- a/lib/Doctrine/Cli/AnsiColorFormatter.php +++ b/lib/Doctrine/Cli/AnsiColorFormatter.php @@ -115,7 +115,7 @@ public function formatSection($section, $text, $size = null) { $width = 9 + strlen($this->format('', 'INFO')); - return sprintf(">> %-${width}s %s", $this->format($section, 'INFO'), $this->excerpt($text, $size)); + return sprintf(">> %-{$width}s %s", $this->format($section, 'INFO'), $this->excerpt($text, $size)); } /** diff --git a/lib/Doctrine/Collection.php b/lib/Doctrine/Collection.php index 38b5d85e9..7b3c60104 100644 --- a/lib/Doctrine/Collection.php +++ b/lib/Doctrine/Collection.php @@ -142,13 +142,38 @@ public function setData(array $data) $this->data = $data; } + /** * This method is automatically called when this Doctrine_Collection is serialized * - * @return array + * @return string */ public function serialize() { + $vars = $this->__serialize(); + + return serialize($vars); + } + + /** + * This method is automatically called everytime a Doctrine_Collection object is unserialized + * + * @return void + */ + public function unserialize($serialized) + { + $array = unserialize($serialized); + + $this->__unserialize($array); + } + + /** + * Serializes the current instance for php 7.4+ + * + * @return array + */ + public function __serialize() { + $vars = get_object_vars($this); unset($vars['reference']); @@ -160,22 +185,21 @@ public function serialize() $vars['_table'] = $vars['_table']->getComponentName(); - return serialize($vars); + return $vars; } /** - * This method is automatically called everytime a Doctrine_Collection object is unserialized + * Unserializes a Doctrine_Collection instance for php 7.4+ * - * @return void + * @param string $serialized A serialized Doctrine_Collection instance */ - public function unserialize($serialized) + public function __unserialize($data) { $manager = Doctrine_Manager::getInstance(); $connection = $manager->getCurrentConnection(); - $array = unserialize($serialized); - foreach ($array as $name => $values) { + foreach ($data as $name => $values) { $this->$name = $values; } @@ -432,6 +456,7 @@ public function getKeys() * * @return integer */ + #[\ReturnTypeWillChange] public function count() { return count($this->data); @@ -786,12 +811,11 @@ public function toHierarchy() /** * Populate a Doctrine_Collection from an array of data * - * @param string $array + * @param array $array * @return void */ public function fromArray($array, $deep = true) { - $data = array(); foreach ($array as $rowKey => $row) { $this[$rowKey]->fromArray($row, $deep); } @@ -1036,6 +1060,7 @@ public function free($deep = false) * * @return Iterator */ + #[\ReturnTypeWillChange] public function getIterator() { $data = $this->data; diff --git a/lib/Doctrine/Collection/Iterator.php b/lib/Doctrine/Collection/Iterator.php index 3fdc79cd0..1c6dbe283 100644 --- a/lib/Doctrine/Collection/Iterator.php +++ b/lib/Doctrine/Collection/Iterator.php @@ -74,6 +74,7 @@ public function __construct($collection) * * @return void */ + #[\ReturnTypeWillChange] public function rewind() { $this->index = 0; @@ -88,6 +89,7 @@ public function rewind() * * @return integer */ + #[\ReturnTypeWillChange] public function key() { return $this->key; @@ -98,6 +100,7 @@ public function key() * * @return Doctrine_Record */ + #[\ReturnTypeWillChange] public function current() { return $this->collection->get($this->key); @@ -108,6 +111,7 @@ public function current() * * @return void */ + #[\ReturnTypeWillChange] public function next() { $this->index++; diff --git a/lib/Doctrine/Collection/Iterator/Expandable.php b/lib/Doctrine/Collection/Iterator/Expandable.php index 7c18c5c58..3bfab7dd5 100644 --- a/lib/Doctrine/Collection/Iterator/Expandable.php +++ b/lib/Doctrine/Collection/Iterator/Expandable.php @@ -32,6 +32,7 @@ */ class Doctrine_Collection_Iterator_Expandable extends Doctrine_Collection_Iterator { + #[\ReturnTypeWillChange] public function valid() { if ($this->index < $this->count) { diff --git a/lib/Doctrine/Collection/Iterator/Normal.php b/lib/Doctrine/Collection/Iterator/Normal.php index 540bdad63..c256bd6fb 100644 --- a/lib/Doctrine/Collection/Iterator/Normal.php +++ b/lib/Doctrine/Collection/Iterator/Normal.php @@ -35,6 +35,7 @@ class Doctrine_Collection_Iterator_Normal extends Doctrine_Collection_Iterator /** * @return boolean whether or not the iteration will continue */ + #[\ReturnTypeWillChange] public function valid() { return ($this->index < $this->count); diff --git a/lib/Doctrine/Collection/Iterator/Offset.php b/lib/Doctrine/Collection/Iterator/Offset.php index 181b73f21..128b1ef10 100644 --- a/lib/Doctrine/Collection/Iterator/Offset.php +++ b/lib/Doctrine/Collection/Iterator/Offset.php @@ -32,6 +32,7 @@ */ class Doctrine_Collection_Iterator_Offset extends Doctrine_Collection_Iterator { + #[\ReturnTypeWillChange] public function valid() { } } \ No newline at end of file diff --git a/lib/Doctrine/Collection/OnDemand.php b/lib/Doctrine/Collection/OnDemand.php index 92cddf3ba..ab2e81134 100644 --- a/lib/Doctrine/Collection/OnDemand.php +++ b/lib/Doctrine/Collection/OnDemand.php @@ -64,6 +64,7 @@ private function _hydrateCurrent() } } + #[\ReturnTypeWillChange] public function rewind() { $this->index = 0; @@ -73,16 +74,19 @@ public function rewind() $this->_hydrateCurrent(); } + #[\ReturnTypeWillChange] public function key() { return $this->index; } + #[\ReturnTypeWillChange] public function current() { return $this->_current; } + #[\ReturnTypeWillChange] public function next() { $this->_current = null; @@ -90,6 +94,7 @@ public function next() $this->_hydrateCurrent(); } + #[\ReturnTypeWillChange] public function valid() { if ( ! is_null($this->_current) && $this->_current !== false) { diff --git a/lib/Doctrine/Column.php b/lib/Doctrine/Column.php index 18e081c33..fafb97adb 100644 --- a/lib/Doctrine/Column.php +++ b/lib/Doctrine/Column.php @@ -146,6 +146,7 @@ public function enumIndex($field, $value) * * @return integer */ + #[\ReturnTypeWillChange] public function count() { return count($this->_definition); @@ -156,6 +157,7 @@ public function count() * * @return ArrayIterator */ + #[\ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->_definition); diff --git a/lib/Doctrine/Connection.php b/lib/Doctrine/Connection.php index a6703a221..73a7e5fa7 100644 --- a/lib/Doctrine/Connection.php +++ b/lib/Doctrine/Connection.php @@ -188,6 +188,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun */ protected $_tableCache; protected $_tableCacheTTL; + protected $exported; /** * the constructor @@ -1178,6 +1179,7 @@ public function getTables() * * @return ArrayIterator SPL ArrayIterator object */ + #[\ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->tables); @@ -1188,6 +1190,7 @@ public function getIterator() * * @return integer */ + #[\ReturnTypeWillChange] public function count() { return $this->_count; @@ -1606,6 +1609,7 @@ public function __toString() return Doctrine_Lib::getConnectionAsString($this); } + /** * Serialize. Remove database connection(pdo) since it cannot be serialized * @@ -1613,9 +1617,8 @@ public function __toString() */ public function serialize() { - $vars = get_object_vars($this); - $vars['dbh'] = null; - $vars['isConnected'] = false; + $vars = $this->__serialize(); + return serialize($vars); } @@ -1629,7 +1632,32 @@ public function unserialize($serialized) { $array = unserialize($serialized); - foreach ($array as $name => $values) { + $this->__unserialize($array); + } + + /** + * Serialize. Remove database connection(pdo) since it cannot be serialized for PHP 7.4+ + * + * @return array + */ + public function __serialize() + { + $vars = get_object_vars($this); + $vars['dbh'] = null; + $vars['isConnected'] = false; + + return $vars; + } + + /** + * Unserialize. Recreate connection from serialized content PHP 7.4+ + * + * @param array $data + * @return void + */ + public function __unserialize($data) + { + foreach ($data as $name => $values) { $this->$name = $values; } } diff --git a/lib/Doctrine/Connection/Common.php b/lib/Doctrine/Connection/Common.php index 1f1aa21b6..36f7e286c 100644 --- a/lib/Doctrine/Connection/Common.php +++ b/lib/Doctrine/Connection/Common.php @@ -38,12 +38,13 @@ class Doctrine_Connection_Common extends Doctrine_Connection * @param string $query * @param mixed $limit * @param mixed $offset + * @return string */ public function modifyLimitQuery($query, $limit = false,$offset = false,$isManip=false) { $limit = (int) $limit; $offset = (int) $offset; - + if ($limit && $offset) { $query .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; } elseif ($limit && ! $offset) { @@ -54,4 +55,4 @@ public function modifyLimitQuery($query, $limit = false,$offset = false,$isManip return $query; } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Connection/Mysql.php b/lib/Doctrine/Connection/Mysql.php index 9c9eb982b..7a7e59c16 100644 --- a/lib/Doctrine/Connection/Mysql.php +++ b/lib/Doctrine/Connection/Mysql.php @@ -85,6 +85,11 @@ public function __construct(Doctrine_Manager $manager, $adapter) $this->properties['varchar_max_length'] = 255; + // PHP8.1 require default to true to keep BC + // https://www.php.net/manual/en/migration81.incompatible.php#migration81.incompatible.pdo.mysql + // Can be overwritten by user later + $this->setAttribute(Doctrine_Core::ATTR_STRINGIFY_FETCHES, true); + parent::__construct($manager, $adapter); } diff --git a/lib/Doctrine/Connection/Profiler.php b/lib/Doctrine/Connection/Profiler.php index 3d3c6f8fa..4f1d7cd5c 100644 --- a/lib/Doctrine/Connection/Profiler.php +++ b/lib/Doctrine/Connection/Profiler.php @@ -68,8 +68,8 @@ public function __construct() { * @return boolean */ public function setFilterQueryType() { - - } + + } /** * method overloader * this method is used for invoking different listeners, for the full @@ -107,9 +107,9 @@ public function __call($m, $a) * get * * @param mixed $key - * @return Doctrine_Event + * @return Doctrine_Event|null */ - public function get($key) + public function get($key) { if (isset($this->events[$key])) { return $this->events[$key]; @@ -121,9 +121,9 @@ public function get($key) * getAll * returns all profiled events as an array * - * @return array all events in an array + * @return Doctrine_Event[] All events in an array */ - public function getAll() + public function getAll() { return $this->events; } @@ -134,6 +134,7 @@ public function getAll() * * @return ArrayIterator */ + #[\ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->events); @@ -141,10 +142,11 @@ public function getIterator() /** * count - * + * * @return integer */ - public function count() + #[\ReturnTypeWillChange] + public function count() { return count($this->events); } @@ -152,9 +154,9 @@ public function count() /** * pop the last event from the event stack * - * @return Doctrine_Event + * @return Doctrine_Event|null */ - public function pop() + public function pop() { $event = array_pop($this->events); if ($event !== null) diff --git a/lib/Doctrine/Connection/Sqlite.php b/lib/Doctrine/Connection/Sqlite.php index a94e2472d..6a29b654e 100644 --- a/lib/Doctrine/Connection/Sqlite.php +++ b/lib/Doctrine/Connection/Sqlite.php @@ -65,9 +65,15 @@ public function __construct(Doctrine_Manager $manager, $adapter) 'identifier_quoting' => true, 'pattern_escaping' => false, ); - parent::__construct($manager, $adapter); + parent::__construct($manager, $adapter); if ($this->isConnected) { + + // PHP8.1 require default to true to keep BC + // https://www.php.net/manual/en/migration81.incompatible.php#migration81.incompatible.pdo.sqlite + // Can be overwritten by user later + $this->dbh->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + $this->dbh->sqliteCreateFunction('mod', array('Doctrine_Expression_Sqlite', 'modImpl'), 2); $this->dbh->sqliteCreateFunction('concat', array('Doctrine_Expression_Sqlite', 'concatImpl')); $this->dbh->sqliteCreateFunction('md5', 'md5', 1); @@ -79,20 +85,32 @@ public function __construct(Doctrine_Manager $manager, $adapter) * initializes database functions missing in sqlite * * @see Doctrine_Expression - * @return void + * @return boolean */ public function connect() { if ($this->isConnected) { - return false; + return; } - parent::connect(); + // If customer configure it + $hasConfigureStringify = (isset($this->pendingAttributes[Doctrine_Core::ATTR_STRINGIFY_FETCHES])); + + $connected = parent::connect(); + + if(!$hasConfigureStringify) { + // PHP8.1 require default to true to keep BC + // https://www.php.net/manual/en/migration81.incompatible.php#migration81.incompatible.pdo.sqlite + // Can be overwritten by user later + $this->dbh->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + } $this->dbh->sqliteCreateFunction('mod', array('Doctrine_Expression_Sqlite', 'modImpl'), 2); $this->dbh->sqliteCreateFunction('concat', array('Doctrine_Expression_Sqlite', 'concatImpl')); $this->dbh->sqliteCreateFunction('md5', 'md5', 1); $this->dbh->sqliteCreateFunction('now', array('Doctrine_Expression_Sqlite', 'nowImpl'), 0); + + return $connected; } /** diff --git a/lib/Doctrine/Connection/Statement.php b/lib/Doctrine/Connection/Statement.php index 7ad3215ad..4c0e86fac 100644 --- a/lib/Doctrine/Connection/Statement.php +++ b/lib/Doctrine/Connection/Statement.php @@ -321,6 +321,11 @@ public function fetch($fetchMode = Doctrine_Core::FETCH_BOTH, { $event = new Doctrine_Event($this, Doctrine_Event::STMT_FETCH, $this->getQuery()); + // null value is not an integer + if(null === $cursorOffset) { + $cursorOffset = 0; + } + $event->fetchMode = $fetchMode; $event->cursorOrientation = $cursorOrientation; $event->cursorOffset = $cursorOffset; diff --git a/lib/Doctrine/Core.php b/lib/Doctrine/Core.php index 382bf9510..8662d3284 100644 --- a/lib/Doctrine/Core.php +++ b/lib/Doctrine/Core.php @@ -564,7 +564,7 @@ public static function setPath($path) public static function getPath() { if ( ! self::$_path) { - self::$_path = realpath(dirname(__FILE__) . '/..'); + self::$_path = dirname(__DIR__); } return self::$_path; @@ -1132,7 +1132,7 @@ public static function compile($target = null, $includedDrivers = array()) public static function autoload($className) { if (strpos($className, 'sfYaml') === 0) { - require dirname(__FILE__) . '/Parser/sfYaml/' . $className . '.php'; + require __DIR__ . '/Parser/sfYaml/' . $className . '.php'; return true; } diff --git a/lib/Doctrine/Export/Reporter.php b/lib/Doctrine/Export/Reporter.php index fb3c43a96..742f39fac 100644 --- a/lib/Doctrine/Export/Reporter.php +++ b/lib/Doctrine/Export/Reporter.php @@ -44,6 +44,7 @@ public function pop() return array_pop($this->messages); } + #[\ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->messages); diff --git a/lib/Doctrine/Formatter.php b/lib/Doctrine/Formatter.php index 99aec1dbe..d942b73b8 100644 --- a/lib/Doctrine/Formatter.php +++ b/lib/Doctrine/Formatter.php @@ -270,6 +270,6 @@ public function getForeignKeyName($fkey) public function getTableName($table) { $format = $this->conn->getAttribute(Doctrine_Core::ATTR_TBLNAME_FORMAT); - return sprintf($format, str_replace(sprintf($format, null), null, $table)); + return sprintf($format, str_replace(sprintf($format, null), '', $table)); } } diff --git a/lib/Doctrine/Hydrator.php b/lib/Doctrine/Hydrator.php index 05ab94599..129743e32 100644 --- a/lib/Doctrine/Hydrator.php +++ b/lib/Doctrine/Hydrator.php @@ -51,7 +51,7 @@ public function __construct() /** * Set the hydration mode * - * @param mixed $hydrationMode One of the Doctrine_Core::HYDRATE_* constants or + * @param mixed $hydrationMode One of the Doctrine_Core::HYDRATE_* constants or * a string representing the name of the hydration mode or * or an instance of the hydration class */ @@ -112,9 +112,9 @@ public function getHydratorDriverClassName($mode = null) /** * Get an instance of the hydration driver for the passed hydration mode * - * @param string $mode - * @param array $tableAliases - * @return object Doctrine_Hydrator_Abstract + * @param string $mode + * @param array $tableAliases + * @return Doctrine_Hydrator_Abstract */ public function getHydratorDriver($mode, $tableAliases) { @@ -138,8 +138,8 @@ public function getHydratorDriver($mode, $tableAliases) * Hydrate the query statement in to its final data structure by one of the * hydration drivers. * - * @param object $stmt - * @param array $tableAliases + * @param object $stmt + * @param array $tableAliases * @return mixed $result */ public function hydrateResultSet($stmt, $tableAliases) @@ -149,4 +149,4 @@ public function hydrateResultSet($stmt, $tableAliases) return $result; } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Hydrator/Abstract.php b/lib/Doctrine/Hydrator/Abstract.php index a603e5fd7..3a4dc7dc4 100644 --- a/lib/Doctrine/Hydrator/Abstract.php +++ b/lib/Doctrine/Hydrator/Abstract.php @@ -97,11 +97,11 @@ public function onDemandReset() * (I.e. ORACLE limit/offset emulation adds doctrine_rownum to the result set). * * @param string $name - * @return boolean + * @return bool */ protected function _isIgnoredName($name) { - return $name == 'DOCTRINE_ROWNUM'; + return $name === 'DOCTRINE_ROWNUM'; } /** @@ -114,8 +114,7 @@ protected function _isIgnoredName($name) * The key idea is the loop over the rowset only once doing all the needed operations * within this massive loop. * - * @param mixed $stmt * @return mixed */ abstract public function hydrateResultSet($stmt); -} \ No newline at end of file +} diff --git a/lib/Doctrine/Hydrator/ArrayHierarchyDriver.php b/lib/Doctrine/Hydrator/ArrayHierarchyDriver.php index ae281eb47..731ad0090 100644 --- a/lib/Doctrine/Hydrator/ArrayHierarchyDriver.php +++ b/lib/Doctrine/Hydrator/ArrayHierarchyDriver.php @@ -32,6 +32,9 @@ */ class Doctrine_Hydrator_ArrayHierarchyDriver extends Doctrine_Hydrator_ArrayDriver { + /** + * @return array + */ public function hydrateResultSet($stmt) { $collection = parent::hydrateResultSet($stmt); @@ -80,4 +83,4 @@ public function hydrateResultSet($stmt) } return $trees; } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Hydrator/ArrayShallowDriver.php b/lib/Doctrine/Hydrator/ArrayShallowDriver.php index cad4a3424..b595122b6 100644 --- a/lib/Doctrine/Hydrator/ArrayShallowDriver.php +++ b/lib/Doctrine/Hydrator/ArrayShallowDriver.php @@ -32,6 +32,9 @@ */ class Doctrine_Hydrator_ArrayShallowDriver extends Doctrine_Hydrator_ScalarDriver { + /** + * @return array + */ public function hydrateResultSet($stmt) { $cache = array(); @@ -41,4 +44,4 @@ public function hydrateResultSet($stmt) } return $result; } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Hydrator/Graph.php b/lib/Doctrine/Hydrator/Graph.php index 3c4b845e7..b227f3874 100644 --- a/lib/Doctrine/Hydrator/Graph.php +++ b/lib/Doctrine/Hydrator/Graph.php @@ -35,7 +35,9 @@ */ abstract class Doctrine_Hydrator_Graph extends Doctrine_Hydrator_Abstract { - protected $_tables = array(); + protected + $_tables = array(), + $_rootAlias = null; /** * Gets the custom field used for indexing for the specified component alias. @@ -48,6 +50,9 @@ protected function _getCustomIndexField($alias) return isset($this->_queryComponents[$alias]['map']) ? $this->_queryComponents[$alias]['map'] : null; } + /** + * @return Doctrine_Collection|mixed + */ public function hydrateResultSet($stmt) { // Used variables during hydration @@ -121,7 +126,9 @@ public function hydrateResultSet($stmt) $table = $this->_queryComponents[$rootAlias]['table']; if ($table->getConnection()->getAttribute(Doctrine_Core::ATTR_PORTABILITY) & Doctrine_Core::PORTABILITY_RTRIM) { - array_map('rtrim', $data); + foreach($data as $key => $foo) { + $data[$key] = (is_string($foo)) ? rtrim($foo) : $foo; + } } $id = $idTemplate; // initialize the id-memory @@ -304,11 +311,17 @@ protected function _gatherRowData(&$data, &$cache, &$id, &$nonemptyComponents) $table = $this->_queryComponents[$cache[$key]['dqlAlias']]['table']; $fieldName = $table->getFieldName($last); $cache[$key]['fieldName'] = $fieldName; + + if (isset($this->_queryComponents[$cache[$key]['dqlAlias']]['agg_field'][$last])) { + $fieldName = $this->_queryComponents[$cache[$key]['dqlAlias']]['agg_field'][$last]; + } + if ($table->isIdentifier($fieldName)) { $cache[$key]['isIdentifier'] = true; } else { $cache[$key]['isIdentifier'] = false; } + $type = $table->getTypeOfColumn($last); if ($type == 'integer' || $type == 'string') { $cache[$key]['isSimpleType'] = true; diff --git a/lib/Doctrine/Hydrator/NoneDriver.php b/lib/Doctrine/Hydrator/NoneDriver.php index d4ed09dd7..6da15a6d6 100644 --- a/lib/Doctrine/Hydrator/NoneDriver.php +++ b/lib/Doctrine/Hydrator/NoneDriver.php @@ -33,8 +33,11 @@ */ class Doctrine_Hydrator_NoneDriver extends Doctrine_Hydrator_Abstract { + /** + * @return mixed + */ public function hydrateResultSet($stmt) { return $stmt->fetchAll(PDO::FETCH_NUM); } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Hydrator/RecordDriver.php b/lib/Doctrine/Hydrator/RecordDriver.php index b4944428b..a028645d4 100644 --- a/lib/Doctrine/Hydrator/RecordDriver.php +++ b/lib/Doctrine/Hydrator/RecordDriver.php @@ -118,7 +118,7 @@ public function flush() $coll->takeSnapshot(); } $this->_initializedRelations = null; - $this->_collections = null; + $this->_collections = array(); $this->_tables = null; } } \ No newline at end of file diff --git a/lib/Doctrine/Hydrator/RecordHierarchyDriver.php b/lib/Doctrine/Hydrator/RecordHierarchyDriver.php index f32055d0f..28c54e20e 100644 --- a/lib/Doctrine/Hydrator/RecordHierarchyDriver.php +++ b/lib/Doctrine/Hydrator/RecordHierarchyDriver.php @@ -32,8 +32,11 @@ */ class Doctrine_Hydrator_RecordHierarchyDriver extends Doctrine_Hydrator_RecordDriver { + /** + * @return Doctrine_Collection + */ public function hydrateResultSet($stmt) { return parent::hydrateResultSet($stmt)->toHierarchy(); } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Hydrator/ScalarDriver.php b/lib/Doctrine/Hydrator/ScalarDriver.php index 894ff3f50..d3ce87e66 100644 --- a/lib/Doctrine/Hydrator/ScalarDriver.php +++ b/lib/Doctrine/Hydrator/ScalarDriver.php @@ -32,6 +32,9 @@ */ class Doctrine_Hydrator_ScalarDriver extends Doctrine_Hydrator_Abstract { + /** + * @return array + */ public function hydrateResultSet($stmt) { $cache = array(); @@ -55,7 +58,7 @@ protected function _gatherRowData($data, &$cache, $aliasPrefix = true) } // cache general information like the column name <-> field name mapping $e = explode('__', $key); - $columnName = strtolower(array_pop($e)); + $columnName = strtolower(array_pop($e)); $cache[$key]['dqlAlias'] = $this->_tableAliases[strtolower(implode('__', $e))]; $table = $this->_queryComponents[$cache[$key]['dqlAlias']]['table']; // check whether it's an aggregate value or a regular field @@ -84,7 +87,7 @@ protected function _gatherRowData($data, &$cache, $aliasPrefix = true) $fieldName = $cache[$key]['fieldName']; $rowDataKey = $aliasPrefix ? $dqlAlias . '_' . $fieldName:$fieldName; - + if ($cache[$key]['isSimpleType'] || $cache[$key]['isAgg']) { $rowData[$rowDataKey] = $value; } else { @@ -94,4 +97,4 @@ protected function _gatherRowData($data, &$cache, $aliasPrefix = true) } return $rowData; } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Hydrator/SingleScalarDriver.php b/lib/Doctrine/Hydrator/SingleScalarDriver.php index ebcad6230..bf7589522 100644 --- a/lib/Doctrine/Hydrator/SingleScalarDriver.php +++ b/lib/Doctrine/Hydrator/SingleScalarDriver.php @@ -32,6 +32,10 @@ */ class Doctrine_Hydrator_SingleScalarDriver extends Doctrine_Hydrator_Abstract { + /** + * @param mixed $stmt + * @return array|mixed + */ public function hydrateResultSet($stmt) { $result = array(); @@ -44,4 +48,4 @@ public function hydrateResultSet($stmt) return $result; } } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Import/Builder.php b/lib/Doctrine/Import/Builder.php index 82195340d..8f1bc34da 100644 --- a/lib/Doctrine/Import/Builder.php +++ b/lib/Doctrine/Import/Builder.php @@ -36,6 +36,7 @@ * @author Nicolas Bérard-Nault * @author Jonathan H. Wage */ +#[\AllowDynamicProperties] class Doctrine_Import_Builder extends Doctrine_Builder { /** @@ -178,6 +179,25 @@ class Doctrine_Import_Builder extends Doctrine_Builder */ protected $_phpDocEmail = '##EMAIL##'; + + /** + * Contains the actAs columns after running buildSetUp + * + * @var array + */ + private $actAsColumns = array(); + /** * _tpl * @@ -395,9 +415,7 @@ public function buildTableDefinition(array $definition) /** * buildSetUp * - * @param array $options - * @param array $columns - * @param array $relations + * @param array $definition * @return string */ public function buildSetUp(array $definition) @@ -782,7 +800,7 @@ public function buildPhpDocs(array $definition) if (isset($definition['relations']) && ! empty($definition['relations'])) { foreach ($definition['relations'] as $relation) { $type = (isset($relation['type']) && $relation['type'] == Doctrine_Relation::MANY) ? 'Doctrine_Collection' : $this->_classPrefix . $relation['class']; - if ($relation["type"] == Doctrine_Relation::ONE) { + if ((isset($relation['type']) ? $relation['type'] : null) == Doctrine_Relation::ONE) { $properties[] = array($relation['class'], $relation['alias'], ""); $getters[] = array($relation['class'], $relation['alias'], ""); $setters[] = array($definition['topLevelClassName'], $relation['alias'], $relation['class'], ""); @@ -856,21 +874,33 @@ public function buildPhpDocs(array $definition) return $ret; } + /** + * find class matching $name + * + * @param $name + * @return class-string + */ + private function findTemplateClassMatchingName($name) + { + $classname = $name; + if (class_exists("Doctrine_Template_$name", true)) { + $classname = "Doctrine_Template_$name"; + } + + return $classname; + } + /** * emit a behavior assign * * @param int $level * @param string $name * @param string $option + * @param class-string $classname * @return string assignation code */ - private function emitAssign($level, $name, $option) + private function emitAssign($level, $name, $option, $classname) { - // find class matching $name - $classname = $name; - if (class_exists("Doctrine_Template_$name", true)) { - $classname = "Doctrine_Template_$name"; - } return " \$" . strtolower($name) . "$level = new $classname($option);". PHP_EOL; } @@ -923,7 +953,7 @@ public function buildActAs($actAs) * @param array $emittedActAs contains on output an array of actAs command to be appended to output * @return string actAs full definition */ - private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emittedActAs) + private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emittedActAs = array()) { // rewrite special case of actAs: [Behavior] which gave [0] => Behavior if (is_array($actAs) && isset($actAs[0]) && !is_array($actAs[0])) { @@ -942,6 +972,7 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi $currentParent = $parent; if (is_array($actAs)) { foreach($actAs as $template => $options) { + $className = $this->findTemplateClassMatchingName($template); if ($template == 'actAs') { // found another actAs $build .= $this->innerBuildActAs($options, $level + 1, $parent, $emittedActAs); @@ -958,7 +989,8 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi } $optionPHP = $this->varExport($realOptions); - $build .= $this->emitAssign($level, $template, $optionPHP); + $build .= $this->emitAssign($level, $template, $optionPHP, $className); + $this->determineActAsColumns($className, $realOptions); if ($level == 0) { $emittedActAs[] = $this->emitActAs($level, $template); } else { @@ -968,7 +1000,8 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi $parent = $template; $build .= $this->innerBuildActAs($leftActAs, $level, $template, $emittedActAs); } else { - $build .= $this->emitAssign($level, $template, null); + $build .= $this->emitAssign($level, $template, null, $className); + $this->determineActAsColumns($className, array($options)); if ($level == 0) { $emittedActAs[] = $this->emitActAs($level, $template); } else { @@ -978,7 +1011,9 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi } } } else { - $build .= $this->emitAssign($level, $actAs, null); + $className = $this->findTemplateClassMatchingName($actAs); + $build .= $this->emitAssign($level, $actAs, null, $className); + $this->determineActAsColumns($className, array()); if ($level == 0) { $emittedActAs[] = $this->emitActAs($level, $actAs); } else { @@ -989,6 +1024,87 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi return $build; } + /** + * Adds the columns of the used actAs behaviors to the comment block. + * + * @param class-string $className + * @param array $instanceOptions + * + * @throws Doctrine_Import_Builder_Exception + */ + private function determineActAsColumns($className, $instanceOptions) + { + // No class specified or class does not exist. + if (!$className || !class_exists($className)) { + return; + } + + // PHP >= 7.4 is planned as a minimum version for the upcoming release of doctrine1, + // therefore we simply skip the generation of actAs columns if run below 7.0, as + // instantiation exceptions are not supported before PHP 7 + if (PHP_VERSION_ID <= 70000) { + return; + } + + try { + $actAsInstance = new $className($instanceOptions); + } catch (Error $e) { + // The class can't be instantiated, skipping it + return; + } + + if (!$actAsInstance || !method_exists($actAsInstance, 'getOptions')) { + return; + } + + $options = $actAsInstance->getOptions(); + + // Some behaviors do not contain an array of columns, e.g. SoftDelete. + if (!is_array(reset($options))) { + $options = array($options); + } + + foreach ($options as $name => $column) { + if (!is_array($column) || !array_key_exists('name', $column) || !array_key_exists('type', $column)) { + // 'name' or 'type' not found. + continue; + } + + if (array_key_exists('disabled', $column) && $column['disabled']) { + // Column has been disabled. + continue; + } + + // Add field, if it does not exist already. + if (array_key_exists($name, $this->actAsColumns)) { + continue; + } + + $this->actAsColumns[$name] = $column; + } + } + + private function mergeDefinitionAndActAsColumns(array $definitionColumns, array $actAsColumns) + { + $result = $definitionColumns; + + foreach ($actAsColumns as $actAsOptionName => $actAsColumn) { + $actAsColumnName = isset($actAsColumn['name']) ? $actAsColumn['name'] : $actAsOptionName; + + foreach ($result as $optionName => $column) { + $name = isset($column['name']) ? $column['name'] : $optionName; + if ($name === $actAsColumnName) { + continue 2; + } + } + + $result[$actAsOptionName] = $actAsColumn; + } + + return $result; + } + + /** * Build php code for adding record listeners * @@ -1121,6 +1237,8 @@ public function buildDefinition(array $definition) $className = $definition['className']; $extends = isset($definition['inheritance']['extends']) ? $definition['inheritance']['extends']:$this->_baseClassName; + // Clear actAsColumns + $this->actAsColumns = array(); if ( ! (isset($definition['no_definition']) && $definition['no_definition'] === true)) { $tableDefinitionCode = $this->buildTableDefinition($definition); $setUpCode = $this->buildSetUp($definition); @@ -1135,6 +1253,7 @@ public function buildDefinition(array $definition) $setUpCode.= $this->buildToString($definition); + $definition['columns'] = $this->mergeDefinitionAndActAsColumns($definition['columns'], $this->actAsColumns); $docs = PHP_EOL . $this->buildPhpDocs($definition); $content = sprintf(self::$_tpl, $docs, $abstract, diff --git a/lib/Doctrine/Locator.php b/lib/Doctrine/Locator.php index 70d1998d6..8b4d2817f 100644 --- a/lib/Doctrine/Locator.php +++ b/lib/Doctrine/Locator.php @@ -178,6 +178,7 @@ public function locate($name) * @see Countable interface * @return integer the number of resources */ + #[\ReturnTypeWillChange] public function count() { return count($this->_resources); @@ -191,6 +192,7 @@ public function count() * @return ArrayIterator an iterator for iterating through * all bound resources */ + #[\ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->_resources); diff --git a/lib/Doctrine/Locator/Injectable.php b/lib/Doctrine/Locator/Injectable.php index 884042dcd..b32ccf404 100644 --- a/lib/Doctrine/Locator/Injectable.php +++ b/lib/Doctrine/Locator/Injectable.php @@ -66,7 +66,7 @@ public function setLocator(Doctrine_Locator $locator) /** * getLocator * returns the locator associated with this object - * + * * if there are no locator locally associated then * this method tries to fetch the current global locator * @@ -101,7 +101,7 @@ public function locate($name) } else { // get the name of the concrete implementation $concreteImpl = $this->_resources[$name]; - + return $this->getLocator()->locate($concreteImpl); } } else { @@ -115,13 +115,13 @@ public function locate($name) * * @param string $name the name of the resource to bind * @param mixed $value the value of the resource - * @return Doctrine_Locator this object + * @return static this object */ - public function bind($name, $resource) + public function bind($name, $value) { - $this->_resources[$name] = $resource; - - return $this; + $this->_resources[$name] = $value; + + return $this; } /** @@ -146,4 +146,4 @@ public static function getNullObject() { return self::$_null; } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Manager.php b/lib/Doctrine/Manager.php index 957c51478..a2b08944d 100644 --- a/lib/Doctrine/Manager.php +++ b/lib/Doctrine/Manager.php @@ -411,6 +411,10 @@ protected function _buildDsnPartsArray($dsn) // silence any warnings $parts = @parse_url($dsn); + if ($parts === false) { + $parts = array(); + } + $names = array('dsn', 'scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment'); foreach ($names as $name) { @@ -638,6 +642,7 @@ public function contains($key) * * @return integer */ + #[\ReturnTypeWillChange] public function count() { return count($this->_connections); @@ -648,6 +653,7 @@ public function count() * * @return ArrayIterator */ + #[\ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->_connections); diff --git a/lib/Doctrine/Migration/Builder.php b/lib/Doctrine/Migration/Builder.php index ff3fc6155..e6ed9042a 100644 --- a/lib/Doctrine/Migration/Builder.php +++ b/lib/Doctrine/Migration/Builder.php @@ -75,7 +75,7 @@ public function __construct($migrationsPath = null) if ($migrationsPath instanceof Doctrine_Migration) { $this->setMigrationsPath($migrationsPath->getMigrationClassesDirectory()); $this->migration = $migrationsPath; - } else if (is_dir($migrationsPath)) { + } else if (is_dir((string) $migrationsPath)) { $this->setMigrationsPath($migrationsPath); $this->migration = new Doctrine_Migration($migrationsPath); } diff --git a/lib/Doctrine/Migration/Diff.php b/lib/Doctrine/Migration/Diff.php index 2b3b621a3..4891f7c07 100644 --- a/lib/Doctrine/Migration/Diff.php +++ b/lib/Doctrine/Migration/Diff.php @@ -330,7 +330,7 @@ protected function _cleanModelInformation($info) Doctrine_Inflector::tableize(self::$_toPrefix), Doctrine_Inflector::tableize(self::$_fromPrefix) ); - return str_replace($find, null, $info); + return str_replace($find, '', (string) $info); } } diff --git a/lib/Doctrine/Node.php b/lib/Doctrine/Node.php index 8b0145ea3..0d0e7c296 100644 --- a/lib/Doctrine/Node.php +++ b/lib/Doctrine/Node.php @@ -160,6 +160,7 @@ public function traverse($type = 'Pre', $options = array()) * @param string $type type of iterator (Pre | Post | Level) * @param array $options options */ + #[\ReturnTypeWillChange] public function getIterator($type = null, $options = null) { if ($type === null) { diff --git a/lib/Doctrine/Node/MaterializedPath/LevelOrderIterator.php b/lib/Doctrine/Node/MaterializedPath/LevelOrderIterator.php index 6283563c3..718a85c0d 100644 --- a/lib/Doctrine/Node/MaterializedPath/LevelOrderIterator.php +++ b/lib/Doctrine/Node/MaterializedPath/LevelOrderIterator.php @@ -41,26 +41,31 @@ public function __construct($node, $opts) throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function rewind() { throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function valid() { throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function current() { throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function key() { throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function next() { throw new Doctrine_Exception('Not yet implemented'); diff --git a/lib/Doctrine/Node/MaterializedPath/PostOrderIterator.php b/lib/Doctrine/Node/MaterializedPath/PostOrderIterator.php index 1cc002f06..be67e3678 100644 --- a/lib/Doctrine/Node/MaterializedPath/PostOrderIterator.php +++ b/lib/Doctrine/Node/MaterializedPath/PostOrderIterator.php @@ -41,26 +41,31 @@ public function __construct($node, $opts) throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function rewind() { throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function valid() { throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function current() { throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function key() { throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function next() { throw new Doctrine_Exception('Not yet implemented'); diff --git a/lib/Doctrine/Node/MaterializedPath/PreOrderIterator.php b/lib/Doctrine/Node/MaterializedPath/PreOrderIterator.php index 4ea31bd8c..d00438fec 100644 --- a/lib/Doctrine/Node/MaterializedPath/PreOrderIterator.php +++ b/lib/Doctrine/Node/MaterializedPath/PreOrderIterator.php @@ -41,26 +41,31 @@ public function __construct($node, $opts) throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function rewind() { throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function valid() { throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function current() { throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function key() { throw new Doctrine_Exception('Not yet implemented'); } + #[\ReturnTypeWillChange] public function next() { throw new Doctrine_Exception('Not yet implemented'); diff --git a/lib/Doctrine/Node/NestedSet/PreOrderIterator.php b/lib/Doctrine/Node/NestedSet/PreOrderIterator.php index a35a72223..9cc399d7d 100644 --- a/lib/Doctrine/Node/NestedSet/PreOrderIterator.php +++ b/lib/Doctrine/Node/NestedSet/PreOrderIterator.php @@ -100,6 +100,7 @@ public function __construct($record, $opts) * * @return void */ + #[\ReturnTypeWillChange] public function rewind() { $this->index = -1; @@ -111,6 +112,7 @@ public function rewind() * * @return integer */ + #[\ReturnTypeWillChange] public function key() { return $this->key; @@ -121,6 +123,7 @@ public function key() * * @return Doctrine_Record */ + #[\ReturnTypeWillChange] public function current() { $record = $this->collection->get($this->key); @@ -133,6 +136,7 @@ public function current() * * @return void */ + #[\ReturnTypeWillChange] public function next() { while ($current = $this->advanceIndex()) { @@ -149,6 +153,7 @@ public function next() /** * @return boolean whether or not the iteration will continue */ + #[\ReturnTypeWillChange] public function valid() { return ($this->index < $this->count); diff --git a/lib/Doctrine/Parser/Xml.php b/lib/Doctrine/Parser/Xml.php index a091580be..0f99699eb 100644 --- a/lib/Doctrine/Parser/Xml.php +++ b/lib/Doctrine/Parser/Xml.php @@ -86,7 +86,7 @@ public static function arrayToXml($array, $rootNodeName = 'data', $xml = null, $ if (strcasecmp($charset, 'utf-8') !== 0 && strcasecmp($charset, 'utf8') !== 0) { $value = iconv($charset, 'UTF-8', $value); } - $value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); + $value = htmlspecialchars((string) $value, ENT_COMPAT, 'UTF-8'); $xml->addChild($key, $value); } } diff --git a/lib/Doctrine/Parser/sfYaml/sfYaml.php b/lib/Doctrine/Parser/sfYaml/sfYaml.php index 1d89ccc97..7e0c14f3f 100644 --- a/lib/Doctrine/Parser/sfYaml/sfYaml.php +++ b/lib/Doctrine/Parser/sfYaml/sfYaml.php @@ -87,7 +87,7 @@ public static function load($input) return $input; } - require_once dirname(__FILE__).'/sfYamlParser.php'; + require_once __DIR__.'/sfYamlParser.php'; $yaml = new sfYamlParser(); @@ -116,7 +116,7 @@ public static function load($input) */ public static function dump($array, $inline = 2) { - require_once dirname(__FILE__).'/sfYamlDumper.php'; + require_once __DIR__.'/sfYamlDumper.php'; $yaml = new sfYamlDumper(); diff --git a/lib/Doctrine/Parser/sfYaml/sfYamlDumper.php b/lib/Doctrine/Parser/sfYaml/sfYamlDumper.php index 0ada2b37d..4ed3c8fbc 100644 --- a/lib/Doctrine/Parser/sfYaml/sfYamlDumper.php +++ b/lib/Doctrine/Parser/sfYaml/sfYamlDumper.php @@ -8,7 +8,7 @@ * file that was distributed with this source code. */ -require_once(dirname(__FILE__).'/sfYamlInline.php'); +require_once(__DIR__.'/sfYamlInline.php'); /** * sfYamlDumper dumps PHP variables to YAML strings. diff --git a/lib/Doctrine/Parser/sfYaml/sfYamlInline.php b/lib/Doctrine/Parser/sfYaml/sfYamlInline.php index 0aff5d375..5f4f31168 100644 --- a/lib/Doctrine/Parser/sfYaml/sfYamlInline.php +++ b/lib/Doctrine/Parser/sfYaml/sfYamlInline.php @@ -8,7 +8,7 @@ * file that was distributed with this source code. */ -require_once dirname(__FILE__).'/sfYaml.php'; +require_once __DIR__.'/sfYaml.php'; /** * sfYamlInline implements a YAML parser/dumper for the YAML inline syntax. @@ -98,9 +98,9 @@ static public function dump($value) return 'true'; case false === $value: return 'false'; - case ctype_digit($value): - return is_string($value) ? "'$value'" : (int) $value; - case is_numeric($value): + case (is_string($value) && ctype_digit($value)): + return "'$value'"; + case is_numeric($value) && false === strpbrk($value, "\f\n\r\t\v"): return is_infinite($value) ? str_ireplace('INF', '.Inf', strval($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)); diff --git a/lib/Doctrine/Parser/sfYaml/sfYamlParser.php b/lib/Doctrine/Parser/sfYaml/sfYamlParser.php index 91da2dcb1..f8bdb34d7 100644 --- a/lib/Doctrine/Parser/sfYaml/sfYamlParser.php +++ b/lib/Doctrine/Parser/sfYaml/sfYamlParser.php @@ -8,7 +8,7 @@ * file that was distributed with this source code. */ -require_once(dirname(__FILE__).'/sfYamlInline.php'); +require_once(__DIR__.'/sfYamlInline.php'); if (!defined('PREG_BAD_UTF8_OFFSET_ERROR')) { diff --git a/lib/Doctrine/Query.php b/lib/Doctrine/Query.php index 461f6937b..a4d0b40f8 100644 --- a/lib/Doctrine/Query.php +++ b/lib/Doctrine/Query.php @@ -160,11 +160,6 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable */ protected $_parsers = array(); - /** - * @var array $_pendingJoinConditions an array containing pending joins - */ - protected $_pendingJoinConditions = array(); - /** * @var array */ @@ -485,7 +480,7 @@ public function processPendingFields($componentAlias) } $sql = array(); - foreach ($fields as $fieldAlias => $fieldName) { + foreach ($fields as $fieldName) { $columnName = $table->getColumnName($fieldName); if (($owner = $table->getColumnOwner($columnName)) !== null && $owner !== $table->getComponentName()) { @@ -497,17 +492,10 @@ public function processPendingFields($componentAlias) . ' AS ' . $this->_conn->quoteIdentifier($tableAlias . '__' . $columnName); } else { - // Fix for http://www.doctrine-project.org/jira/browse/DC-585 - // Take the field alias if available - if (isset($this->_aggregateAliasMap[$fieldAlias])) { - $aliasSql = $this->_aggregateAliasMap[$fieldAlias]; - } else { - $columnName = $table->getColumnName($fieldName); - $aliasSql = $this->_conn->quoteIdentifier($tableAlias . '__' . $columnName); - } + $columnName = $table->getColumnName($fieldName); $sql[] = $this->_conn->quoteIdentifier($tableAlias) . '.' . $this->_conn->quoteIdentifier($columnName) . ' AS ' - . $aliasSql; + . $this->_conn->quoteIdentifier($tableAlias . '__' . $columnName); } } @@ -660,14 +648,11 @@ public function parseSelect($dql) $this->_queryComponents[$componentAlias]['agg'][$index] = $alias; - $this->_neededTables[] = $tableAlias; - - // Fix for http://www.doctrine-project.org/jira/browse/DC-585 - // Add selected columns to pending fields if (preg_match('/^([^\(]+)\.(\'?)(.*?)(\'?)$/', $expression, $field)) { - $this->_pendingFields[$componentAlias][$alias] = $field[3]; + $this->_queryComponents[$componentAlias]['agg_field'][$index] = $field[3]; } + $this->_neededTables[] = $tableAlias; } else { $e = explode('.', $terms[0]); @@ -1423,7 +1408,7 @@ public function getLimitSubquery() // Remove identifier quoting if it exists $e = $this->_tokenizer->bracketExplode($part, ' '); foreach ($e as $f) { - if ($f == 0 || $f % 2 == 0) { + if ($f == 0 || (int) $f % 2 == 0) { $partOriginal = str_replace(',', '', trim($f)); $e = explode('.', $partOriginal); foreach ($e as &$v) { @@ -2134,6 +2119,7 @@ public function getCountSqlQuery() * @param array $params an array of prepared statement parameters * @return integer the count of this query */ + #[\ReturnTypeWillChange] public function count($params = array()) { $q = $this->getCountSqlQuery(); diff --git a/lib/Doctrine/Query/Abstract.php b/lib/Doctrine/Query/Abstract.php index 8f7f91174..9d404e1c8 100644 --- a/lib/Doctrine/Query/Abstract.php +++ b/lib/Doctrine/Query/Abstract.php @@ -206,6 +206,16 @@ abstract class Doctrine_Query_Abstract * * map the name of the column / aggregate value this * component is mapped to a collection + * + * agg_field the field names for each aggregates + * Example: + * DQL: COMPONENT.FIELD as ALIAS + * SQL: TABLE.COLUMN as TABLE__0 + * $_queryComponents + * agg: + * 0: ALIAS + * agg_field: + * 0: FIELD */ protected $_queryComponents = array(); @@ -267,6 +277,11 @@ abstract class Doctrine_Query_Abstract */ protected $_preQueried = false; + /** + * @var array $_pendingJoinConditions an array containing pending joins + */ + protected $_pendingJoinConditions = array(); + /** * Fix for http://www.doctrine-project.org/jira/browse/DC-701 * @@ -1253,6 +1268,9 @@ protected function _constructQueryFromCache($cached) if (isset($components['agg'])) { $queryComponents[$alias]['agg'] = $components['agg']; } + if (isset($components['agg_field'])) { + $queryComponents[$alias]['agg_field'] = $components['agg_field']; + } if (isset($components['map'])) { $queryComponents[$alias]['map'] = $components['map']; } @@ -1283,6 +1301,9 @@ public function getCachedForm($customComponent = null) if (isset($components['agg'])) { $componentInfo[$alias]['agg'] = $components['agg']; } + if (isset($components['agg_field'])) { + $componentInfo[$alias]['agg_field'] = $components['agg_field']; + } if (isset($components['map'])) { $componentInfo[$alias]['map'] = $components['map']; } diff --git a/lib/Doctrine/Query/Having.php b/lib/Doctrine/Query/Having.php index 893f6ffc6..cb7308d74 100644 --- a/lib/Doctrine/Query/Having.php +++ b/lib/Doctrine/Query/Having.php @@ -78,7 +78,7 @@ private function parseAggregateFunction($func) * @param mixed $value * @return string */ - final private function _parseAliases($value) + private function _parseAliases($value) { if ( ! is_numeric($value)) { $a = explode('.', $value); diff --git a/lib/Doctrine/RawSql.php b/lib/Doctrine/RawSql.php index 25c07317b..73220e2e9 100644 --- a/lib/Doctrine/RawSql.php +++ b/lib/Doctrine/RawSql.php @@ -59,7 +59,7 @@ function __construct(Doctrine_Connection $connection = null, Doctrine_Hydrator_A protected function clear() { - $this->_preQuery = false; + $this->_preQueried = false; $this->_pendingJoinConditions = array(); } diff --git a/lib/Doctrine/Record.php b/lib/Doctrine/Record.php index 386286d29..2a2d92c06 100644 --- a/lib/Doctrine/Record.php +++ b/lib/Doctrine/Record.php @@ -151,7 +151,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count * @var string */ protected $_pendingDeletes = array(); - + /** * Array of pending un links in format alias => keys to be executed after save * @@ -185,7 +185,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count * * @var array */ - protected $_invokedSaveHooks = false; + protected $_invokedSaveHooks = array(); /** * @var integer $index this index is used for creating object identifiers @@ -259,7 +259,7 @@ public function __construct($table = null, $isNewEntry = false) } $repository = $this->_table->getRepository(); - + // Fix for #1682 and #1841. // Doctrine_Table does not have the repository yet during dummy record creation. if ($repository) { @@ -399,9 +399,9 @@ public function isValid($deep = false, $hooks = true) $event = new Doctrine_Event($this, Doctrine_Event::RECORD_VALIDATE); $this->preValidate($event); $this->getTable()->getRecordListener()->preValidate($event); - + if ( ! $event->skipOperation) { - + $validator = new Doctrine_Validator(); $validator->validateRecord($this); $this->validate(); @@ -553,7 +553,7 @@ public function postInsert($event) /** * Empty template method to provide concrete Record classes with the possibility - * to hook into the validation procedure. Useful for cleaning up data before + * to hook into the validation procedure. Useful for cleaning up data before * validating it. */ public function preValidate($event) @@ -587,14 +587,14 @@ public function preDqlDelete($event) { } /** - * Empty template method to provide Record classes with the ability to alter hydration + * Empty template method to provide Record classes with the ability to alter hydration * before it runs */ public function preHydrate($event) { } /** - * Empty template method to provide Record classes with the ability to alter hydration + * Empty template method to provide Record classes with the ability to alter hydration * after it runs */ public function postHydrate($event) @@ -633,7 +633,7 @@ public function getErrorStack() if ( ! $this->_errorStack) { $this->_errorStack = new Doctrine_Validator_ErrorStack(get_class($this)); } - + return $this->_errorStack; } @@ -798,6 +798,32 @@ private function prepareIdentifiers($exists = true) */ public function serialize() { + $vars = $this->__serialize(); + + return serialize($vars); + } + + /** + * this method is automatically called everytime an instance is unserialized + * + * @param string $serialized Doctrine_Record as serialized string + * @throws Doctrine_Record_Exception if the cleanData operation fails somehow + * @return void + */ + public function unserialize($serialized) + { + $array = unserialize($serialized); + + $this->__unserialize($array); + } + + /** + * Serializes the current instance for php 7.4+ + * + * @return array + */ + public function __serialize() { + $event = new Doctrine_Event($this, Doctrine_Event::RECORD_SERIALIZE); $this->preSerialize($event); @@ -839,36 +865,30 @@ public function serialize() } } - $str = serialize($vars); - $this->postSerialize($event); $this->getTable()->getRecordListener()->postSerialize($event); - return $str; + return $vars; } /** - * this method is automatically called everytime an instance is unserialized + * Unserializes a Doctrine_Record instance for php 7.4+ * - * @param string $serialized Doctrine_Record as serialized string - * @throws Doctrine_Record_Exception if the cleanData operation fails somehow - * @return void + * @param array $serialized */ - public function unserialize($serialized) + public function __unserialize($data) { $event = new Doctrine_Event($this, Doctrine_Event::RECORD_UNSERIALIZE); - + $manager = Doctrine_Manager::getInstance(); $connection = $manager->getConnectionForComponent(get_class($this)); $this->_table = $connection->getTable(get_class($this)); - + $this->preUnserialize($event); $this->getTable()->getRecordListener()->preUnserialize($event); - $array = unserialize($serialized); - - foreach($array as $k => $v) { + foreach($data as $k => $v) { $this->$k = $v; } @@ -924,7 +944,7 @@ public function state($state = null) if ($state == null) { return $this->_state; } - + $err = false; if (is_integer($state)) { if ($state >= 1 && $state <= 7) { @@ -1070,7 +1090,7 @@ public function clearRelated($name = null) * in order to check. If the reference didn't already exist and it doesn't * exist in the database, the related reference will be cleared immediately. * - * @param string $name + * @param string $name * @return boolean Whether or not the related relationship exists */ public function relatedExists($name) @@ -1150,18 +1170,18 @@ public function load(array $data = array()) // only load the data from database if the Doctrine_Record is in proxy state if ($this->exists() && $this->isInProxyState()) { $id = $this->identifier(); - + if ( ! is_array($id)) { $id = array($id); } - + if (empty($id)) { return false; } $table = $this->getTable(); $data = empty($data) ? $table->find($id, Doctrine_Core::HYDRATE_ARRAY) : $data; - + if (is_array($data)) { foreach ($data as $field => $value) { if ($table->hasField($field) && ( ! array_key_exists($field, $this->_data) || $this->_data[$field] === self::$_null)) { @@ -1169,19 +1189,19 @@ public function load(array $data = array()) } } } - + if ($this->isModified()) { $this->_state = Doctrine_Record::STATE_DIRTY; } else if (!$this->isInProxyState()) { $this->_state = Doctrine_Record::STATE_CLEAN; } - + return true; } - + return false; } - + /** * indicates whether record has any not loaded fields * @@ -1205,8 +1225,8 @@ public function isInProxyState() * sets a fieldname to have a custom accessor or check if a field has a custom * accessor defined (when called without $accessor parameter). * - * @param string $fieldName - * @param string $accessor + * @param string $fieldName + * @param string $accessor * @return boolean */ public function hasAccessor($fieldName, $accessor = null) @@ -1222,7 +1242,7 @@ public function hasAccessor($fieldName, $accessor = null) /** * clears the accessor for a field name * - * @param string $fieldName + * @param string $fieldName * @return void */ public function clearAccessor($fieldName) @@ -1234,7 +1254,7 @@ public function clearAccessor($fieldName) /** * gets the custom accessor for a field name * - * @param string $fieldName + * @param string $fieldName * @return string $accessor */ public function getAccessor($fieldName) @@ -1260,8 +1280,8 @@ public function getAccessors() * sets a fieldname to have a custom mutator or check if a field has a custom * mutator defined (when called without the $mutator parameter) * - * @param string $fieldName - * @param string $mutator + * @param string $fieldName + * @param string $mutator * @return boolean */ public function hasMutator($fieldName, $mutator = null) @@ -1277,7 +1297,7 @@ public function hasMutator($fieldName, $mutator = null) /** * gets the custom mutator for a field name * - * @param string $fieldname + * @param string $fieldname * @return string */ public function getMutator($fieldName) @@ -1291,7 +1311,7 @@ public function getMutator($fieldName) /** * clears the custom mutator for a field name * - * @param string $fieldName + * @param string $fieldName * @return void */ public function clearMutator($fieldName) @@ -1337,7 +1357,7 @@ public function get($fieldName, $load = true) if ($this->_table->getAttribute(Doctrine_Core::ATTR_AUTO_ACCESSOR_OVERRIDE) || $this->hasAccessor($fieldName)) { $componentName = $this->_table->getComponentName(); - $accessor = $this->hasAccessor($fieldName) + $accessor = $this->hasAccessor($fieldName) ? $this->getAccessor($fieldName) : 'get' . Doctrine_Inflector::classify($fieldName); @@ -1368,10 +1388,10 @@ protected function _get($fieldName, $load = true) } else { $value = $this->_data[$fieldName]; } - + return $value; } - + try { if ( ! isset($this->_references[$fieldName])) { if ($load) { @@ -1474,10 +1494,10 @@ protected function _set($fieldName, $value, $load = true) } else { $old = $this->_data[$fieldName]; } - + if ($this->_isValueModified($type, $old, $value)) { if ($value === null) { - $value = $this->_table->getDefaultValueOf($fieldName); + $value = $this->_table->getDefaultValueOf($fieldName); } $this->_data[$fieldName] = $value; $this->_modified[] = $fieldName; @@ -1538,13 +1558,13 @@ protected function _isValueModified($type, $old, $new) if ($type == 'boolean' && (is_bool($old) || is_numeric($old)) && (is_bool($new) || is_numeric($new)) && $old == $new) { return false; - } else if (in_array($type, array('decimal', 'float')) && is_numeric($old) && is_numeric($new)) { + } else if (in_array($type, array('decimal', 'float', 'double')) && is_numeric($old) && is_numeric($new)) { return $old * 100 != $new * 100; } else if (in_array($type, array('integer', 'int')) && is_numeric($old) && is_numeric($new)) { return $old != $new; } else if ($type == 'timestamp' || $type == 'date') { - $oldStrToTime = strtotime($old); - $newStrToTime = strtotime($new); + $oldStrToTime = @strtotime((string) $old); + $newStrToTime = @strtotime((string) $new); if ($oldStrToTime && $newStrToTime) { return $oldStrToTime !== $newStrToTime; } else { @@ -1558,7 +1578,7 @@ protected function _isValueModified($type, $old, $new) /** * Places a related component in the object graph. * - * This method inserts a related component instance in this record + * This method inserts a related component instance in this record * relations, populating the foreign keys accordingly. * * @param string $name related component alias in the relation @@ -1568,11 +1588,11 @@ protected function _isValueModified($type, $old, $new) public function coreSetRelated($name, $value) { $rel = $this->_table->getRelation($name); - + if ($value === null) { $value = self::$_null; } - + // one-to-many or one-to-one relation if ($rel instanceof Doctrine_Relation_ForeignKey || $rel instanceof Doctrine_Relation_LocalKey) { if ( ! $rel->isOneToOne()) { @@ -1762,7 +1782,7 @@ public function replace(Doctrine_Connection $conn = null) /** * retrieves an array of modified fields and associated new values. - * + * * @param boolean $old pick the old values (instead of the new ones) * @param boolean $last pick only lastModified values (@see getLastModified()) * @return array $a @@ -1774,8 +1794,8 @@ public function getModified($old = false, $last = false) $modified = $last ? $this->_lastModified:$this->_modified; foreach ($modified as $fieldName) { if ($old) { - $a[$fieldName] = isset($this->_oldValues[$fieldName]) - ? $this->_oldValues[$fieldName] + $a[$fieldName] = isset($this->_oldValues[$fieldName]) + ? $this->_oldValues[$fieldName] : $this->getTable()->getDefaultValueOf($fieldName); } else { $a[$fieldName] = $this->_data[$fieldName]; @@ -1799,7 +1819,7 @@ public function getLastModified($old = false) * Retrieves data prepared for a sql transaction. * * Returns an array of modified fields and values with data preparation; - * adds column aggregation inheritance and converts Records into primary + * adds column aggregation inheritance and converts Records into primary * key values. * * @param array $array @@ -1865,6 +1885,7 @@ public function getPrepared(array $array = array()) * * @return integer the number of columns in this record */ + #[\ReturnTypeWillChange] public function count() { return count($this->_data); @@ -1893,10 +1914,10 @@ public function toArray($deep = true, $prefixKey = false) if ($this->_state == self::STATE_LOCKED || $this->_state == self::STATE_TLOCKED) { return false; } - + $stateBeforeLock = $this->_state; $this->_state = $this->exists() ? self::STATE_LOCKED : self::STATE_TLOCKED; - + $a = array(); foreach ($this as $column => $value) { @@ -2162,6 +2183,7 @@ public function hasRelation($fieldName) * implements IteratorAggregate interface * @return Doctrine_Record_Iterator iterator through data */ + #[\ReturnTypeWillChange] public function getIterator() { return new Doctrine_Record_Iterator($this); @@ -2433,7 +2455,7 @@ public function unlink($alias, $ids = array(), $now = false) // fix for #1622 if ( ! isset($this->_references[$alias]) && $this->hasRelation($alias)) { $this->loadReference($alias); - } + } $allIds = array(); if (isset($this->_references[$alias])) { @@ -2613,8 +2635,8 @@ public function linkInDb($alias, $ids) } /** - * Reset the modified array and store the old array in lastModified so it - * can be accessed by users after saving a record, since the modified array + * Reset the modified array and store the old array in lastModified so it + * can be accessed by users after saving a record, since the modified array * is reset after the object is saved. * * @return void @@ -2667,7 +2689,7 @@ public function deleteNode() { $this->getNode()->delete(); } - + /** * Helps freeing the memory occupied by the entity. * Cuts all references the entity has to other entities and removes the entity diff --git a/lib/Doctrine/Record/Filter.php b/lib/Doctrine/Record/Filter.php index e1cf85d4a..b122ff723 100644 --- a/lib/Doctrine/Record/Filter.php +++ b/lib/Doctrine/Record/Filter.php @@ -50,18 +50,24 @@ public function init() } /** - * filterSet - * defines an implementation for filtering the set() method of Doctrine_Record + * Provides a way for setting property or relation value to the given record. * - * @param mixed $name name of the property or related component + * @param string $propertyOrRelation + * + * @return Doctrine_Record the given record + * + * @thrown Doctrine_Exception when this way is not available */ - abstract public function filterSet(Doctrine_Record $record, $name, $value); + abstract public function filterSet(Doctrine_Record $record, $propertyOrRelation, $value); /** - * filterGet - * defines an implementation for filtering the get() method of Doctrine_Record + * Provides a way for getting property or relation value from the given record. + * + * @param string $propertyOrRelation + * + * @return mixed * - * @param mixed $name name of the property or related component + * @thrown Doctrine_Exception when this way is not available */ - abstract public function filterGet(Doctrine_Record $record, $name); -} \ No newline at end of file + abstract public function filterGet(Doctrine_Record $record, $propertyOrRelation); +} diff --git a/lib/Doctrine/Record/Filter/Compound.php b/lib/Doctrine/Record/Filter/Compound.php index 98174deeb..38e599aec 100644 --- a/lib/Doctrine/Record/Filter/Compound.php +++ b/lib/Doctrine/Record/Filter/Compound.php @@ -32,66 +32,89 @@ */ class Doctrine_Record_Filter_Compound extends Doctrine_Record_Filter { + /** + * @var string[] + */ protected $_aliases = array(); + /** + * @param string[] $aliases A list of relation name + */ public function __construct(array $aliases) { $this->_aliases = $aliases; } + /** + * @throws Doctrine_Table_Exception when at least one configured alias is not a relation + */ public function init() { - // check that all aliases exist - foreach ($this->_aliases as $alias) { + // check that all aliases exist + foreach ($this->_aliases as $alias) { $this->_table->getRelation($alias); - } + } } /** - * filterSet - * defines an implementation for filtering the set() method of Doctrine_Record + * Provides a way for setting property or relation value to the given record. * - * @param mixed $name name of the property or related component + * @param string $propertyOrRelation + * + * @return Doctrine_Record the given record + * + * @thrown Doctrine_Record_UnknownPropertyException when this way is not available */ - public function filterSet(Doctrine_Record $record, $name, $value) + public function filterSet(Doctrine_Record $record, $propertyOrRelation, $value) { foreach ($this->_aliases as $alias) { + // The relationship must be fetched in order to check the field existence. + // Related to PHP-7.0 compatibility so an explicit call to method get is required. + $record[$alias]; + if ( ! $record->exists()) { - if (isset($record[$alias][$name])) { - $record[$alias][$name] = $value; - + if (isset($record[$alias][$propertyOrRelation])) { + $record[$alias][$propertyOrRelation] = $value; + return $record; } } else { - if (isset($record[$alias][$name])) { - $record[$alias][$name] = $value; + if (isset($record[$alias][$propertyOrRelation])) { + $record[$alias][$propertyOrRelation] = $value; } return $record; } } - throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $name, get_class($record))); + throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $propertyOrRelation, get_class($record))); } /** - * filterGet - * defines an implementation for filtering the get() method of Doctrine_Record + * Provides a way for getting property or relation value from the given record. * - * @param mixed $name name of the property or related component + * @param string $propertyOrRelation + * + * @return mixed + * + * @thrown Doctrine_Record_UnknownPropertyException when this way is not available */ - public function filterGet(Doctrine_Record $record, $name) + public function filterGet(Doctrine_Record $record, $propertyOrRelation) { foreach ($this->_aliases as $alias) { + // The relationship must be fetched in order to check the field existence. + // Related to PHP-7.0 compatibility so an explicit call to method get is required. + $record[$alias]; + if ( ! $record->exists()) { - if (isset($record[$alias][$name])) { - return $record[$alias][$name]; + if (isset($record[$alias][$propertyOrRelation])) { + return $record[$alias][$propertyOrRelation]; } } else { - if (isset($record[$alias][$name])) { - return $record[$alias][$name]; + if (isset($record[$alias][$propertyOrRelation])) { + return $record[$alias][$propertyOrRelation]; } } } - throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $name, get_class($record))); + throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $propertyOrRelation, get_class($record))); } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Record/Filter/Standard.php b/lib/Doctrine/Record/Filter/Standard.php index 7e4572889..f2a665358 100644 --- a/lib/Doctrine/Record/Filter/Standard.php +++ b/lib/Doctrine/Record/Filter/Standard.php @@ -34,24 +34,22 @@ class Doctrine_Record_Filter_Standard extends Doctrine_Record_Filter { /** - * filterSet - * defines an implementation for filtering the set() method of Doctrine_Record + * @param string $propertyOrRelation * - * @param mixed $name name of the property or related component + * @thrown Doctrine_Record_UnknownPropertyException */ - public function filterSet(Doctrine_Record $record, $name, $value) + public function filterSet(Doctrine_Record $record, $propertyOrRelation, $value) { - throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $name, get_class($record))); + throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $propertyOrRelation, get_class($record))); } /** - * filterGet - * defines an implementation for filtering the get() method of Doctrine_Record + * @param string $propertyOrRelation * - * @param mixed $name name of the property or related component + * @thrown Doctrine_Record_UnknownPropertyException */ - public function filterGet(Doctrine_Record $record, $name) + public function filterGet(Doctrine_Record $record, $propertyOrRelation) { - throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $name, get_class($record))); + throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $propertyOrRelation, get_class($record))); } } diff --git a/lib/Doctrine/Record/Iterator.php b/lib/Doctrine/Record/Iterator.php index 71a9d4f21..6385c0131 100644 --- a/lib/Doctrine/Record/Iterator.php +++ b/lib/Doctrine/Record/Iterator.php @@ -68,6 +68,7 @@ public static function initNullObject(Doctrine_Null $null) * * @return mixed */ + #[\ReturnTypeWillChange] public function current() { $value = parent::current(); diff --git a/lib/Doctrine/Relation.php b/lib/Doctrine/Relation.php index 03d77e1c4..cbdcb6ff2 100644 --- a/lib/Doctrine/Relation.php +++ b/lib/Doctrine/Relation.php @@ -41,12 +41,12 @@ abstract class Doctrine_Relation implements ArrayAccess * constant for ONE_TO_ONE and MANY_TO_ONE relationships */ const ONE = 0; - + /** * constant for MANY_TO_MANY and ONE_TO_MANY relationships */ const MANY = 1; - + // TRUE => mandatory, everything else is just a default value. this should be refactored // since TRUE can bot be used as a default value this way. All values should be default values. /** @@ -93,10 +93,10 @@ abstract class Doctrine_Relation implements ArrayAccess * refTable the reference table object (if any) * * onDelete referential delete action - * + * * onUpdate referential update action * - * deferred deferred constraint checking + * deferred deferred constraint checking * * alias relation alias * @@ -114,10 +114,10 @@ abstract class Doctrine_Relation implements ArrayAccess * in the parent table or in the child table. * * SET NULL: Delete or update the row from the parent table and set the foreign key column or columns in the - * child table to NULL. This is valid only if the foreign key columns do not have the NOT NULL qualifier + * child table to NULL. This is valid only if the foreign key columns do not have the NOT NULL qualifier * specified. Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported. * - * NO ACTION: In standard SQL, NO ACTION means no action in the sense that an attempt to delete or update a primary + * NO ACTION: In standard SQL, NO ACTION means no action in the sense that an attempt to delete or update a primary * key value is not allowed to proceed if there is a related foreign key value in the referenced table. * * RESTRICT: Rejects the delete or update operation for the parent table. NO ACTION and RESTRICT are the same as @@ -135,7 +135,7 @@ public function __construct(array $definition) if (isset($definition[$key])) { $def[$key] = $definition[$key]; } else { - $def[$key] = $this->definition[$key]; + $def[$key] = $this->definition[$key]; } } $this->definition = $def; @@ -169,20 +169,32 @@ public function isEqual() return $this->definition['equal']; } + /** + * @return bool + */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->definition[$offset]); } + /** + * @return mixed + */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { if (isset($this->definition[$offset])) { return $this->definition[$offset]; } - + return null; } + /** + * @return void + */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { if (isset($this->definition[$offset])) { @@ -190,6 +202,10 @@ public function offsetSet($offset, $value) } } + /** + * @return void + */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { $this->definition[$offset] = false; @@ -200,7 +216,7 @@ public function offsetUnset($offset) * * @return array */ - public function toArray() + public function toArray() { return $this->definition; } @@ -227,7 +243,7 @@ final public function getType() { return $this->definition['type']; } - + /** * Checks whether this relation cascades deletions to the related objects * on the application level. @@ -273,7 +289,7 @@ final public function getLocal() { return $this->definition['local']; } - + /** * getLocalFieldName * returns the field name of the local column @@ -305,7 +321,7 @@ final public function getForeign() { return $this->definition['foreign']; } - + /** * getLocalFieldName * returns the field name of the foreign column diff --git a/lib/Doctrine/Search/File.php b/lib/Doctrine/Search/File.php index b04b2986c..feff520f4 100644 --- a/lib/Doctrine/Search/File.php +++ b/lib/Doctrine/Search/File.php @@ -77,6 +77,10 @@ public function indexDirectory($dir) continue; } + if ($file->isDir()) { + continue; + } + $this->updateIndex(array('url' => $file->getPathName(), 'content' => file_get_contents($file))); } diff --git a/lib/Doctrine/Sequence/Mssql.php b/lib/Doctrine/Sequence/Mssql.php index 5b786560a..fff760886 100644 --- a/lib/Doctrine/Sequence/Mssql.php +++ b/lib/Doctrine/Sequence/Mssql.php @@ -32,6 +32,8 @@ */ class Doctrine_Sequence_Mssql extends Doctrine_Sequence { + protected $warnings; + /** * Returns the next free id of a sequence * diff --git a/lib/Doctrine/Table.php b/lib/Doctrine/Table.php index 4cf111a0c..faac80574 100644 --- a/lib/Doctrine/Table.php +++ b/lib/Doctrine/Table.php @@ -31,8 +31,6 @@ * @version $Revision$ * @link www.doctrine-project.org * @since 1.0 - * @method mixed findBy*(mixed $value) magic finders; @see __call() - * @method mixed findOneBy*(mixed $value) magic finders; @see __call() */ class Doctrine_Table extends Doctrine_Configurable implements Countable, Serializable { @@ -561,7 +559,7 @@ public function getRecordInstance() /** * Checks whether a column is inherited from a component further up in the hierarchy. * - * @param $columnName The column name + * @param string $columnName The column name * @return boolean TRUE if column is inherited, FALSE otherwise. */ public function isInheritedColumn($columnName) @@ -965,7 +963,7 @@ public function bind($args, $type) * @param string $componentName the name of the related component * @param string $options relation options * @see Doctrine_Relation::_$definition - * @return Doctrine_Record this object + * @return void */ public function hasOne() { @@ -978,7 +976,7 @@ public function hasOne() * @param string $componentName the name of the related component * @param string $options relation options * @see Doctrine_Relation::_$definition - * @return Doctrine_Record this object + * @return void */ public function hasMany() { @@ -994,7 +992,7 @@ public function hasMany() * side. * * @param string $alias the relation alias to search for. - * @return boolean true if the relation exists. Otherwise false. + * @return bool true if the relation exists. Otherwise false. */ public function hasRelation($alias) { @@ -1132,6 +1130,11 @@ public function processOrderBy($alias, $orderBy, $columnNames = false) $alias = $this->getComponentName(); } + // Php8.1 require a string + if (null === $orderBy) { + $orderBy = ''; + } + if ( ! is_array($orderBy)) { $e1 = explode(',', $orderBy); } else { @@ -1176,6 +1179,10 @@ public function getColumnName($fieldName) return $this->_columnNames[$fieldName]; } + if (null === $fieldName) { + return ''; + } + return strtolower($fieldName); } @@ -1701,7 +1708,7 @@ public function findByDql($dql, $params = array(), $hydrationMode = null) * Find records basing on a field. * * @param string $column field for the WHERE clause - * @param string $value prepared statement parameter + * @param string|array $value prepared statement parameter * @param int $hydrationMode Doctrine_Core::HYDRATE_ARRAY or Doctrine_Core::HYDRATE_RECORD * @return Doctrine_Collection|array */ @@ -1716,7 +1723,7 @@ public function findBy($fieldName, $value, $hydrationMode = null) * Finds the first record that satisfy the clause. * * @param string $column field for the WHERE clause - * @param string $value prepared statement parameter + * @param string|array $value prepared statement parameter * @param int $hydrationMode Doctrine_Core::HYDRATE_ARRAY or Doctrine_Core::HYDRATE_RECORD * @return Doctrine_Record */ @@ -1977,6 +1984,7 @@ final public function applyInheritance($where) * * @return integer number of records in the table */ + #[\ReturnTypeWillChange] public function count() { return $this->createQuery()->count(); @@ -2974,12 +2982,44 @@ public function __call($method, $arguments) throw new Doctrine_Table_Exception(sprintf('Unknown method %s::%s', get_class($this), $method)); } + /** + * serialize + * this method is automatically called when an instance of Doctrine_Record is serialized + * + * @return string + */ public function serialize() { + $data = $this->__serialize(); + + return serialize($data); + } + + /** + * this method is automatically called everytime an instance is unserialized + * + * @param string $serialized Doctrine_Record as serialized string + * @return void + */ + public function unserialize($serialized) + { + $data = unserialize($serialized); + + $this->__unserialize($data); + } + + + /** + * Serializes the current instance for php 7.4+ + * + * @return array + */ + public function __serialize() { + $options = $this->_options; unset($options['declaringClass']); - return serialize(array( + return array( $this->_identifier, $this->_identifierType, $this->_columns, @@ -2991,26 +3031,33 @@ public function serialize() $options, $this->_invokedMethods, $this->_useIdentityMap, - )); + ); } - public function unserialize($data) - { - $all = unserialize($data); + /** + * Unserializes a Doctrine_Record instance for php 7.4+ + * + * @param array $data + */ + public function __unserialize($data) { - $this->_identifier = $all[0]; - $this->_identifierType = $all[1]; - $this->_columns = $all[2]; - $this->_uniques = $all[3]; - $this->_fieldNames = $all[4]; - $this->_columnNames = $all[5]; - $this->columnCount = $all[6]; - $this->hasDefaultValues = $all[7]; - $this->_options = $all[8]; - $this->_invokedMethods = $all[9]; - $this->_useIdentityMap = $all[10]; + $this->_identifier = $data[0]; + $this->_identifierType = $data[1]; + $this->_columns = $data[2]; + $this->_uniques = $data[3]; + $this->_fieldNames = $data[4]; + $this->_columnNames = $data[5]; + $this->columnCount = $data[6]; + $this->hasDefaultValues = $data[7]; + $this->_options = $data[8]; + $this->_invokedMethods = $data[9]; + $this->_useIdentityMap = $data[10]; } + /** + * Creates new instance and initialize it from cache. + * + */ public function initializeFromCache(Doctrine_Connection $conn) { $this->_conn = $conn; diff --git a/lib/Doctrine/Table/Repository.php b/lib/Doctrine/Table/Repository.php index b31cda062..715160434 100644 --- a/lib/Doctrine/Table/Repository.php +++ b/lib/Doctrine/Table/Repository.php @@ -102,6 +102,7 @@ public function get($oid) * Doctrine_Registry implements interface Countable * @return integer the number of records this registry has */ + #[\ReturnTypeWillChange] public function count() { return count($this->registry); @@ -138,6 +139,7 @@ public function evictAll() * getIterator * @return ArrayIterator */ + #[\ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->registry); diff --git a/lib/Doctrine/Table/Repository/None.php b/lib/Doctrine/Table/Repository/None.php index da421ec74..fe651cae6 100644 --- a/lib/Doctrine/Table/Repository/None.php +++ b/lib/Doctrine/Table/Repository/None.php @@ -62,6 +62,7 @@ public function get($oid) * * @return integer the number of records this registry has */ + #[\ReturnTypeWillChange] public function count() { return 0; diff --git a/lib/Doctrine/Task.php b/lib/Doctrine/Task.php index 8af7cfb1f..3a9311c07 100644 --- a/lib/Doctrine/Task.php +++ b/lib/Doctrine/Task.php @@ -53,10 +53,10 @@ public function __construct($dispatcher = null) { $this->dispatcher = $dispatcher; - $taskName = $this->getTaskName(); + $taskName = (string) $this->getTaskName(); //Derive the task name only if it wasn't entered at design-time - if (! strlen($taskName)) { + if ('' === trim($taskName)) { $taskName = self::deriveTaskName(get_class($this)); } diff --git a/lib/Doctrine/Task/BuildAll.php b/lib/Doctrine/Task/BuildAll.php index 2d5a4bb9d..07d07e216 100644 --- a/lib/Doctrine/Task/BuildAll.php +++ b/lib/Doctrine/Task/BuildAll.php @@ -37,6 +37,7 @@ class Doctrine_Task_BuildAll extends Doctrine_Task $optionalArguments = array(); protected $models, + $createDb, $tables; public function __construct($dispatcher = null) diff --git a/lib/Doctrine/Task/BuildAllLoad.php b/lib/Doctrine/Task/BuildAllLoad.php index 6b6d2fc5a..90e685a01 100644 --- a/lib/Doctrine/Task/BuildAllLoad.php +++ b/lib/Doctrine/Task/BuildAllLoad.php @@ -35,6 +35,9 @@ class Doctrine_Task_BuildAllLoad extends Doctrine_Task public $description = 'Calls build-all, and load-data', $requiredArguments = array(), $optionalArguments = array(); + + protected $buildAll, + $loadData; public function __construct($dispatcher = null) { diff --git a/lib/Doctrine/Task/BuildAllReload.php b/lib/Doctrine/Task/BuildAllReload.php index f06475cf2..1cd3c1aba 100644 --- a/lib/Doctrine/Task/BuildAllReload.php +++ b/lib/Doctrine/Task/BuildAllReload.php @@ -35,6 +35,9 @@ class Doctrine_Task_BuildAllReload extends Doctrine_Task public $description = 'Calls rebuild-db and load-data', $requiredArguments = array(), $optionalArguments = array(); + + protected $rebuildDb, + $loadData; public function __construct($dispatcher = null) { diff --git a/lib/Doctrine/Task/RebuildDb.php b/lib/Doctrine/Task/RebuildDb.php index 4a3e66581..ad9623f6d 100644 --- a/lib/Doctrine/Task/RebuildDb.php +++ b/lib/Doctrine/Task/RebuildDb.php @@ -35,6 +35,10 @@ class Doctrine_Task_RebuildDb extends Doctrine_Task public $description = 'Drops and re-creates databases', $requiredArguments = array(), $optionalArguments = array(); + + protected $dropDb, + $createDb, + $createTables; public function __construct($dispatcher = null) { diff --git a/lib/Doctrine/Validator.php b/lib/Doctrine/Validator.php index afd1709ac..bab8fe82c 100644 --- a/lib/Doctrine/Validator.php +++ b/lib/Doctrine/Validator.php @@ -126,9 +126,9 @@ public static function validateLength($value, $type, $maximumLength) public static function getStringLength($string) { if (function_exists('mb_strlen')) { - return mb_strlen($string, 'utf8'); + return mb_strlen((string) $string, 'utf8'); } else { - return strlen(utf8_decode($string)); + return strlen(utf8_decode((string) $string)); } } diff --git a/lib/Doctrine/Validator/ErrorStack.php b/lib/Doctrine/Validator/ErrorStack.php index d3591ff08..b3f5c41c1 100644 --- a/lib/Doctrine/Validator/ErrorStack.php +++ b/lib/Doctrine/Validator/ErrorStack.php @@ -149,6 +149,7 @@ public function clear() * * @return ArrayIterator unknown */ + #[\ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->_errors); @@ -164,6 +165,7 @@ public function toArray() * * @return integer */ + #[\ReturnTypeWillChange] public function count() { return count($this->_errors); diff --git a/lib/Doctrine/Validator/Exception.php b/lib/Doctrine/Validator/Exception.php index 53a3df079..98d3534fb 100644 --- a/lib/Doctrine/Validator/Exception.php +++ b/lib/Doctrine/Validator/Exception.php @@ -51,11 +51,13 @@ public function getInvalidRecords() return $this->invalid; } + #[\ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->invalid); } + #[\ReturnTypeWillChange] public function count() { return count($this->invalid); diff --git a/lib/Doctrine/Validator/Notblank.php b/lib/Doctrine/Validator/Notblank.php index 50dbced75..fe6591105 100644 --- a/lib/Doctrine/Validator/Notblank.php +++ b/lib/Doctrine/Validator/Notblank.php @@ -41,6 +41,6 @@ class Doctrine_Validator_Notblank extends Doctrine_Validator_Driver */ public function validate($value) { - return (trim($value) !== '' && $value !== null); + return (null !== $value && '' !== trim($value)); } } \ No newline at end of file diff --git a/package.xml b/package.xml deleted file mode 100644 index 056831624..000000000 --- a/package.xml +++ /dev/null @@ -1,1625 +0,0 @@ - - - Doctrine - pear.doctrine-project.org - PHP5 Database ORM - Doctrine is an ORM (object relational mapper) for PHP 5.2.x+ that sits on top of -a powerful DBAL (database abstraction layer). One of its key features is the -ability to optionally write database queries in an OO (object oriented) -SQL-dialect called DQL inspired by Hibernates HQL. This provides developers with -a powerful alternative to SQL that maintains a maximum of flexibility without -requiring needless code duplication. - - Konsta Vesterinen - zYne- - kvesteri@cc.hut.fi - yes - - - Jonathan H. Wage - jwage - jonwage@gmail.com - yes - - 2010-03-29 - - - 1.2.2 - 1.2.2 - - - stable - stable - - LGPL license - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5.2.3 - - - 1.4.0b1 - - - PEAR - pear.php.net - 1.3.6 - - - pdo - - - - - pdo_dblib - - - pdo_mysql - - - pdo_odbc - - - pdo_sqlite - - - pdo_oci - - - pdo_pgsql - - - - - - - - 1.2.2 - 1.2.2 - - - stable - stable - - 2010-03-29 - LGPL license - -- - - - - - 1.2.1 - 1.2.1 - - - stable - stable - - 2009-12-07 - LGPL license - -- - - - - - 1.2.0 - 1.2.0 - - - stable - stable - - 2009-11-30 - LGPL license - -- - - - - - 1.1.2 - 1.1.2 - - - stable - stable - - 2009-06-15 - LGPL license - -- - - - - - 1.1.1 - 1.1.1 - - - stable - stable - - 2009-05-11 - LGPL license - -- - - - - - 1.1.0 - 1.1.0 - - - stable - stable - - 2009-03-16 - LGPL license - -- - - - - - 1.0.2 - 1.0.2 - - - stable - stable - - 2008-09-11 - LGPL license - -- - - - - - 1.0.1 - 1.0.1 - - - stable - stable - - 2008-09-09 - LGPL license - -- - - - - - 1.0.0 - 1.0.0 - - - stable - stable - - 2008-09-01 - LGPL license - -- - - - - - 0.11.0 - 0.11.0 - - - stable - stable - - 2008-06-23 - LGPL license - -- - - - - - 0.10.4 - 0.10.4 - - - beta - beta - - 2008-03-28 - LGPL license - -- - - - - - 0.10.3 - 0.10.3 - - - beta - beta - - 2008-03-18 - LGPL license - -- - - - - - 0.10.2 - 0.10.2 - - - beta - beta - - 2008-03-01 - LGPL license - -- - - - - - 0.10.1 - 0.10.1 - - - beta - beta - - 2008-02-29 - LGPL license - -- - - - - - 0.10.0 - 0.10.0 - - - beta - beta - - 2008-02-13 - LGPL license - -- - - - - - 0.9 - 0.9 - - - beta - beta - - 2008-02-06 - MIT license - -barfoo - - - - diff --git a/tests/BaseTestCase.php b/tests/BaseTestCase.php index 6a6595cd4..5a865cab2 100644 --- a/tests/BaseTestCase.php +++ b/tests/BaseTestCase.php @@ -30,7 +30,7 @@ * @since 1.0 * @version $Revision$ */ -class Doctrine_Base_TestCase extends Doctrine_UnitTestCase +class Doctrine_Base_TestCase extends Doctrine_UnitTestCase { public function testAggressiveModelLoading() { @@ -92,21 +92,22 @@ public function testModelLoadingCacheInformation() $this->assertTrue(file_exists($modelFiles['ConservativeModelLoadingContact'])); } - public function testGetConnectionByTableName() + public function testGetConnectionByTableNameForTableWithOneModel() { - $connectionBefore = Doctrine_Core::getConnectionByTableName('entity'); + $connectionBefore = Doctrine_Core::getConnectionByTableName('account'); - Doctrine_Manager::connection('sqlite::memory:', 'test_memory'); - Doctrine_Manager::getInstance()->bindComponent('Entity', 'test_memory'); + $this->openAdditionalConnection('sqlite::memory:', 'test_memory'); - $connectionAfter = Doctrine_Core::getConnectionByTableName('entity'); + Doctrine_Manager::getInstance()->bindComponent('Account', 'test_memory'); + + $connectionAfter = Doctrine_Core::getConnectionByTableName('account'); $this->assertEqual($connectionAfter->getName(), 'test_memory'); - Doctrine_Manager::getInstance()->bindComponent('Entity', $connectionBefore->getName()); + Doctrine_Manager::getInstance()->bindComponent('Account', $connectionBefore->getName()); + + $connectionAfter = Doctrine_Core::getConnectionByTableName('account'); - $connectionAfter = Doctrine_Core::getConnectionByTableName('entity'); - $this->assertEqual($connectionBefore->getName(), $connectionAfter->getName()); } -} \ No newline at end of file +} diff --git a/tests/Cache/DbTestCase.php b/tests/Cache/DbTestCase.php index 91dc4563a..594103662 100644 --- a/tests/Cache/DbTestCase.php +++ b/tests/Cache/DbTestCase.php @@ -33,6 +33,8 @@ */ class Doctrine_Cache_Db_TestCase extends Doctrine_Cache_Abstract_TestCase { + protected $cache; + public function setUp() { parent::setUp(); diff --git a/tests/CliTestCase.php b/tests/CliTestCase.php index 681bcb833..c2e206533 100644 --- a/tests/CliTestCase.php +++ b/tests/CliTestCase.php @@ -30,7 +30,7 @@ * @since 1.0 * @version $Revision$ */ -class Doctrine_Cli_TestCase extends Doctrine_UnitTestCase +class Doctrine_Cli_TestCase extends UnitTestCase { /** * @ignore @@ -57,16 +57,12 @@ class Doctrine_Cli_TestCase extends Doctrine_UnitTestCase protected function getFixturesPath() { if (! isset($this->fixturesPath)) { - $this->fixturesPath = dirname(__FILE__) . '/CliTestCase'; + $this->fixturesPath = __DIR__ . '/CliTestCase'; } return $this->fixturesPath; } - public function setUp() {} - - public function tearDown() {} - public function testTheNameOfTheTaskBaseClassNameIsStoredInAClassConstant() { $this->assertFalse(is_null(constant('Doctrine_Cli::TASK_BASE_CLASS'))); @@ -446,4 +442,4 @@ protected function _run(array $args) class Doctrine_Cli_TestCase_TestTask01 extends Doctrine_Task { public function execute() {} -} \ No newline at end of file +} diff --git a/tests/CliTestCase/cli-default.php b/tests/CliTestCase/cli-default.php index cf3e8f524..c0e4c46a8 100644 --- a/tests/CliTestCase/cli-default.php +++ b/tests/CliTestCase/cli-default.php @@ -5,10 +5,10 @@ * @author Dan Bettles */ -require_once(dirname(dirname(dirname(__FILE__))) . '/lib/Doctrine/Core.php'); +require_once dirname(__DIR__, 2) . '/lib/Doctrine/Core.php'; spl_autoload_register(array('Doctrine_Core', 'autoload')); -require_once(dirname(__FILE__) . '/TestTask02.php'); +require_once(__DIR__ . '/TestTask02.php'); $cli = new Doctrine_Cli(); $cli->run($_SERVER['argv']); diff --git a/tests/CliTestCase/cli-with-custom-tasks.php b/tests/CliTestCase/cli-with-custom-tasks.php index ef081e51f..8d16617ad 100644 --- a/tests/CliTestCase/cli-with-custom-tasks.php +++ b/tests/CliTestCase/cli-with-custom-tasks.php @@ -5,12 +5,12 @@ * @author Dan Bettles */ -require_once(dirname(dirname(dirname(__FILE__))) . '/lib/Doctrine/Core.php'); +require_once dirname(__DIR__, 2) . '/lib/Doctrine/Core.php'; spl_autoload_register(array('Doctrine_Core', 'autoload')); $cli = new Doctrine_Cli(); -require_once(dirname(__FILE__) . '/TestTask02.php'); +require_once(__DIR__ . '/TestTask02.php'); //Either...: $cli->registerTaskClass('Doctrine_Cli_TestCase_TestTask02'); diff --git a/tests/CliTestCase/cli-without-autoregistered-custom-tasks.php b/tests/CliTestCase/cli-without-autoregistered-custom-tasks.php index f9b644f5a..a7b6d2599 100644 --- a/tests/CliTestCase/cli-without-autoregistered-custom-tasks.php +++ b/tests/CliTestCase/cli-without-autoregistered-custom-tasks.php @@ -5,10 +5,10 @@ * @author Dan Bettles */ -require_once(dirname(dirname(dirname(__FILE__))) . '/lib/Doctrine/Core.php'); +require_once dirname(__DIR__, 2) . '/lib/Doctrine/Core.php'; spl_autoload_register(array('Doctrine_Core', 'autoload')); -require_once(dirname(__FILE__) . '/TestTask02.php'); +require_once(__DIR__ . '/TestTask02.php'); $cli = new Doctrine_Cli(array('autoregister_custom_tasks' => false)); $cli->run($_SERVER['argv']); diff --git a/tests/Connection/CustomTestCase.php b/tests/Connection/CustomTestCase.php index badb87d77..6fd75b448 100644 --- a/tests/Connection/CustomTestCase.php +++ b/tests/Connection/CustomTestCase.php @@ -32,6 +32,9 @@ */ class Doctrine_Connection_Custom_TestCase extends Doctrine_UnitTestCase { + protected $_conn; + protected $_dbh; + public function setUp() { $manager = Doctrine_Manager::getInstance(); @@ -49,7 +52,10 @@ public function testConnection() class Doctrine_Connection_Test extends Doctrine_Connection_Common { - + /** + * @var string $driverName The name of this connection driver + */ + protected $driverName = 'Mock'; } class Doctrine_Adapter_Test implements Doctrine_Adapter_Interface diff --git a/tests/DoctrineTest.php b/tests/DoctrineTest.php index 59e60b050..3bafe851a 100644 --- a/tests/DoctrineTest.php +++ b/tests/DoctrineTest.php @@ -32,10 +32,10 @@ * @version $Revision$ */ -require_once dirname(__FILE__) . '/DoctrineTest/UnitTestCase.php'; -require_once dirname(__FILE__) . '/DoctrineTest/GroupTest.php'; -require_once dirname(__FILE__) . '/DoctrineTest/Doctrine_UnitTestCase.php'; -require_once dirname(__FILE__) . '/DoctrineTest/Reporter.php'; +require_once __DIR__ . '/DoctrineTest/UnitTestCase.php'; +require_once __DIR__ . '/DoctrineTest/GroupTest.php'; +require_once __DIR__ . '/DoctrineTest/Doctrine_UnitTestCase.php'; +require_once __DIR__ . '/DoctrineTest/Reporter.php'; class DoctrineTest { @@ -75,13 +75,13 @@ public function run() { $testGroup = $this->testGroup; if (PHP_SAPI === 'cli') { - require_once(dirname(__FILE__) . '/DoctrineTest/Reporter/Cli.php'); + require_once(__DIR__ . '/DoctrineTest/Reporter/Cli.php'); $reporter = new DoctrineTest_Reporter_Cli(); $argv = $_SERVER['argv']; array_shift($argv); $options = $this->parseOptions($argv); } else { - require_once(dirname(__FILE__) . '/DoctrineTest/Reporter/Html.php'); + require_once(__DIR__ . '/DoctrineTest/Reporter/Html.php'); $options = $_GET; if (isset($options['filter'])) { if ( ! is_array($options['filter'])) { @@ -148,7 +148,7 @@ public function run() * somebody could give it a try. Just replace this block of code * with the one below * - define('PHPCOVERAGE_HOME', dirname(dirname(__FILE__)) . '/vendor/spikephpcoverage'); + define('PHPCOVERAGE_HOME', dirname(__DIR__) . '/vendor/spikephpcoverage'); require_once PHPCOVERAGE_HOME . '/CoverageRecorder.php'; require_once PHPCOVERAGE_HOME . '/reporter/HtmlCoverageReporter.php'; @@ -170,8 +170,8 @@ public function run() $ret = $testGroup->run($reporter, $filter); $result['coverage'] = xdebug_get_code_coverage(); xdebug_stop_code_coverage(); - file_put_contents(dirname(__FILE__) . '/coverage/coverage.txt', serialize($result)); - require_once dirname(__FILE__) . '/DoctrineTest/Coverage.php'; + file_put_contents(__DIR__ . '/coverage/coverage.txt', serialize($result)); + require_once __DIR__ . '/DoctrineTest/Coverage.php'; $coverageGeneration = new DoctrineTest_Coverage(); $coverageGeneration->generateReport(); return $ret; @@ -203,7 +203,7 @@ public function run() */ public function requireModels() { - $models = new DirectoryIterator(dirname(__FILE__) . '/models/'); + $models = new DirectoryIterator(__DIR__ . '/models/'); foreach($models as $key => $file) { if ($file->isFile() && ! $file->isDot()) { diff --git a/tests/DoctrineTest/Doctrine_UnitTestCase.php b/tests/DoctrineTest/Doctrine_UnitTestCase.php index 15d05f36e..a1f0fb2f7 100644 --- a/tests/DoctrineTest/Doctrine_UnitTestCase.php +++ b/tests/DoctrineTest/Doctrine_UnitTestCase.php @@ -53,10 +53,40 @@ class Doctrine_UnitTestCase extends UnitTestCase protected $dataDict; protected $transaction; protected $_name; - + protected $query; + protected $profiler; + protected $import; + protected $sequence; + protected $exc; protected $init = false; + /** + * @var Doctrine_Connection[] + */ + private $additionalConnections = array(); + + public function setUp() + { + parent::setUp(); + + if ( ! $this->init) { + $this->init(); + } + if (isset($this->objTable)) { + $this->objTable->clear(); + } + + $this->init = true; + } + + public function tearDown() + { + $this->closeAdditionalConnections(); + + parent::tearDown(); + } + public function getName() { return $this->_name; @@ -275,18 +305,20 @@ public function getDeclaration($type) { return $this->dataDict->getPortableDeclaration(array('type' => $type, 'name' => 'colname', 'length' => 1, 'fixed' => true)); } - public function setUp() + + protected function openAdditionalConnection($adapter = null, $name = null) { - if ( ! $this->init) { - $this->init(); - } - if (isset($this->objTable)) { - $this->objTable->clear(); - } + $connection = $this->manager->openConnection($adapter, $name); - $this->init = true; + $this->additionalConnections[] = $connection; + + return $connection; } - public function tearDown() { + private function closeAdditionalConnections() + { + foreach ($this->additionalConnections as $connection) { + $this->manager->closeConnection($connection); + } } } diff --git a/tests/DoctrineTest/GroupTest.php b/tests/DoctrineTest/GroupTest.php index 5e826c048..b17f5e37e 100644 --- a/tests/DoctrineTest/GroupTest.php +++ b/tests/DoctrineTest/GroupTest.php @@ -6,6 +6,8 @@ class GroupTest extends UnitTestCase protected $_title; protected $_onlyRunFailed = false; + protected $_formatter; + public function __construct($title, $name) { $this->_title = $title; diff --git a/tests/DoctrineTest/UnitTestCase.php b/tests/DoctrineTest/UnitTestCase.php index 681079d03..f1aca2fe5 100644 --- a/tests/DoctrineTest/UnitTestCase.php +++ b/tests/DoctrineTest/UnitTestCase.php @@ -11,6 +11,14 @@ class UnitTestCase protected static $_lastRunsPassesAndFails = array('passes' => array(), 'fails' => array()); + public function setUp() + { + } + + public function tearDown() + { + } + public function init() { $tmpFileName = $this->getPassesAndFailsCachePath(); @@ -149,15 +157,11 @@ public function _fail($message = "") self::$_passesAndFails['fails'][$class] = $class; } - public function run(DoctrineTest_Reporter $reporter = null, $filter = null) + public function run(DoctrineTest_Reporter $reporter = null, $filter = null) { foreach (get_class_methods($this) as $method) { - if (substr($method, 0, 4) === 'test') { - $this->setUp(); - - $this->$method(); - - $this->tearDown(); + if ($this->isTestMethod($method)) { + $this->runTest($method); } } } @@ -179,7 +183,7 @@ public function getPassCount() public function getPassesAndFailsCachePath() { - $dir = dirname(__FILE__) . '/doctrine_tests'; + $dir = __DIR__ . '/doctrine_tests'; if ( ! is_dir($dir)) { mkdir($dir, 0777, true); } @@ -249,4 +253,49 @@ public function getNumFixedFails() { return count($this->getFixedFails()); } -} \ No newline at end of file + + private function runTest($method) + { + $this->setUp(); + + $this->doRunTestAndTearDown($method); + } + + private function doRunTestAndTearDown($method) + { + $test = $this; + + $this->tryFinally( + function () use ($test, $method) { + $test->$method(); + }, + function () use ($test) { + $test->tearDown(); + } + ); + } + + private function isTestMethod($method) + { + return 'test' === substr($method, 0, 4); + } + + private function tryFinally(Closure $try, Closure $finally) + { + $thrownException = null; + + try { + $try(); + } catch (Throwable $e) { + $thrownException = $e; + } catch (Exception $e) { // for PHP v5.x + $thrownException = $e; + } + + $finally(); + + if (null !== $thrownException) { + throw $thrownException; + } + } +} diff --git a/tests/EventListenerTestCase.php b/tests/EventListenerTestCase.php index 737910ebb..f84218340 100644 --- a/tests/EventListenerTestCase.php +++ b/tests/EventListenerTestCase.php @@ -192,6 +192,7 @@ public function clear() { public function getAll() { return $this->messages; } + #[\ReturnTypeWillChange] public function count() { return count($this->messages); } diff --git a/tests/Export/PgsqlTestCase.php b/tests/Export/PgsqlTestCase.php index aa99596bc..d2a393fea 100644 --- a/tests/Export/PgsqlTestCase.php +++ b/tests/Export/PgsqlTestCase.php @@ -128,7 +128,7 @@ public function testCreateTableSupportsMultiplePks() public function testExportSql() { $sql = $this->export->exportClassesSql(array("FooRecord", "FooReferenceRecord", "FooLocallyOwned", "FooForeignlyOwned", "FooForeignlyOwnedWithPK", "FooBarRecord", "BarRecord")); - //dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files'); + //__DIR__ . DIRECTORY_SEPARATOR . '_files'); $this->assertEqual($sql, array ( 0 => 'CREATE TABLE foo_reference (foo1 BIGINT, foo2 BIGINT, PRIMARY KEY(foo1, foo2))', 1 => 'CREATE TABLE foo_locally_owned (id BIGSERIAL, name VARCHAR(200), PRIMARY KEY(id))', @@ -175,4 +175,4 @@ public function testAlterTableSqlIdentifierQuoting() 1 => 'ALTER TABLE "mytable" DROP "oldfield"' )); } -} \ No newline at end of file +} diff --git a/tests/Export/RecordTestCase.php b/tests/Export/RecordTestCase.php index 39a6976af..c51f14f53 100644 --- a/tests/Export/RecordTestCase.php +++ b/tests/Export/RecordTestCase.php @@ -97,7 +97,7 @@ public function testExportSupportsForeignKeysForManyToManyRelations() public function testExportModelFromDirectory() { - Doctrine_Core::createTablesFromModels(dirname(__FILE__) . DIRECTORY_SEPARATOR .'..' . DIRECTORY_SEPARATOR . 'models' . DIRECTORY_SEPARATOR . 'export'); + Doctrine_Core::createTablesFromModels(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'models' . DIRECTORY_SEPARATOR . 'export'); $this->assertEqual($this->adapter->pop(), 'COMMIT'); $this->assertEqual($this->adapter->pop(), 'ALTER TABLE cms__category_languages ADD CONSTRAINT cms__category_languages_category_id_cms__category_id FOREIGN KEY (category_id) REFERENCES cms__category(id) ON DELETE CASCADE'); $this->assertEqual($this->adapter->pop(), 'CREATE TABLE cms__category_languages (id BIGINT AUTO_INCREMENT, name TEXT, category_id BIGINT, language_id BIGINT, INDEX index_category_idx (category_id), INDEX index_language_idx (language_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = INNODB'); diff --git a/tests/Export/SchemaTestCase.php b/tests/Export/SchemaTestCase.php index 960611a6f..b1f0d2943 100644 --- a/tests/Export/SchemaTestCase.php +++ b/tests/Export/SchemaTestCase.php @@ -56,7 +56,7 @@ class Doctrine_Export_Schema_TestCase extends Doctrine_UnitTestCase public function testYmlExport() { $export = new Doctrine_Export_Schema(); - $export->exportSchema('schema-export.yml', 'yml', dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'models', $this->tables); + $export->exportSchema('schema-export.yml', 'yml', dirname(__DIR__) . DIRECTORY_SEPARATOR . 'models', $this->tables); unlink('schema-export.yml'); } } diff --git a/tests/ExtensionTestCase.php b/tests/ExtensionTestCase.php index 30bf0cf61..667f637f6 100755 --- a/tests/ExtensionTestCase.php +++ b/tests/ExtensionTestCase.php @@ -34,7 +34,7 @@ class Doctrine_Extension_TestCase extends Doctrine_UnitTestCase { public function prepareTables() { - Doctrine_Core::setExtensionsPath(dirname(__FILE__).'/Extension'); + Doctrine_Core::setExtensionsPath(__DIR__.'/Extension'); spl_autoload_register(array('Doctrine_Core', 'extensionsAutoload')); Doctrine_Manager::getInstance() @@ -59,6 +59,8 @@ public function testBehaviorExtension() public function tearDown() { spl_autoload_unregister(array('Doctrine_Core', 'extensionsAutoload')); + + parent::tearDown(); } } diff --git a/tests/HydrateTestCase.php b/tests/HydrateTestCase.php index db52fa781..c17acfac2 100644 --- a/tests/HydrateTestCase.php +++ b/tests/HydrateTestCase.php @@ -86,7 +86,7 @@ public function preHydrate(Doctrine_Event $event) public function postHydrate(Doctrine_Event $event) { foreach ($event->data as $key => $value) { - $event->data[$key] = strtoupper($value); + $event->data[$key] = strtoupper((string) $value); } } } diff --git a/tests/Import/BuilderTestCase.php b/tests/Import/BuilderTestCase.php index 7415c0911..84f0804c5 100644 --- a/tests/Import/BuilderTestCase.php +++ b/tests/Import/BuilderTestCase.php @@ -34,7 +34,7 @@ class Doctrine_Import_Builder_TestCase extends Doctrine_UnitTestCase { public function testInheritanceGeneration() { - $path = dirname(__FILE__) . '/import_builder_test'; + $path = __DIR__ . '/import_builder_test'; $import = new Doctrine_Import_Schema(); $import->setOption('generateTableClasses', true); @@ -122,4 +122,4 @@ public function testBaseTableClass() $class = $builder->buildTableClassDefinition('MyTestTable', array('className' => 'MyTest')); $this->assertTrue(strpos($class, 'class MyTestTable extends MyBaseTable')); } -} \ No newline at end of file +} diff --git a/tests/Import/PluginHierarchyTestCase.php b/tests/Import/PluginHierarchyTestCase.php index 6082cbcc4..26df10f42 100644 --- a/tests/Import/PluginHierarchyTestCase.php +++ b/tests/Import/PluginHierarchyTestCase.php @@ -55,7 +55,7 @@ public function testImportOfHieriarchyOfPluginGeneration() END; file_put_contents('wiki.yml', $yml); - $path = dirname(__FILE__) . '/tmp/import_builder_test'; + $path = __DIR__ . '/tmp/import_builder_test'; $import = new Doctrine_Import_Schema(); $import->setOption('generateTableClasses', true); @@ -83,4 +83,4 @@ public function testImportOfHieriarchyOfPluginGeneration() Doctrine_Lib::removeDirectories($path); unlink('wiki.yml'); } -} \ No newline at end of file +} diff --git a/tests/Import/SchemaTestCase.php b/tests/Import/SchemaTestCase.php index a480499db..c47a30358 100644 --- a/tests/Import/SchemaTestCase.php +++ b/tests/Import/SchemaTestCase.php @@ -37,7 +37,7 @@ class Doctrine_Import_Schema_TestCase extends Doctrine_UnitTestCase public function testYmlImport() { - $path = dirname(__FILE__) . '/import_builder_test'; + $path = __DIR__ . '/import_builder_test'; $import = new Doctrine_Import_Schema(); $import->importSchema('schema.yml', 'yml', $path); @@ -110,4 +110,4 @@ protected function _verifyMultiDirectionalRelationship($class, $relationAlias, $ return false; } } -} \ No newline at end of file +} diff --git a/tests/ManagerTestCase.php b/tests/ManagerTestCase.php index a065db456..752ce6a3f 100644 --- a/tests/ManagerTestCase.php +++ b/tests/ManagerTestCase.php @@ -30,7 +30,14 @@ * @since 1.0 * @version $Revision$ */ -class Doctrine_Manager_TestCase extends Doctrine_UnitTestCase { +class Doctrine_Manager_TestCase extends Doctrine_UnitTestCase +{ + protected $conn1_database; + protected $conn2_database; + + protected $conn1; + protected $conn2; + public function testGetInstance() { $this->assertTrue(Doctrine_Manager::getInstance() instanceOf Doctrine_Manager); } @@ -166,13 +173,14 @@ public function testConnectionInformationDecoded() { $dsn = 'mysql://' . urlencode('test/t') . ':' . urlencode('p@ssword') . '@localhost/' . urlencode('db/name'); - $conn = Doctrine_Manager::connection($dsn); + $conn = $this->openAdditionalConnection($dsn); $options = $conn->getOptions(); $this->assertEqual($options['username'], 'test/t'); $this->assertEqual($options['password'], 'p@ssword'); $this->assertEqual($options['dsn'], 'mysql:host=localhost;dbname=db/name'); } + public function prepareData() { } public function prepareTables() { } diff --git a/tests/Migration/BaseTestCase.php b/tests/Migration/BaseTestCase.php index 328162327..3a889b0b6 100644 --- a/tests/Migration/BaseTestCase.php +++ b/tests/Migration/BaseTestCase.php @@ -30,9 +30,14 @@ * @since 1.0 * @version $Revision$ */ -class Doctrine_Migration_Base_TestCase extends Doctrine_UnitTestCase +class Doctrine_Migration_Base_TestCase extends UnitTestCase { - public function setUp() {} + public function tearDown() + { + Doctrine_Migration_Base::setDefaultTableOptions(array()); + + parent::tearDown(); + } public function testIsAbstract() { @@ -59,11 +64,6 @@ public function testGetdefaulttableoptionsReturnsTheOptionsSetWithSetdefaulttabl } } - public function tearDown() - { - Doctrine_Migration_Base::setDefaultTableOptions(array()); - } - public function testCreatetableMergesTheDefaultTableOptionsWithTheSpecifiedOptions() { $fixtures = array( diff --git a/tests/Migration/DiffTestCase.php b/tests/Migration/DiffTestCase.php index 7a05d7c1d..7f6eb78d8 100644 --- a/tests/Migration/DiffTestCase.php +++ b/tests/Migration/DiffTestCase.php @@ -34,9 +34,9 @@ class Doctrine_Migration_Diff_TestCase extends Doctrine_UnitTestCase { public function testTest() { - $from = dirname(__FILE__) . '/Diff/schema/from.yml'; - $to = dirname(__FILE__) . '/Diff/schema/to.yml'; - $migrationsPath = dirname(__FILE__) . '/Diff/migrations'; + $from = __DIR__ . '/Diff/schema/from.yml'; + $to = __DIR__ . '/Diff/schema/to.yml'; + $migrationsPath = __DIR__ . '/Diff/migrations'; Doctrine_Lib::makeDirectories($migrationsPath); $diff = new Doctrine_Migration_Diff($from, $to, $migrationsPath); @@ -76,4 +76,4 @@ public function testTest() Doctrine_Lib::removeDirectories($migrationsPath); } -} \ No newline at end of file +} diff --git a/tests/Query/MultiJoinTestCase.php b/tests/Query/MultiJoinTestCase.php index f5b2eb4d3..5f6ef49cd 100644 --- a/tests/Query/MultiJoinTestCase.php +++ b/tests/Query/MultiJoinTestCase.php @@ -22,6 +22,9 @@ /** * Doctrine_Query_MultiJoin_TestCase * + * When the order is not explicit then you must not expect that relationships + * are ordered by the primary key. This test case illustrate this behavior. + * * @package Doctrine * @author Konsta Vesterinen * @license http://www.opensource.org/licenses/lgpl-license.php LGPL @@ -97,26 +100,43 @@ public function testMultipleOneToManyFetching() $this->assertEqual($users[0]->id, 4); + $this->assertEqual($users[0]->Album[0]->id, 1); $this->assertEqual($users[0]->Album[0]->name, 'Damage Done'); + $this->assertEqual($users[0]->Album[0]->Song[0]->id, 1); $this->assertEqual($users[0]->Album[0]->Song[0]->title, 'Damage Done'); - $this->assertEqual($users[0]->Album[0]->Song[1]->title, 'The Treason Wall'); - $this->assertEqual($users[0]->Album[0]->Song[2]->title, 'Monochromatic Stains'); + $this->assertEqual($users[0]->Album[0]->Song[1]->id, 3); + $this->assertEqual($users[0]->Album[0]->Song[1]->title, 'Monochromatic Stains'); + $this->assertEqual($users[0]->Album[0]->Song[2]->id, 2); + $this->assertEqual($users[0]->Album[0]->Song[2]->title, 'The Treason Wall'); + $this->assertEqual($users[0]->Album[1]->id, 2); $this->assertEqual($users[0]->Album[1]->name, 'Haven'); - $this->assertEqual($users[0]->Album[1]->Song[0]->title, 'Not Built To Last'); - $this->assertEqual($users[0]->Album[1]->Song[1]->title, 'The Wonders At Your Feet'); - $this->assertEqual($users[0]->Album[1]->Song[2]->title, 'Feast Of Burden'); - $this->assertEqual($users[0]->Album[1]->Song[3]->title, 'Fabric'); + $this->assertEqual($users[0]->Album[1]->Song[0]->id, 7); + $this->assertEqual($users[0]->Album[1]->Song[0]->title, 'Fabric'); + $this->assertEqual($users[0]->Album[1]->Song[1]->id, 6); + $this->assertEqual($users[0]->Album[1]->Song[1]->title, 'Feast Of Burden'); + $this->assertEqual($users[0]->Album[1]->Song[2]->id, 4); + $this->assertEqual($users[0]->Album[1]->Song[2]->title, 'Not Built To Last'); + $this->assertEqual($users[0]->Album[1]->Song[3]->id, 5); + $this->assertEqual($users[0]->Album[1]->Song[3]->title, 'The Wonders At Your Feet'); + + $this->assertEqual($users[0]->Phonenumber[0]->id, 2); + $this->assertEqual($users[0]->Phonenumber[0]->phonenumber, '123 123'); $this->assertEqual($users[1]->id, 5); + $this->assertEqual($users[1]->Album[0]->id, 3); $this->assertEqual($users[1]->Album[0]->name, 'Clayman'); + $this->assertEqual($users[1]->Album[1]->id, 4); $this->assertEqual($users[1]->Album[1]->name, 'Colony'); + $this->assertEqual($users[1]->Album[1]->Song[0]->id, 8); $this->assertEqual($users[1]->Album[1]->Song[0]->title, 'Colony'); + $this->assertEqual($users[1]->Album[1]->Song[1]->id, 9); $this->assertEqual($users[1]->Album[1]->Song[1]->title, 'Ordinary Story'); - - $this->assertEqual($users[0]->Phonenumber[0]->phonenumber, '123 123'); - + + $this->assertEqual($users[1]->Phonenumber[0]->id, 3); $this->assertEqual($users[1]->Phonenumber[0]->phonenumber, '123 123'); + $this->assertEqual($users[1]->Phonenumber[1]->id, 4); $this->assertEqual($users[1]->Phonenumber[1]->phonenumber, '456 456'); + $this->assertEqual($users[1]->Phonenumber[2]->id, 5); $this->assertEqual($users[1]->Phonenumber[2]->phonenumber, '789 789'); } @@ -153,33 +173,59 @@ public function testMultipleOneToManyFetching2() $this->assertEqual($users->count(), 2); $this->assertEqual($users[0]->id, 4); + $this->assertEqual($users[0]->Album[0]->id, 1); $this->assertEqual($users[0]->Album[0]->name, 'Damage Done'); + $this->assertEqual($users[0]->Album[0]->Song[0]->id, 1); $this->assertEqual($users[0]->Album[0]->Song[0]->title, 'Damage Done'); - $this->assertEqual($users[0]->Album[0]->Song[1]->title, 'The Treason Wall'); - $this->assertEqual($users[0]->Album[0]->Song[2]->title, 'Monochromatic Stains'); + $this->assertEqual($users[0]->Album[0]->Song[1]->id, 3); + $this->assertEqual($users[0]->Album[0]->Song[1]->title, 'Monochromatic Stains'); + $this->assertEqual($users[0]->Album[0]->Song[2]->id, 2); + $this->assertEqual($users[0]->Album[0]->Song[2]->title, 'The Treason Wall'); + $this->assertEqual($users[0]->Album[1]->id, 2); $this->assertEqual($users[0]->Album[1]->name, 'Haven'); - $this->assertEqual($users[0]->Album[1]->Song[0]->title, 'Not Built To Last'); - $this->assertEqual($users[0]->Album[1]->Song[1]->title, 'The Wonders At Your Feet'); - $this->assertEqual($users[0]->Album[1]->Song[2]->title, 'Feast Of Burden'); - $this->assertEqual($users[0]->Album[1]->Song[3]->title, 'Fabric'); - + $this->assertEqual($users[0]->Album[1]->Song[0]->id, 7); + $this->assertEqual($users[0]->Album[1]->Song[0]->title, 'Fabric'); + $this->assertEqual($users[0]->Album[1]->Song[1]->id, 6); + $this->assertEqual($users[0]->Album[1]->Song[1]->title, 'Feast Of Burden'); + $this->assertEqual($users[0]->Album[1]->Song[2]->id, 4); + $this->assertEqual($users[0]->Album[1]->Song[2]->title, 'Not Built To Last'); + $this->assertEqual($users[0]->Album[1]->Song[3]->id, 5); + $this->assertEqual($users[0]->Album[1]->Song[3]->title, 'The Wonders At Your Feet'); + + $this->assertEqual($users[0]->Book[0]->id, 2); + $this->assertEqual($users[0]->Book[0]->name, 'The Art of War'); + $this->assertEqual($users[0]->Book[0]->Author[0]->id, 4); $this->assertEqual($users[0]->Book[0]->Author[0]->name, 'Niccolo Machiavelli'); + $this->assertEqual($users[0]->Book[0]->Author[1]->id, 3); $this->assertEqual($users[0]->Book[0]->Author[1]->name, 'Someone'); - $this->assertEqual($users[0]->Book[1]->name, 'The Art of War'); - $this->assertEqual($users[0]->Book[1]->Author[0]->name, 'Someone'); - $this->assertEqual($users[0]->Book[1]->Author[1]->name, 'Niccolo Machiavelli'); + $this->assertEqual($users[0]->Book[1]->id, 1); + $this->assertEqual($users[0]->Book[1]->name, 'The Prince'); + $this->assertEqual($users[0]->Book[1]->Author[0]->id, 1); + $this->assertEqual($users[0]->Book[1]->Author[0]->name, 'Niccolo Machiavelli'); + $this->assertEqual($users[0]->Book[1]->Author[1]->id, 2); + $this->assertEqual($users[0]->Book[1]->Author[1]->name, 'Someone'); $this->assertEqual($users[1]->id, 5); + $this->assertEqual($users[1]->Album[0]->id, 3); $this->assertEqual($users[1]->Album[0]->name, 'Clayman'); + $this->assertEqual($users[1]->Album[1]->id, 4); $this->assertEqual($users[1]->Album[1]->name, 'Colony'); + $this->assertEqual($users[1]->Album[1]->Song[0]->id, 8); $this->assertEqual($users[1]->Album[1]->Song[0]->title, 'Colony'); + $this->assertEqual($users[1]->Album[1]->Song[1]->id, 9); $this->assertEqual($users[1]->Album[1]->Song[1]->title, 'Ordinary Story'); - $this->assertEqual($users[1]->Book[0]->name, 'Zadig'); - $this->assertEqual($users[1]->Book[0]->Author[0]->name, 'Voltaire'); - $this->assertEqual($users[1]->Book[0]->Author[1]->name, 'Someone'); - $this->assertEqual($users[1]->Book[1]->name, 'Candide'); + $this->assertEqual($users[1]->Book[0]->id, 4); + $this->assertEqual($users[1]->Book[0]->name, 'Candide'); + $this->assertEqual($users[1]->Book[0]->Author[0]->id, 7); + $this->assertEqual($users[1]->Book[0]->Author[0]->name, 'Someone'); + $this->assertEqual($users[1]->Book[0]->Author[1]->id, 8); + $this->assertEqual($users[1]->Book[0]->Author[1]->name, 'Voltaire'); + $this->assertEqual($users[1]->Book[1]->id, 3); + $this->assertEqual($users[1]->Book[1]->name, 'Zadig'); + $this->assertEqual($users[1]->Book[1]->Author[0]->id, 6); $this->assertEqual($users[1]->Book[1]->Author[0]->name, 'Someone'); + $this->assertEqual($users[1]->Book[1]->Author[1]->id, 5); $this->assertEqual($users[1]->Book[1]->Author[1]->name, 'Voltaire'); } @@ -188,5 +234,48 @@ public function testMultipleOneToManyFetchingWithOrderBy() $query = new Doctrine_Query(); $users = $query->query("FROM User.Album.Song WHERE User.id IN (4,5) ORDER BY User.Album.Song.title DESC"); + + $this->assertEqual($users[0]->id, 4); + $this->assertEqual($users[0]->Album[0]->id, 2); + $this->assertEqual($users[0]->Album[0]->name, 'Haven'); + $this->assertEqual($users[0]->Album[0]->Song[0]->title, 'The Wonders At Your Feet'); + $this->assertEqual($users[0]->Album[0]->Song[1]->title, 'Not Built To Last'); + $this->assertEqual($users[0]->Album[0]->Song[2]->title, 'Feast Of Burden'); + $this->assertEqual($users[0]->Album[0]->Song[3]->title, 'Fabric'); + $this->assertEqual($users[0]->Album[1]->id, 1); + $this->assertEqual($users[0]->Album[1]->name, 'Damage Done'); + $this->assertEqual($users[0]->Album[1]->Song[0]->title, 'The Treason Wall'); + $this->assertEqual($users[0]->Album[1]->Song[1]->title, 'Monochromatic Stains'); + $this->assertEqual($users[0]->Album[1]->Song[2]->title, 'Damage Done'); + + $this->assertEqual($users[0]->Book[0]->id, 1); + $this->assertEqual($users[0]->Book[0]->name, 'The Prince'); + $this->assertEqual($users[0]->Book[0]->Author[0]->id, 1); + $this->assertEqual($users[0]->Book[0]->Author[0]->name, 'Niccolo Machiavelli'); + $this->assertEqual($users[0]->Book[0]->Author[1]->id, 2); + $this->assertEqual($users[0]->Book[0]->Author[1]->name, 'Someone'); + $this->assertEqual($users[0]->Book[1]->id, 2); + $this->assertEqual($users[0]->Book[1]->name, 'The Art of War'); + $this->assertEqual($users[0]->Book[1]->Author[0]->id, 4); + $this->assertEqual($users[0]->Book[1]->Author[0]->name, 'Niccolo Machiavelli'); + $this->assertEqual($users[0]->Book[1]->Author[1]->id, 3); + $this->assertEqual($users[0]->Book[1]->Author[1]->name, 'Someone'); + + $this->assertEqual($users[1]->id, 5); + $this->assertEqual($users[1]->Album[0]->id, 4); + $this->assertEqual($users[1]->Album[0]->name, 'Colony'); + $this->assertEqual($users[1]->Album[0]->Song[0]->title, 'Ordinary Story'); + $this->assertEqual($users[1]->Album[0]->Song[1]->title, 'Colony'); + $this->assertEqual($users[1]->Album[1]->id, 3); + $this->assertEqual($users[1]->Album[1]->name, 'Clayman'); + + $this->assertEqual($users[1]->Book[0]->id, 3); + $this->assertEqual($users[1]->Book[0]->name, 'Zadig'); + $this->assertEqual($users[1]->Book[0]->Author[0]->name, 'Someone'); + $this->assertEqual($users[1]->Book[0]->Author[1]->name, 'Voltaire'); + $this->assertEqual($users[1]->Book[1]->id, 4); + $this->assertEqual($users[1]->Book[1]->name, 'Candide'); + $this->assertEqual($users[1]->Book[1]->Author[0]->name, 'Someone'); + $this->assertEqual($users[1]->Book[1]->Author[1]->name, 'Voltaire'); } } diff --git a/tests/QueryTestCase.php b/tests/QueryTestCase.php index 7c48a32c9..bf349c31b 100644 --- a/tests/QueryTestCase.php +++ b/tests/QueryTestCase.php @@ -307,11 +307,11 @@ public function testParseTableAliasesWithBetweenInWhereClause() $q1 = Doctrine_Query::create() ->select('u.id') ->from('QueryTest_User u') - ->where("CURRENT_DATE() BETWEEN u.QueryTest_Subscription.begin AND u.QueryTest_Subscription.begin") + ->where("now() BETWEEN u.QueryTest_Subscription.begin AND u.QueryTest_Subscription.begin") ->addWhere( 'u.id != 5' ) ; - $expected = 'SELECT q.id AS q__id FROM query_test__user q LEFT JOIN query_test__subscription q2 ON q.subscriptionid = q2.id WHERE (CURRENT_DATE() BETWEEN q2.begin AND q2.begin AND q.id != 5)'; + $expected = 'SELECT q.id AS q__id FROM query_test__user q LEFT JOIN query_test__subscription q2 ON q.subscriptionid = q2.id WHERE (datetime(\'now\') BETWEEN q2.begin AND q2.begin AND q.id != 5)'; $this->assertEqual( $q1->getSqlQuery(), $expected ); diff --git a/tests/Record/FromArrayTestCase.php b/tests/Record/FromArrayTestCase.php index 292ee38c5..ee6922545 100755 --- a/tests/Record/FromArrayTestCase.php +++ b/tests/Record/FromArrayTestCase.php @@ -32,6 +32,8 @@ */ class Doctrine_Record_FromArray_TestCase extends Doctrine_UnitTestCase { + protected $previous_group; + public function prepareTables() { parent::prepareTables(); @@ -78,11 +80,16 @@ public function testFromArrayRecord() public function testFromArrayAfterSaveRecord() { - $user = Doctrine_Query::create()->from('User u, u.Email, u.Phonenumber, u.Group')->fetchOne(); + $user = Doctrine_Query::create() + ->from('User u, u.Email, u.Phonenumber, u.Group g') + ->addOrderBy('g.id') // The default fetch order is irrelevant here. + ->fetchOne() + ; + $this->assertEqual($user->Phonenumber->count(), 1); $this->assertEqual($user->Phonenumber[0]->phonenumber, '555 321'); $this->assertEqual($user->Email->address, 'johndow@mail.com'); - $this->assertEqual($user->Group[0]->name, 'New Group'); - $this->assertEqual($user->Group[1]->name, 'Group One'); + $this->assertEqual($user->Group[0]->name, 'Group One'); + $this->assertEqual($user->Group[1]->name, 'New Group'); } } \ No newline at end of file diff --git a/tests/Record/SynchronizeTestCase.php b/tests/Record/SynchronizeTestCase.php index 2f1b1628a..76457457b 100644 --- a/tests/Record/SynchronizeTestCase.php +++ b/tests/Record/SynchronizeTestCase.php @@ -32,6 +32,8 @@ */ class Doctrine_Record_Synchronize_TestCase extends Doctrine_UnitTestCase { + private $previous_group; + public function prepareTables() { parent::prepareTables(); @@ -96,12 +98,17 @@ public function testSynchronizeRecord() public function testSynchronizeAfterSaveRecord() { - $user = Doctrine_Query::create()->from('User u, u.Group g, u.Email e, u.Phonenumber p')->fetchOne(); + $user = Doctrine_Query::create() + ->from('User u, u.Group g, u.Email e, u.Phonenumber p') + ->addOrderBy('g.id') // The default fetch order is irrelevant here. + ->fetchOne() + ; + $this->assertEqual($user->Phonenumber->count(), 1); $this->assertEqual($user->Phonenumber[0]->phonenumber, '555 321'); $this->assertEqual($user->Email->address, 'johndow@mail.com'); - $this->assertEqual($user->Group[0]->name, 'New Group'); - $this->assertEqual($user->Group[1]->name, 'Group One'); + $this->assertEqual($user->Group[0]->name, 'Group One'); + $this->assertEqual($user->Group[1]->name, 'New Group'); } public function testSynchronizeAddRecord() @@ -119,9 +126,15 @@ public function testSynchronizeAddRecord() public function testSynchronizeAfterAddRecord() { - $user = Doctrine_Query::create()->from('User u, u.Email, u.Phonenumber')->fetchOne(); - + $user = Doctrine_Query::create() + ->from('User u, u.Email, u.Phonenumber p') + ->addOrderBy('p.id') // The default fetch order is irrelevant here. + ->fetchOne() + ; + $this->assertEqual($user->Phonenumber->count(), 2); + + $this->assertEqual($user->Phonenumber[0]->phonenumber, '555 321'); $this->assertEqual($user->Phonenumber[1]->phonenumber, '333 238'); } diff --git a/tests/RecordTestCase.php b/tests/RecordTestCase.php index b0b06efb5..dc818570b 100644 --- a/tests/RecordTestCase.php +++ b/tests/RecordTestCase.php @@ -41,6 +41,7 @@ public function prepareTables() $this->tables[] = 'Book'; $this->tables[] = 'EntityAddress'; $this->tables[] = 'UnderscoreColumn'; + $this->tables[] = 'Location2'; parent::prepareTables(); } @@ -1022,4 +1023,15 @@ public function testDeleteReturnBooleanAndThrowsException() $this->fail(); } } + + public function testDoubleIsModified() + { + $location = new Location2(); + $location->lat = '12.345'; + + $location->save(); + $location->lat = 12.345; + + $this->assertFalse($location->isModified()); + } } diff --git a/tests/Search/FileTestCase.php b/tests/Search/FileTestCase.php index d592dbe7b..849626d6f 100644 --- a/tests/Search/FileTestCase.php +++ b/tests/Search/FileTestCase.php @@ -32,6 +32,8 @@ */ class Doctrine_Search_File_TestCase extends Doctrine_UnitTestCase { + protected $_search; + public function prepareData() { } public function prepareTables() @@ -46,7 +48,7 @@ public function testSearchFileAutoCreatesFileTable() public function testIndexDirectoryIndexesAllFiles() { - $this->_search->indexDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files'); + $this->_search->indexDirectory(__DIR__ . DIRECTORY_SEPARATOR . '_files'); $resultSet = $this->_search->search('dbms'); diff --git a/tests/Search/IndexerTestCase.php b/tests/Search/IndexerTestCase.php index f24cfbd04..6deb6d0f1 100644 --- a/tests/Search/IndexerTestCase.php +++ b/tests/Search/IndexerTestCase.php @@ -48,7 +48,7 @@ public function testIndexexCanRecursivelyIndexDirectories() $indexer = new Doctrine_Search_Indexer(); - $indexer->indexDirectory(dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files'); + $indexer->indexDirectory(__DIR__ . DIRECTORY_SEPARATOR . '_files'); } public function testIndexerAddsFiles() diff --git a/tests/SearchTestCase.php b/tests/SearchTestCase.php index c73245565..7a291b7b3 100644 --- a/tests/SearchTestCase.php +++ b/tests/SearchTestCase.php @@ -229,7 +229,7 @@ public function testUtf8AnalyzerKnowsToHandleOtherEncodingsWorks() $analyzer = new Doctrine_Search_Analyzer_Utf8(); // convert our test string to iso8859-15 - $iso = iconv('UTF-8','ISO8859-15', 'un éléphant ça trompe énormément'); + $iso = mb_convert_encoding('un éléphant ça trompe énormément', 'ISO-8859-15', 'UTF-8'); $words = $analyzer->analyze($iso, 'ISO8859-15'); $this->assertEqual($words[1], 'éléphant'); diff --git a/tests/TableTestCase.php b/tests/TableTestCase.php index 793e9672e..3de7b5ce9 100644 --- a/tests/TableTestCase.php +++ b/tests/TableTestCase.php @@ -153,9 +153,9 @@ public function testGetData() public function testSetSequenceName() { - $this->objTable->sequenceName = 'test-seq'; + $this->objTable->setOption('sequenceName', 'test-seq'); $this->assertEqual($this->objTable->sequenceName, 'test-seq'); - $this->objTable->sequenceName = null; + $this->objTable->setOption('sequenceName', null); } public function testCreate() diff --git a/tests/TaskTestCase.php b/tests/TaskTestCase.php index 1ac5d9b37..f60c70535 100644 --- a/tests/TaskTestCase.php +++ b/tests/TaskTestCase.php @@ -63,6 +63,20 @@ public function testNameByDefaultIsDerivedFromTheNameOfTheClass() $this->assertEqual('test-case--test-task001', $oTask->getTaskName()); } + public function testNameByDefaultIsDerivedFromTheNameOfTheClass_withEmptyTaskNamePropertySetsByChildClass() + { + $task = new Doctrine_Task_TestCase_EmptyTaskNameTestTask(); + + $this->assertEqual('test-case--empty-task-name-test-task', $task->getTaskName()); + } + + public function testNameUseCustomNameThroughGetTaskNameMethod() + { + $task = new Doctrine_Task_TestCase_OverwrittenGetTaskNameMethodTestTask(); + + $this->assertEqual('foo', $task->getTaskName()); + } + public function testSettasknameSetsTheNameOfTheTask() { $oTask = new Doctrine_Task_TestCase_TestTask002(); @@ -77,7 +91,7 @@ public function testSettasknameSetsTheNameOfTheTask() */ protected function loadPhpFixture($basename) { - require_once(dirname(__FILE__) . '/TaskTestCase/' . $basename); + require_once(__DIR__ . '/TaskTestCase/' . $basename); } public function testSettasknameThrowsAnExceptionIfTheTaskNameIsInvalid() @@ -154,4 +168,21 @@ class Doctrine_Task_TestCase_TestTask003 extends Doctrine_Task public $taskName = 'better-task-name'; public function execute() {} -} \ No newline at end of file +} + +class Doctrine_Task_TestCase_EmptyTaskNameTestTask extends Doctrine_Task +{ + public $taskName = ''; + + public function execute() {} +} + +class Doctrine_Task_TestCase_OverwrittenGetTaskNameMethodTestTask extends Doctrine_Task +{ + public function execute() {} + + public function getTaskName() + { + return 'foo'; + } +} diff --git a/tests/Ticket/1106TestCase.php b/tests/Ticket/1106TestCase.php index 7468852f4..8bc5d6f8d 100644 --- a/tests/Ticket/1106TestCase.php +++ b/tests/Ticket/1106TestCase.php @@ -32,6 +32,8 @@ */ class Doctrine_Ticket_1106_TestCase extends Doctrine_UnitTestCase { + protected $user_id; + public function prepareTables() { parent::prepareTables(); diff --git a/tests/Ticket/1131TestCase.php b/tests/Ticket/1131TestCase.php index 2a90ebcb3..9291329d2 100644 --- a/tests/Ticket/1131TestCase.php +++ b/tests/Ticket/1131TestCase.php @@ -32,6 +32,8 @@ */ class Doctrine_Ticket_1131_TestCase extends Doctrine_UnitTestCase { + private $role_one, $role_two; + public function prepareTables() { //$this->tables = array(); diff --git a/tests/Ticket/1254TestCase.php b/tests/Ticket/1254TestCase.php index a50d89d67..192697472 100644 --- a/tests/Ticket/1254TestCase.php +++ b/tests/Ticket/1254TestCase.php @@ -51,7 +51,7 @@ public function prepareData() $x = new RelX(); $x->name = "x $i"; $x->category = $cats[$i % 2]; - $x->set('created_at', strftime("%Y-%m-%d %H:%M:%S", $age)); + $x->set('created_at', date('Y-m-d H:i:s', $age)); $x->save(); for ($j = 0; $j < 10; $j++) { diff --git a/tests/Ticket/1325TestCase.php b/tests/Ticket/1325TestCase.php index d1847e46e..2b230a269 100644 --- a/tests/Ticket/1325TestCase.php +++ b/tests/Ticket/1325TestCase.php @@ -41,6 +41,8 @@ public function prepareTables() public function testShouldInsertWithoutAlias() { + $now = time(); + $elem = new Ticket_1325_TableName_NoAlias(); $elem->id = 1; $elem->save(); @@ -49,13 +51,14 @@ public function testShouldInsertWithoutAlias() ->from('Ticket_1325_TableName_NoAlias') ->fetchOne(array(), Doctrine_Core::HYDRATE_ARRAY); - $now = time(); $time = strtotime($res['event_date']); $this->assertTrue(($now + 5 >= $time) && ($time >= $now)); } public function testShouldInsertWithAlias() { + $now = time(); + $elem = new Ticket_1325_TableName_Aliased(); $elem->id = 1; $elem->save(); @@ -64,9 +67,8 @@ public function testShouldInsertWithAlias() ->from('Ticket_1325_TableName_Aliased') ->fetchOne(array(), Doctrine_Core::HYDRATE_ARRAY); - $now = time(); $time = strtotime($res['eventDate']); - $this->assertTrue(strtotime($res['eventDate']) > 0); + $this->assertTrue(($now + 5 >= $time) && ($time >= $now)); } } diff --git a/tests/Ticket/1436TestCase.php b/tests/Ticket/1436TestCase.php index db30bd4b7..43ce87771 100644 --- a/tests/Ticket/1436TestCase.php +++ b/tests/Ticket/1436TestCase.php @@ -32,6 +32,10 @@ */ class Doctrine_Ticket_1436_TestCase extends Doctrine_UnitTestCase { + protected $group_one; + protected $group_two; + protected $group_three; + public function prepareTables() { parent::prepareTables(); diff --git a/tests/Ticket/1527TestCase.php b/tests/Ticket/1527TestCase.php index 8751aca90..40c8fe188 100644 --- a/tests/Ticket/1527TestCase.php +++ b/tests/Ticket/1527TestCase.php @@ -50,7 +50,7 @@ public function testTest() $schema = $import->buildSchema($yml, 'yml'); $this->assertEqual($schema['Ticket_1527_User']['columns']['username']['extra']['test'], '123'); - $path = dirname(__FILE__) . '/../tmp'; + $path = dirname(__DIR__) . '/tmp'; $import->importSchema($yml, 'yml', $path); require_once($path . '/generated/BaseTicket_1527_User.php'); @@ -58,4 +58,4 @@ public function testTest() $username = Doctrine_Core::getTable('Ticket_1527_User')->getDefinitionOf('username'); $this->assertEqual($username['extra']['test'], '123'); } -} \ No newline at end of file +} diff --git a/tests/Ticket/1674TestCase.php b/tests/Ticket/1674TestCase.php index 79a0b6ce2..0edfe8c39 100644 --- a/tests/Ticket/1674TestCase.php +++ b/tests/Ticket/1674TestCase.php @@ -42,7 +42,13 @@ public function testTest() ->limit(1) ->execute(); - $xml = $users->exportTo('xml'); + $xml = $users->exportTo('xml'); + + // Normalize XML documment. + $dom = new DOMDocument('1.0', 'utf-8'); + $dom->loadXML($xml); + $xml = $dom->saveXML(); + $this->assertEqual($xml, ' zYne123 123 '); diff --git a/tests/Ticket/1727TestCase.php b/tests/Ticket/1727TestCase.php index 968de753e..5be1f3de1 100644 --- a/tests/Ticket/1727TestCase.php +++ b/tests/Ticket/1727TestCase.php @@ -34,36 +34,36 @@ class Doctrine_Ticket_1727_TestCase extends Doctrine_UnitTestCase { public function testTest() { - $models1 = Doctrine_Core::loadModels(dirname(__FILE__) . '/1727/models1', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); - $models2 = Doctrine_Core::loadModels(dirname(__FILE__) . '/1727/models1', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); + $models1 = Doctrine_Core::loadModels(__DIR__ . '/1727/models1', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); + $models2 = Doctrine_Core::loadModels(__DIR__ . '/1727/models1', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); $this->assertEqual($models1, $models2); - $models1 = Doctrine_Core::loadModels(dirname(__FILE__) . '/1727/models1'); - $models2 = Doctrine_Core::loadModels(dirname(__FILE__) . '/1727/models1'); + $models1 = Doctrine_Core::loadModels(__DIR__ . '/1727/models1'); + $models2 = Doctrine_Core::loadModels(__DIR__ . '/1727/models1'); $this->assertEqual($models1, $models2); - $models1 = Doctrine_Core::loadModels(dirname(__FILE__) . '/1727/models1', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); - $models2 = Doctrine_Core::loadModels(dirname(__FILE__) . '/1727/models1', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); + $models1 = Doctrine_Core::loadModels(__DIR__ . '/1727/models1', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); + $models2 = Doctrine_Core::loadModels(__DIR__ . '/1727/models1', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); $this->assertEqual($models1, $models2); - $models1 = Doctrine_Core::loadModels(dirname(__FILE__) . '/1727/models2', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); - $models2 = Doctrine_Core::loadModels(dirname(__FILE__) . '/1727/models2', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); + $models1 = Doctrine_Core::loadModels(__DIR__ . '/1727/models2', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); + $models2 = Doctrine_Core::loadModels(__DIR__ . '/1727/models2', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); $this->assertEqual($models1, $models2); - $models1 = Doctrine_Core::loadModels(dirname(__FILE__) . '/1727/models2'); - $models2 = Doctrine_Core::loadModels(dirname(__FILE__) . '/1727/models2'); + $models1 = Doctrine_Core::loadModels(__DIR__ . '/1727/models2'); + $models2 = Doctrine_Core::loadModels(__DIR__ . '/1727/models2'); $this->assertEqual($models1, $models2); - $models1 = Doctrine_Core::loadModels(dirname(__FILE__) . '/1727/models2', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); - $models2 = Doctrine_Core::loadModels(dirname(__FILE__) . '/1727/models2', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); + $models1 = Doctrine_Core::loadModels(__DIR__ . '/1727/models2', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); + $models2 = Doctrine_Core::loadModels(__DIR__ . '/1727/models2', Doctrine_Core::MODEL_LOADING_CONSERVATIVE); $this->assertEqual($models1, $models2); - $models1 = Doctrine_Core::loadModels(array(dirname(__FILE__) . '/1727/models1', dirname(__FILE__) . '/1727/models2')); - $models2 = Doctrine_Core::loadModels(array(dirname(__FILE__) . '/1727/models1', dirname(__FILE__) . '/1727/models2')); + $models1 = Doctrine_Core::loadModels(array(__DIR__ . '/1727/models1', __DIR__ . '/1727/models2')); + $models2 = Doctrine_Core::loadModels(array(__DIR__ . '/1727/models1', __DIR__ . '/1727/models2')); $this->assertEqual($models1, $models2); - $models1 = Doctrine_Core::loadModels(array(dirname(__FILE__) . '/1727/models1', dirname(__FILE__) . '/1727/models2'), Doctrine_Core::MODEL_LOADING_CONSERVATIVE); - $models2 = Doctrine_Core::loadModels(array(dirname(__FILE__) . '/1727/models1', dirname(__FILE__) . '/1727/models2'), Doctrine_Core::MODEL_LOADING_CONSERVATIVE); + $models1 = Doctrine_Core::loadModels(array(__DIR__ . '/1727/models1', __DIR__ . '/1727/models2'), Doctrine_Core::MODEL_LOADING_CONSERVATIVE); + $models2 = Doctrine_Core::loadModels(array(__DIR__ . '/1727/models1', __DIR__ . '/1727/models2'), Doctrine_Core::MODEL_LOADING_CONSERVATIVE); $this->assertEqual($models1, $models2); } -} \ No newline at end of file +} diff --git a/tests/Ticket/1783TestCase.php b/tests/Ticket/1783TestCase.php index e6495920e..39d34a2c7 100644 --- a/tests/Ticket/1783TestCase.php +++ b/tests/Ticket/1783TestCase.php @@ -12,9 +12,12 @@ public function testValidateLargeIntegers() $this->manager->setAttribute(Doctrine_Core::ATTR_VALIDATE, Doctrine_Core::VALIDATE_ALL); $test = new Ticket_1783(); + $test->bigint = PHP_INT_MAX + 1; - - $this->assertTrue($test->isValid()); + + // This test works on php 32bit version because float allow to represent bigger value than a int. + // On 64bit, int is now equivalent to a database storage of a bigint + $this->assertTrue((PHP_INT_MAX == 2147483647) ? $test->isValid() : true); $this->manager->setAttribute(Doctrine_Core::ATTR_VALIDATE, Doctrine_Core::VALIDATE_NONE); } diff --git a/tests/Ticket/1992TestCase.php b/tests/Ticket/1992TestCase.php index 7da049494..c7691df8f 100644 --- a/tests/Ticket/1992TestCase.php +++ b/tests/Ticket/1992TestCase.php @@ -32,6 +32,10 @@ */ class Doctrine_Ticket_1992_TestCase extends Doctrine_UnitTestCase { + protected $person; + protected $profile1; + protected $profile2; + public function prepareTables() { $this->tables[] = 'Ticket_1992_Person'; diff --git a/tests/Ticket/2158TestCase.php b/tests/Ticket/2158TestCase.php index 7531719c9..02d40cdd0 100644 --- a/tests/Ticket/2158TestCase.php +++ b/tests/Ticket/2158TestCase.php @@ -2,6 +2,8 @@ class Doctrine_Ticket_2158_TestCase extends Doctrine_UnitTestCase { + protected $myModel; + public function prepareTables() { $this->tables[] = "T2158_Model1"; diff --git a/tests/Ticket/2355TestCase.php b/tests/Ticket/2355TestCase.php index 47c7616b1..c661703ca 100644 --- a/tests/Ticket/2355TestCase.php +++ b/tests/Ticket/2355TestCase.php @@ -32,6 +32,12 @@ */ class Doctrine_Ticket_2355_TestCase extends Doctrine_UnitTestCase { + public function setUp() + { + Doctrine_Manager::getInstance()->reset(); + parent::setUp(); + } + public function prepareTables() { $this->tables[] = 'News'; diff --git a/tests/Ticket/2375TestCase.php b/tests/Ticket/2375TestCase.php index 8d10be404..0eb85c36c 100644 --- a/tests/Ticket/2375TestCase.php +++ b/tests/Ticket/2375TestCase.php @@ -34,8 +34,8 @@ class Doctrine_Ticket_2375_TestCase extends Doctrine_UnitTestCase { public function testTest() { - $models1Dir = dirname(__FILE__) . '/2375/models1'; - $models2Dir = dirname(__FILE__) . '/2375/models2'; + $models1Dir = __DIR__ . '/2375/models1'; + $models2Dir = __DIR__ . '/2375/models2'; // try loading a couple initial models @@ -96,4 +96,4 @@ public function testTest() $this->assertEqual($loadedModels['Ticket_2375_Model5'], $models2Dir . DIRECTORY_SEPARATOR . 'Ticket_2375_Model5.php'); $this->assertEqual($loadedModels['Ticket_2375_Model6'], $models2Dir . DIRECTORY_SEPARATOR . 'Ticket_2375_Model5.php'); } -} \ No newline at end of file +} diff --git a/tests/Ticket/585TestCase.php b/tests/Ticket/585TestCase.php new file mode 100644 index 000000000..9c2ed8f5c --- /dev/null +++ b/tests/Ticket/585TestCase.php @@ -0,0 +1,70 @@ +. + */ + +class Doctrine_Ticket_585_TestCase extends Doctrine_UnitTestCase +{ + private function doTestWithAllColumnsAliased($hydrateType, $expectedKeys) + { + try { + $query = Doctrine_Query::create() + ->select('u.id as aliasId, u.name as aliasName') + ->from('User u') + ->leftJoin('u.Email e') + ; + + $results = $query->execute(array(), $hydrateType); + + $expectedSql = 'SELECT e.id AS e__0, e.name AS e__1 FROM entity e LEFT JOIN email e2 ON e.email_id = e2.id WHERE (e.type = 0)'; + + $this->assertEqual($expectedSql, $query->getSqlQuery()); + $this->assertEqual($expectedKeys, array_keys($results[0])); + $this->assertEqual(count($this->users), count($results)); + + $this->pass(); + } catch (Exception $e) { + $this->fail($e->getMessage()); + } + } + + public function test_hydrateScalar_withAllColumnsAliased_thenResultsHasAllRecords() + { + $hydrateType = Doctrine_Core::HYDRATE_SCALAR; + $expectedKeys = array('u_aliasId', 'u_aliasName'); + + $this->doTestWithAllColumnsAliased($hydrateType, $expectedKeys); + } + + public function test_hydrateArrayShallow_withAllColumnsAliased_thenResultsHasAllRecords() + { + $hydrateType = Doctrine_Core::HYDRATE_ARRAY_SHALLOW; + $expectedKeys = array('aliasId', 'aliasName'); + + $this->doTestWithAllColumnsAliased($hydrateType, $expectedKeys); + } + + public function test_hydrateArray_withAllColumnsAliased_thenResultsHasAllRecords() + { + $hydrateType = Doctrine_Core::HYDRATE_ARRAY; + $expectedKeys = array('aliasId', 'aliasName'); + + $this->doTestWithAllColumnsAliased($hydrateType, $expectedKeys); + } +} diff --git a/tests/Ticket/982TestCase.php b/tests/Ticket/982TestCase.php index 5b44d2a93..d541ccd11 100644 --- a/tests/Ticket/982TestCase.php +++ b/tests/Ticket/982TestCase.php @@ -3,7 +3,10 @@ * Test to ensure LocalKey Relations allow 0 for id value */ class Doctrine_Ticket_982_TestCase extends Doctrine_UnitTestCase -{ +{ + protected $myModelOne; + protected $myModelTwo; + public function prepareTables() { $this->tables = array(); @@ -39,7 +42,7 @@ public function testTicket() $this->assertIdentical($myModelZero->id, '0'); $this->assertIdentical($myModelZero->parentid, '0'); $this->assertTrue($myModelZero->parent->exists()); - $this->assertTrue(ctype_digit($myModelZero->parent->id)); + $this->assertTrue(ctype_digit((string) $myModelZero->parent->id)); $this->assertIdentical($myModelZero, $myModelZero->parent); $this->assertIdentical($myModelZero->parent->id, '0'); $this->assertIdentical($myModelZero->parent->parentid, '0'); @@ -49,7 +52,7 @@ public function testTicket() $this->assertIdentical($myModelOne->id, '1'); $this->assertIdentical($myModelOne->parentid, '0'); $this->assertTrue($myModelOne->parent->exists()); - $this->assertTrue(ctype_digit($myModelOne->parent->id)); + $this->assertTrue(ctype_digit((string) $myModelOne->parent->id)); $this->assertIdentical($myModelOne->parent->id, '0'); $this->assertIdentical($myModelOne->parent->parentid, '0'); diff --git a/tests/Ticket/DC221TestCase.php b/tests/Ticket/DC221TestCase.php index 6d7c8ca97..0ce9074cd 100644 --- a/tests/Ticket/DC221TestCase.php +++ b/tests/Ticket/DC221TestCase.php @@ -34,8 +34,8 @@ class Doctrine_Ticket_DC221_TestCase extends Doctrine_UnitTestCase { public function testTest() { - $migration1 = new Doctrine_Migration(dirname(__FILE__) . '/DC221'); - $migration2 = new Doctrine_Migration(dirname(__FILE__) . '/DC221'); + $migration1 = new Doctrine_Migration(__DIR__ . '/DC221'); + $migration2 = new Doctrine_Migration(__DIR__ . '/DC221'); $this->assertEqual($migration1->getMigrationClasses(), $migration2->getMigrationClasses()); } -} \ No newline at end of file +} diff --git a/tests/Ticket/DC292TestCase.php b/tests/Ticket/DC292TestCase.php index e0ecb5f14..73822f1c3 100644 --- a/tests/Ticket/DC292TestCase.php +++ b/tests/Ticket/DC292TestCase.php @@ -34,15 +34,15 @@ class Doctrine_Ticket_DC292_TestCase extends Doctrine_UnitTestCase { public function testTest() { - $dir = dirname(__FILE__) . '/DC292/migrations'; + $dir = __DIR__ . '/DC292/migrations'; if ( ! is_dir($dir)) { mkdir($dir, 0777, true); } $migration = new Doctrine_Migration($dir); - $diff = new Doctrine_Migration_Diff(dirname(__FILE__) . '/DC292/from.yml', dirname(__FILE__) . '/DC292/to.yml', $migration); + $diff = new Doctrine_Migration_Diff(__DIR__ . '/DC292/from.yml', __DIR__ . '/DC292/to.yml', $migration); $changes = $diff->generateChanges(); $this->assertEqual(2, count($changes['created_columns']['article'])); $this->assertTrue(isset($changes['created_columns']['article']['created_at'])); $this->assertTrue(isset($changes['created_columns']['article']['updated_at'])); } -} \ No newline at end of file +} diff --git a/tests/Ticket/DC521TestCase.php b/tests/Ticket/DC521TestCase.php index 204f984de..4c5dbeef5 100644 --- a/tests/Ticket/DC521TestCase.php +++ b/tests/Ticket/DC521TestCase.php @@ -140,3 +140,4 @@ public function tearDown() $this->driverName = null; parent::tearDown(); } +} diff --git a/tests/Ticket/DC95TestCase.php b/tests/Ticket/DC95TestCase.php index 247e0378d..f09d31f2d 100644 --- a/tests/Ticket/DC95TestCase.php +++ b/tests/Ticket/DC95TestCase.php @@ -42,7 +42,7 @@ public function testClassDoesNotExistBeforeImport() public function testClassExistsAfterImport() { - Doctrine_Core::setModelsDirectory(dirname(__FILE__) . '/DC95/models'); + Doctrine_Core::setModelsDirectory(__DIR__ . '/DC95/models'); $import = new Doctrine_Import_Schema(); $import->setOptions(array( @@ -52,8 +52,8 @@ public function testClassExistsAfterImport() 'classPrefix' => 'DC95_', 'classPrefixFiles' => true )); - $modelsPath = dirname(__FILE__) . '/DC95/models'; - $import->importSchema(dirname(__FILE__) . '/DC95/schema.yml', 'yml', $modelsPath); + $modelsPath = __DIR__ . '/DC95/models'; + $import->importSchema(__DIR__ . '/DC95/schema.yml', 'yml', $modelsPath); /* $this->assertTrue(file_exists($modelsPath . '/DC95/Base/Article.php')); @@ -63,6 +63,6 @@ public function testClassExistsAfterImport() */ Doctrine_Core::setModelsDirectory(null); - Doctrine_Lib::removeDirectories(dirname(__FILE__) . '/DC95/models'); + Doctrine_Lib::removeDirectories(__DIR__ . '/DC95/models'); } -} \ No newline at end of file +} diff --git a/tests/Ticket/gh110/Ticket_gh110_TestRecord.snapshot b/tests/Ticket/gh110/Ticket_gh110_TestRecord.snapshot new file mode 100644 index 000000000..a6b440b47 --- /dev/null +++ b/tests/Ticket/gh110/Ticket_gh110_TestRecord.snapshot @@ -0,0 +1,66 @@ +/** + * Ticket_gh110_TestRecord + * + * This class has been auto-generated by the Doctrine ORM Framework + * + * @property int $id Type: integer(4) + * @property my_custom_type $created_at Type: my_custom_type + * @property string $deleted_at Type: timestamp, Timestamp in ISO-8601 format (YYYY-MM-DD HH:MI:SS) + * + * @method int getId() Type: integer(4) + * @method my_custom_type getCreatedAt() Type: my_custom_type + * @method string getDeletedAt() Type: timestamp, Timestamp in ISO-8601 format (YYYY-MM-DD HH:MI:SS) + * + * @method Ticket_gh110_TestRecord setId(int $val) Type: integer(4) + * @method Ticket_gh110_TestRecord setCreatedAt(my_custom_type $val) Type: my_custom_type + * @method Ticket_gh110_TestRecord setDeletedAt(string $val) Type: timestamp, Timestamp in ISO-8601 format (YYYY-MM-DD HH:MI:SS) + * + * @package ##PACKAGE## + * @subpackage ##SUBPACKAGE## + * @author ##NAME## <##EMAIL##> + * @version SVN: $Id: Builder.php 7490 2010-03-29 19:53:27Z jwage $ + */ +class Ticket_gh110_TestRecord extends Doctrine_Record +{ + public function setTableDefinition() + { + $this->hasColumn('id', 'integer', 4, array( + 'type' => 'integer', + 'length' => 4, + )); + $this->hasColumn('created_at', 'my_custom_type', null, array( + 'type' => 'my_custom_type', + 'length' => '', + )); + } + + public function setUp() + { + parent::setUp(); + $softdelete0 = new Doctrine_Template_SoftDelete(array( + )); + $timestampable0 = new Doctrine_Template_Timestampable(array( + 'updated' => + array( + 'disabled' => true, + ), + 'unknown_column' => + array( + ), + )); + $unknownactas0 = new UnknownActAs(array( + )); + $gh110_template0 = new Doctrine_Template_gh110_Template(array( + )); + $gh110_invalid_template0 = new gh110_Invalid_Template(array( + )); + $gh110_abstract_template0 = new gh110_Abstract_Template(array( + )); + $this->actAs($softdelete0); + $this->actAs($timestampable0); + $this->actAs($unknownactas0); + $this->actAs($gh110_template0); + $this->actAs($gh110_invalid_template0); + $this->actAs($gh110_abstract_template0); + } +} \ No newline at end of file diff --git a/tests/Ticket/gh110TestCase.php b/tests/Ticket/gh110TestCase.php new file mode 100644 index 000000000..f140d88ed --- /dev/null +++ b/tests/Ticket/gh110TestCase.php @@ -0,0 +1,81 @@ +buildDefinition( + array( + 'className' => 'Ticket_gh110_TestRecord', + 'topLevelClassName' => 'Ticket_gh110_TestRecord', + 'is_base_class' => true, + 'columns' => array( + 'id' => array( + 'type' => 'integer', + 'length' => 4, + ), + 'my_custom_created_at' => array( + 'name' => 'created_at', + 'type' => 'my_custom_type', + 'length' => '', + ) + ), + 'actAs' => array( + 'SoftDelete' => array(), + 'Timestampable' => array( + 'updated' => array( + 'disabled' => true, + ), + 'unknown_column' => array() + ), + 'UnknownActAs' => array(), + // This template brings an already defined column + 'gh110_Template' => array(), + 'gh110_Invalid_Template' => array(), + 'gh110_Abstract_Template' => array(), + ) + ) + ); + + // Can be used to update the snapshot. + //file_put_contents(__DIR__ . '/gh110/Ticket_gh110_TestRecord.snapshot', $class); + $this->assertEqual($class, file_get_contents(__DIR__ . '/gh110/Ticket_gh110_TestRecord.snapshot')); + } +} + +abstract class gh110_Abstract_Template {} + +/** This is just a simple class without the required getOptions()-Method */ +class gh110_Invalid_Template {} + +class Doctrine_Template_gh110_Template extends Doctrine_Template +{ + protected $_options = array( + 'created' => array( + 'name' => 'created_at', + 'alias' => null, + 'type' => 'timestamp', + 'format' => 'Y-m-d H:i:s', + 'disabled' => false, + 'expression' => false, + 'options' => array('notnull' => true) + ) + ); + + /** + * Set table definition for Timestampable behavior + * + * @return void + */ + public function setTableDefinition() + { + if ( ! $this->_options['created']['disabled']) { + $name = $this->_options['created']['name']; + if ($this->_options['created']['alias']) { + $name .= ' as ' . $this->_options['created']['alias']; + } + $this->hasColumn($name, $this->_options['created']['type'], null, $this->_options['created']['options']); + } + } +} diff --git a/tests/bin/test b/tests/bin/test new file mode 100755 index 000000000..2df829884 --- /dev/null +++ b/tests/bin/test @@ -0,0 +1,76 @@ +#! /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`" +composerUpdate='composer update --prefer-dist --optimize-autoloader' +doctrineTestSuite='run.php' + +# Parse arguments +# +phpVersions="${1-}" +dependencyPreferences="${2-${dependencyPreferences}}" +phpTestRuntime="${3-${doctrineTestSuite}}" + +script () +{ + echo + echo + echo $0 ${1} ${2} + echo + ${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 () +{ + ${dcexec} composer ${composerUpdate} +} + +install_lowest () +{ + ${dcexec} composer ${composerUpdate} --prefer-lowest +} + +echo '+ docker-compose build' +docker-compose up -d --build --remove-orphans > /dev/null + +test x"" != x"${phpVersions}" || { + phpVersions=`fetchAllPHPVersions` +} + +scriptAll diff --git a/tests/models/Location2.php b/tests/models/Location2.php new file mode 100644 index 000000000..80ad551cf --- /dev/null +++ b/tests/models/Location2.php @@ -0,0 +1,10 @@ +hasColumn('id', 'integer', 10, array('primary' => true)); + $this->hasColumn('lat', 'double', 10); + $this->hasColumn('lon', 'double', 10); + } +} diff --git a/tests/run.php b/tests/run.php index d6360a114..d1dd2c7ee 100644 --- a/tests/run.php +++ b/tests/run.php @@ -1,24 +1,45 @@ addTestCase(new Doctrine_Search_TestCase()); +$search->addTestCase(new Doctrine_Search_Query_TestCase()); +$search->addTestCase(new Doctrine_Search_File_TestCase()); +$test->addTestCase($search); + +// Behaviors Testing +$behaviors = new GroupTest('Behaviors Tests', 'behaviors'); +$behaviors->addTestCase(new Doctrine_I18n_TestCase()); +$behaviors->addTestCase(new Doctrine_Plugin_TestCase()); +$behaviors->addTestCase(new Doctrine_View_TestCase()); +$behaviors->addTestCase(new Doctrine_AuditLog_TestCase()); +$behaviors->addTestCase(new Doctrine_Hook_TestCase()); +$behaviors->addTestCase(new Doctrine_Sluggable_TestCase()); +$behaviors->addTestCase(new Doctrine_Record_Generator_TestCase()); +$behaviors->addTestCase(new Doctrine_SoftDelete_TestCase()); +$behaviors->addTestCase(new Doctrine_SoftDeleteBC_TestCase()); +$test->addTestCase($behaviors); + +// Ticket Tests +$tickets = new GroupTest('Tickets Tests', 'tickets'); + +$ticketTestCases = glob(__DIR__ . '/Ticket/*TestCase.php'); foreach ($ticketTestCases as $testCase) { @@ -159,19 +180,6 @@ $data_types->addTestCase(new Doctrine_DataType_Boolean_TestCase()); $test->addTestCase($data_types); -// Behaviors Testing -$behaviors = new GroupTest('Behaviors Tests', 'behaviors'); -$behaviors->addTestCase(new Doctrine_Plugin_TestCase()); -$behaviors->addTestCase(new Doctrine_View_TestCase()); -$behaviors->addTestCase(new Doctrine_AuditLog_TestCase()); -$behaviors->addTestCase(new Doctrine_Hook_TestCase()); -$behaviors->addTestCase(new Doctrine_I18n_TestCase()); -$behaviors->addTestCase(new Doctrine_Sluggable_TestCase()); -$behaviors->addTestCase(new Doctrine_Record_Generator_TestCase()); -$behaviors->addTestCase(new Doctrine_SoftDelete_TestCase()); -$behaviors->addTestCase(new Doctrine_SoftDeleteBC_TestCase()); -$test->addTestCase($behaviors); - // Validator Testing $validators = new GroupTest('Validators Testing', 'validators'); $validators->addTestCase(new Doctrine_Validator_TestCase()); @@ -255,13 +263,6 @@ $inheritance->addTestCase(new Doctrine_Query_ApplyInheritance_TestCase()); $test->addTestCase($inheritance); -// Search Tests -$search = new GroupTest('Search Tests', 'search'); -$search->addTestCase(new Doctrine_Search_TestCase()); -$search->addTestCase(new Doctrine_Search_Query_TestCase()); -$search->addTestCase(new Doctrine_Search_File_TestCase()); -$test->addTestCase($search); - // Cache Tests $cache = new GroupTest('Cache Tests', 'cache'); $cache->addTestCase(new Doctrine_Query_Cache_TestCase()); @@ -317,4 +318,4 @@ $test->addTestCase($unsorted); */ -exit($test->run() ? 0 : 1); \ No newline at end of file +exit($test->run() ? 0 : 1); diff --git a/tests/tmp/Ticket_1527_User.php b/tests/tmp/Ticket_1527_User.php deleted file mode 100644 index 243acef32..000000000 --- a/tests/tmp/Ticket_1527_User.php +++ /dev/null @@ -1,16 +0,0 @@ - - * @version SVN: $Id: Builder.php 7490 2010-03-29 19:53:27Z jwage $ - */ -class Ticket_1527_User extends BaseTicket_1527_User -{ - -} \ No newline at end of file diff --git a/tests/tmp/generated/BaseTicket_1527_User.php b/tests/tmp/generated/BaseTicket_1527_User.php deleted file mode 100644 index a12f60801..000000000 --- a/tests/tmp/generated/BaseTicket_1527_User.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @version SVN: $Id: Builder.php 7490 2010-03-29 19:53:27Z jwage $ - */ -abstract class BaseTicket_1527_User extends Doctrine_Record -{ - public function setTableDefinition() - { - $this->setTableName('ticket_1527__user'); - $this->hasColumn('username', 'string', 255, array( - 'type' => 'string', - 'extra' => - array( - 'test' => 123, - ), - 'length' => '255', - )); - $this->hasColumn('password', 'string', 255, array( - 'type' => 'string', - 'length' => '255', - )); - } - - public function setUp() - { - parent::setUp(); - - } -} \ No newline at end of file diff --git a/tests/unsolved.php b/tests/unsolved.php index e10461a6b..0009580a0 100644 --- a/tests/unsolved.php +++ b/tests/unsolved.php @@ -1,12 +1,12 @@ ";