From 50cb69ed2cbaf335cd7d340fac8caceeea97e029 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 16:35:12 +0200 Subject: [PATCH] PHP 8.1 > Compatibility sfYamlInline, backport fix from Symfony1. Doctrine_Hydrator_Graph fix array_map, rtrim(): Passing null to parameter #1 ($string) of type string is deprecated I emmit the hypothese that this array_map was broken, because array_map result is not assigned. Doctrine_Migration_Diff:333, str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated Doctrine_Migration_Builder:78:, is_dir(): Passing null to parameter #1 ($filename) of type string is deprecated Doctrine_Validator_Notblank, allow null value HydrationListener, in HydrateTestCase.php, fix strtoupper(): Passing null to parameter #1 ($string) of type string is deprecated internal_method_return_types https://wiki.php.net/rfc/internal_method_return_types see 2b2d173848f84d557a8239c37501ba68df98e582 for details Doctrine_Collection_OnDemand Doctrine_Validator_Exception PHP 8.1 PDO stringify is now disable by default. Activate it for Mysql + Sqlite https://www.php.net/manual/en/migration81.incompatible.php#migration81.incompatible.pdo.mysql PHP 8.1 Fix: Warning: strtotime() : Epoch doesn't fit in a PHP integer in Doctrine_Record. This is only happening on 32bit system, because int 32bit could not map the whole strtotime date scope. Example value: "0000-00-00 00:00:00" Before 8.1 strtotime returns false, after it return false but also raise a Warning. @ is slightly lowering performance, it should not trigger any unwanted error, as if format is invalid strtotime should return "false" As this old project need BC for old system, seems the best fix. PHP 8.1 > Automatic conversion of false to array is deprecated Fix Doctrine_Record _invokedSaveHooks cannot assign array value to boolean Declaration to array instead of boolean PHP 8.1 > Serializable Phase Out https://wiki.php.net/rfc/phase_out_serializable PHP 7.4 add a new Serialize mecanism PHP 8.1 made old method, "Serializable implementation" deprecated PHP 9.0 (no release date at this moment) will drop the support. Temporary Fix: Adding both method serialize/unserialize and __serialize/__unserialize In order to be compatible with future PHP 9.0, once it will be release, we will have to drop the support to PHP Version before 7.4. Currently a lot of Unix distribution in LTS are running a PHP Version older than 7.4 so moving to the final solution of "add return type" should break a lot of setup for the moment. PHP 8.1 > internal_method_return_types https://wiki.php.net/rfc/internal_method_return_types PHP 8.0 added return type for abstract methods on Iterator, ArrayAccess, Countable, IteratorAggregate PHP 8.1 made non implementation as a Deprecated Warning PHP 9.0 (no release date at this moment) will drop the support. Temporary Fix : adding this Attribute #[\ReturnTypeWillChange] Will drop the Deprecated warning. Adding return type will break compatibility before PHP 7.4, Return type has been added on PHP 7.0, but "mixed" special type is required, and it has been added on PHP 7.4. In order to be compatible with future PHP 9.0, once it will be release, we will have to drop the support to PHP Version before 7.4 Currently a lot of Unix distribution in LTS are running a PHP Version older than 7.4 so moving to the final solution of "add return type" should break a lot of setup for the moment. Update Travis to PHP up to 8.1 PHP 8.0 > Doctrine_Query:36, uncaught TypeError: Unsupported operand types: string % int Doctrine_Parser_Xml:89, htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated https://wiki.php.net/rfc/internal_method_return_types for Doctrine_Node Doctrine_Adapter_Mock Doctrine_EventListener_TestLogger Doctrine_Parser_Xml Doctrine_Ticket_1254_TestCase, replace stftime() by date() with format adaptation. --- .travis.yml | 20 ++++-- lib/Doctrine/Access.php | 5 ++ lib/Doctrine/Adapter/Mock.php | 1 + lib/Doctrine/Collection.php | 40 +++++++++--- lib/Doctrine/Collection/OnDemand.php | 5 ++ lib/Doctrine/Connection.php | 35 +++++++++-- lib/Doctrine/Connection/Mysql.php | 5 ++ lib/Doctrine/Connection/Profiler.php | 16 ++--- lib/Doctrine/Connection/Sqlite.php | 18 +++++- lib/Doctrine/Hydrator/Graph.php | 4 +- lib/Doctrine/Manager.php | 2 + lib/Doctrine/Migration/Builder.php | 2 +- lib/Doctrine/Migration/Diff.php | 2 +- lib/Doctrine/Node.php | 1 + lib/Doctrine/Parser/Xml.php | 2 +- lib/Doctrine/Parser/sfYaml/sfYamlInline.php | 6 +- lib/Doctrine/Query.php | 3 +- lib/Doctrine/Record.php | 55 +++++++++++----- lib/Doctrine/Record/Iterator.php | 1 + lib/Doctrine/Relation.php | 4 ++ lib/Doctrine/Table.php | 69 ++++++++++++++++----- lib/Doctrine/Table/Repository.php | 2 + lib/Doctrine/Validator/ErrorStack.php | 2 + lib/Doctrine/Validator/Exception.php | 2 + lib/Doctrine/Validator/Notblank.php | 2 +- tests/EventListenerTestCase.php | 1 + tests/HydrateTestCase.php | 2 +- tests/Ticket/1254TestCase.php | 2 +- tests/Ticket/982TestCase.php | 4 +- 29 files changed, 243 insertions(+), 70 deletions(-) diff --git a/.travis.yml b/.travis.yml index 70a0ca577..cfd880464 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,11 @@ os: linux -dist: xenial +dist: focal language: php php: - - 7.0 - - 7.1 - - 7.2 - - 7.3 - 7.4 + - 8.0 + - 8.1 - nightly cache: @@ -18,15 +16,25 @@ jobs: fast_finish: true allow_failures: - php: nightly + - php: 5.3 include: - php: 5.3 dist: precise - php: 5.4 - dist: precise + dist: trusty - php: 5.5 dist: trusty - php: 5.6 dist: trusty + - php: 7.0 + dist: xenial + - php: 7.1 + dist: xenial + - php: 7.2 + dist: xenial + - php: 7.3 + dist: xenial + services: - mysql diff --git a/lib/Doctrine/Access.php b/lib/Doctrine/Access.php index 572ff7ff0..82204abc9 100644 --- a/lib/Doctrine/Access.php +++ b/lib/Doctrine/Access.php @@ -89,6 +89,7 @@ public function __isset($name) * @param string $name * @return void */ + #[\ReturnTypeWillChange] public function __unset($name) { return $this->remove($name); @@ -100,6 +101,7 @@ public function __unset($name) * @param mixed $offset * @return boolean Whether or not this object contains $offset */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return $this->contains($offset); @@ -112,6 +114,7 @@ public function offsetExists($offset) * @param mixed $offset * @return mixed */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { // array notation with no index was causing 'undefined variable: $offset' notices in php7, @@ -131,6 +134,7 @@ public function offsetGet($offset) * @param mixed $value * @return void */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { if ( ! isset($offset)) { @@ -146,6 +150,7 @@ public function offsetSet($offset, $value) * @see set, offsetSet, __set * @param mixed $offset */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { return $this->remove($offset); 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/Collection.php b/lib/Doctrine/Collection.php index 38b5d85e9..25b7ca441 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); @@ -1036,6 +1061,7 @@ public function free($deep = false) * * @return Iterator */ + #[\ReturnTypeWillChange] public function getIterator() { $data = $this->data; 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/Connection.php b/lib/Doctrine/Connection.php index a6703a221..338bb060d 100644 --- a/lib/Doctrine/Connection.php +++ b/lib/Doctrine/Connection.php @@ -1178,6 +1178,7 @@ public function getTables() * * @return ArrayIterator SPL ArrayIterator object */ + #[\ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->tables); @@ -1188,6 +1189,7 @@ public function getIterator() * * @return integer */ + #[\ReturnTypeWillChange] public function count() { return $this->_count; @@ -1606,6 +1608,7 @@ public function __toString() return Doctrine_Lib::getConnectionAsString($this); } + /** * Serialize. Remove database connection(pdo) since it cannot be serialized * @@ -1613,9 +1616,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 +1631,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/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..1b7894b53 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 @@ -109,7 +109,7 @@ public function __call($m, $a) * @param mixed $key * @return Doctrine_Event */ - public function get($key) + public function get($key) { if (isset($this->events[$key])) { return $this->events[$key]; @@ -123,7 +123,7 @@ public function get($key) * * @return array 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); } @@ -154,7 +156,7 @@ public function count() * * @return Doctrine_Event */ - 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..6df19b1a7 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); @@ -87,8 +93,18 @@ public function connect() return false; } + // If customer configure it + $hasConfigureStringify = (isset($this->pendingAttributes[Doctrine_Core::ATTR_STRINGIFY_FETCHES])); + 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); diff --git a/lib/Doctrine/Hydrator/Graph.php b/lib/Doctrine/Hydrator/Graph.php index 3c4b845e7..88232a889 100644 --- a/lib/Doctrine/Hydrator/Graph.php +++ b/lib/Doctrine/Hydrator/Graph.php @@ -121,7 +121,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 diff --git a/lib/Doctrine/Manager.php b/lib/Doctrine/Manager.php index 957c51478..fe7560b4c 100644 --- a/lib/Doctrine/Manager.php +++ b/lib/Doctrine/Manager.php @@ -638,6 +638,7 @@ public function contains($key) * * @return integer */ + #[\ReturnTypeWillChange] public function count() { return count($this->_connections); @@ -648,6 +649,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/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/sfYamlInline.php b/lib/Doctrine/Parser/sfYaml/sfYamlInline.php index 0aff5d375..77096e43f 100644 --- a/lib/Doctrine/Parser/sfYaml/sfYamlInline.php +++ b/lib/Doctrine/Parser/sfYaml/sfYamlInline.php @@ -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/Query.php b/lib/Doctrine/Query.php index 461f6937b..99f54a170 100644 --- a/lib/Doctrine/Query.php +++ b/lib/Doctrine/Query.php @@ -1423,7 +1423,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 +2134,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/Record.php b/lib/Doctrine/Record.php index 370691f2e..1777e9af7 100644 --- a/lib/Doctrine/Record.php +++ b/lib/Doctrine/Record.php @@ -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 @@ -798,6 +798,33 @@ 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 +866,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; } @@ -1543,8 +1564,8 @@ protected function _isValueModified($type, $old, $new) } 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((string) $old); - $newStrToTime = strtotime((string) $new); + $oldStrToTime = @strtotime((string) $old); + $newStrToTime = @strtotime((string) $new); if ($oldStrToTime && $newStrToTime) { return $oldStrToTime !== $newStrToTime; } else { @@ -1865,6 +1886,7 @@ public function getPrepared(array $array = array()) * * @return integer the number of columns in this record */ + #[\ReturnTypeWillChange] public function count() { return count($this->_data); @@ -2162,6 +2184,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); 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..df83c3aa5 100644 --- a/lib/Doctrine/Relation.php +++ b/lib/Doctrine/Relation.php @@ -169,11 +169,13 @@ public function isEqual() return $this->definition['equal']; } + #[\ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->definition[$offset]); } + #[\ReturnTypeWillChange] public function offsetGet($offset) { if (isset($this->definition[$offset])) { @@ -183,6 +185,7 @@ public function offsetGet($offset) return null; } + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { if (isset($this->definition[$offset])) { @@ -190,6 +193,7 @@ public function offsetSet($offset, $value) } } + #[\ReturnTypeWillChange] public function offsetUnset($offset) { $this->definition[$offset] = false; diff --git a/lib/Doctrine/Table.php b/lib/Doctrine/Table.php index 87d6cb0bc..a76a7bdfc 100644 --- a/lib/Doctrine/Table.php +++ b/lib/Doctrine/Table.php @@ -1982,6 +1982,7 @@ final public function applyInheritance($where) * * @return integer number of records in the table */ + #[\ReturnTypeWillChange] public function count() { return $this->createQuery()->count(); @@ -2979,12 +2980,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, @@ -2996,26 +3029,30 @@ 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 $serialized + */ + 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]; } + 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/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..e90c18a47 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 (trim((string) $value) !== '' && $value !== null); } } \ No newline at end of file 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/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/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/982TestCase.php b/tests/Ticket/982TestCase.php index 5b44d2a93..781b305a1 100644 --- a/tests/Ticket/982TestCase.php +++ b/tests/Ticket/982TestCase.php @@ -39,7 +39,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 +49,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');