From 245c7cce0d705d97fbe2b0209474d8a18920c859 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 19 May 2022 15:52:46 +0200 Subject: [PATCH 01/23] PHP 8.1 > internal_method_return_types https://wiki.php.net/rfc/internal_method_return_types PHP 8.0 added return type for abstract methods on Iterator, ArrayAccess, Countable, IteratorAggregate PHP 8.1 made non implementation as a Deprecated Warning PHP 9.0 (no release date at this moment) will drop the support. Temporary Fix : adding this Attribute Will drop the Deprecated warning. Adding return type will break compatibility before PHP 7.4, Return type has been added on PHP 7.0, but "mixed" special type is required, and it has been added on PHP 7.4. In order to be compatible with future PHP 9.0, once it will be release, we will have to drop the support to PHP Version before 7.4 Currently a lot of Unix distribution in LTS are running a PHP Version older than 7.4 so moving to the final solution of "add return type" should break a lot of setup for the moment. --- lib/addon/sfPager.class.php | 6 ++++++ lib/escaper/sfOutputEscaperArrayDecorator.class.php | 10 ++++++++++ lib/escaper/sfOutputEscaperIteratorDecorator.class.php | 9 +++++++++ lib/escaper/sfOutputEscaperObjectDecorator.class.php | 1 + lib/event/sfEvent.class.php | 6 +++++- lib/form/sfForm.class.php | 10 ++++++++++ lib/form/sfFormFieldSchema.class.php | 10 ++++++++++ .../lib/generator/sfDoctrineColumn.class.php | 6 +++++- lib/request/sfRequest.class.php | 4 ++++ lib/routing/sfRouteCollection.class.php | 5 +++++ lib/user/sfUser.class.php | 4 ++++ lib/util/sfContext.class.php | 4 ++++ lib/util/sfDomCssSelector.class.php | 6 ++++++ lib/validator/sfValidatorErrorSchema.class.php | 10 ++++++++++ lib/validator/sfValidatorSchema.class.php | 4 ++++ lib/widget/sfWidgetFormSchema.class.php | 4 ++++ lib/widget/sfWidgetFormSchemaDecorator.class.php | 4 ++++ .../escaper/sfOutputEscaperObjectDecoratorTest.php | 1 + 18 files changed, 102 insertions(+), 2 deletions(-) diff --git a/lib/addon/sfPager.class.php b/lib/addon/sfPager.class.php index 594b1417a..84a4cc5f1 100644 --- a/lib/addon/sfPager.class.php +++ b/lib/addon/sfPager.class.php @@ -529,6 +529,7 @@ protected function resetIterator() * * @see Iterator */ + #[\ReturnTypeWillChange] public function current() { if (!$this->isIteratorInitialized()) @@ -544,6 +545,7 @@ public function current() * * @see Iterator */ + #[\ReturnTypeWillChange] public function key() { if (!$this->isIteratorInitialized()) @@ -559,6 +561,7 @@ public function key() * * @see Iterator */ + #[\ReturnTypeWillChange] public function next() { if (!$this->isIteratorInitialized()) @@ -576,6 +579,7 @@ public function next() * * @see Iterator */ + #[\ReturnTypeWillChange] public function rewind() { if (!$this->isIteratorInitialized()) @@ -593,6 +597,7 @@ public function rewind() * * @see Iterator */ + #[\ReturnTypeWillChange] public function valid() { if (!$this->isIteratorInitialized()) @@ -608,6 +613,7 @@ public function valid() * * @see Countable */ + #[\ReturnTypeWillChange] public function count() { return $this->getNbResults(); diff --git a/lib/escaper/sfOutputEscaperArrayDecorator.class.php b/lib/escaper/sfOutputEscaperArrayDecorator.class.php index 0e6b0b0ae..6b87a4322 100644 --- a/lib/escaper/sfOutputEscaperArrayDecorator.class.php +++ b/lib/escaper/sfOutputEscaperArrayDecorator.class.php @@ -42,6 +42,7 @@ public function __construct($escapingMethod, $value) /** * Reset the array to the beginning (as required for the Iterator interface). */ + #[\ReturnTypeWillChange] public function rewind() { reset($this->value); @@ -54,6 +55,7 @@ public function rewind() * * @return string The key */ + #[\ReturnTypeWillChange] public function key() { return key($this->value); @@ -67,6 +69,7 @@ public function key() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return sfOutputEscaper::escape($this->escapingMethod, current($this->value)); @@ -75,6 +78,7 @@ public function current() /** * Moves to the next element (as required by the Iterator interface). */ + #[\ReturnTypeWillChange] public function next() { next($this->value); @@ -91,6 +95,7 @@ public function next() * * @return bool The validity of the current element; true if it is valid */ + #[\ReturnTypeWillChange] public function valid() { return $this->count > 0; @@ -103,6 +108,7 @@ public function valid() * * @return bool true if the offset isset; false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->value[$offset]); @@ -115,6 +121,7 @@ public function offsetExists($offset) * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return sfOutputEscaper::escape($this->escapingMethod, $this->value[$offset]); @@ -132,6 +139,7 @@ public function offsetGet($offset) * * @throws sfException */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new sfException('Cannot set values.'); @@ -148,6 +156,7 @@ public function offsetSet($offset, $value) * * @throws sfException */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { throw new sfException('Cannot unset values.'); @@ -158,6 +167,7 @@ public function offsetUnset($offset) * * @return int The size of the array */ + #[\ReturnTypeWillChange] public function count() { return count($this->value); diff --git a/lib/escaper/sfOutputEscaperIteratorDecorator.class.php b/lib/escaper/sfOutputEscaperIteratorDecorator.class.php index 7d9eca063..68ed43dfd 100644 --- a/lib/escaper/sfOutputEscaperIteratorDecorator.class.php +++ b/lib/escaper/sfOutputEscaperIteratorDecorator.class.php @@ -56,6 +56,7 @@ public function __construct($escapingMethod, Traversable $value) * * @return void */ + #[\ReturnTypeWillChange] public function rewind() { return $this->iterator->rewind(); @@ -66,6 +67,7 @@ public function rewind() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return sfOutputEscaper::escape($this->escapingMethod, $this->iterator->current()); @@ -76,6 +78,7 @@ public function current() * * @return string Iterator key */ + #[\ReturnTypeWillChange] public function key() { return $this->iterator->key(); @@ -86,6 +89,7 @@ public function key() * * @return void */ + #[\ReturnTypeWillChange] public function next() { return $this->iterator->next(); @@ -97,6 +101,7 @@ public function next() * * @return bool true if the current element is valid; false otherwise */ + #[\ReturnTypeWillChange] public function valid() { return $this->iterator->valid(); @@ -109,6 +114,7 @@ public function valid() * * @return bool true if the offset isset; false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->value[$offset]); @@ -121,6 +127,7 @@ public function offsetExists($offset) * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return sfOutputEscaper::escape($this->escapingMethod, $this->value[$offset]); @@ -138,6 +145,7 @@ public function offsetGet($offset) * * @throws sfException */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new sfException('Cannot set values.'); @@ -154,6 +162,7 @@ public function offsetSet($offset, $value) * * @throws sfException */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { throw new sfException('Cannot unset values.'); diff --git a/lib/escaper/sfOutputEscaperObjectDecorator.class.php b/lib/escaper/sfOutputEscaperObjectDecorator.class.php index 89e70edcd..fe506d9c1 100644 --- a/lib/escaper/sfOutputEscaperObjectDecorator.class.php +++ b/lib/escaper/sfOutputEscaperObjectDecorator.class.php @@ -115,6 +115,7 @@ public function __isset($key) * * @return int The size of the object */ + #[\ReturnTypeWillChange] public function count() { return count($this->value); diff --git a/lib/event/sfEvent.class.php b/lib/event/sfEvent.class.php index 0ffd44281..750b28023 100644 --- a/lib/event/sfEvent.class.php +++ b/lib/event/sfEvent.class.php @@ -83,7 +83,7 @@ public function getReturnValue() /** * Sets the processed flag. * - * @param Boolean $processed The processed flag value + * @param boolean $processed The processed flag value */ public function setProcessed($processed) { @@ -117,6 +117,7 @@ public function getParameters() * * @return Boolean true if the parameter exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return array_key_exists($name, $this->parameters); @@ -129,6 +130,7 @@ public function offsetExists($name) * * @return mixed The parameter value */ + #[\ReturnTypeWillChange] public function offsetGet($name) { if (!array_key_exists($name, $this->parameters)) @@ -145,6 +147,7 @@ public function offsetGet($name) * @param string $name The parameter name * @param mixed $value The parameter value */ + #[\ReturnTypeWillChange] public function offsetSet($name, $value) { $this->parameters[$name] = $value; @@ -155,6 +158,7 @@ public function offsetSet($name, $value) * * @param string $name The parameter name */ + #[\ReturnTypeWillChange] public function offsetUnset($name) { unset($this->parameters[$name]); diff --git a/lib/form/sfForm.class.php b/lib/form/sfForm.class.php index db46c4d82..2db45bbde 100644 --- a/lib/form/sfForm.class.php +++ b/lib/form/sfForm.class.php @@ -1064,6 +1064,7 @@ public function resetFormFields() * * @return Boolean true if the widget exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->widgetSchema[$name]); @@ -1076,6 +1077,7 @@ public function offsetExists($name) * * @return sfFormField|sfFormFieldSchema A form field instance */ + #[\ReturnTypeWillChange] public function offsetGet($name) { if (!isset($this->formFields[$name])) @@ -1114,6 +1116,7 @@ public function offsetGet($name) * * @throws LogicException */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new LogicException('Cannot update form fields.'); @@ -1126,6 +1129,7 @@ public function offsetSet($offset, $value) * * @param string $offset The field name */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { unset( @@ -1227,6 +1231,7 @@ public function getErrors() /** * Resets the field names array to the beginning (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function rewind() { $this->fieldNames = $this->widgetSchema->getPositions(); @@ -1240,6 +1245,7 @@ public function rewind() * * @return string The key */ + #[\ReturnTypeWillChange] public function key() { return current($this->fieldNames); @@ -1250,6 +1256,7 @@ public function key() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return $this[current($this->fieldNames)]; @@ -1258,6 +1265,7 @@ public function current() /** * Moves to the next form field (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function next() { next($this->fieldNames); @@ -1269,6 +1277,7 @@ public function next() * * @return boolean The validity of the current element; true if it is valid */ + #[\ReturnTypeWillChange] public function valid() { return $this->count > 0; @@ -1279,6 +1288,7 @@ public function valid() * * @return integer The number of embedded form fields */ + #[\ReturnTypeWillChange] public function count() { return count($this->getFormFieldSchema()); diff --git a/lib/form/sfFormFieldSchema.class.php b/lib/form/sfFormFieldSchema.class.php index 520058dfe..2e9407ad5 100644 --- a/lib/form/sfFormFieldSchema.class.php +++ b/lib/form/sfFormFieldSchema.class.php @@ -91,6 +91,7 @@ public function getHiddenFields($recursive = true) * * @return Boolean true if the widget exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->widget[$name]); @@ -103,6 +104,7 @@ public function offsetExists($name) * * @return sfFormField A form field instance */ + #[\ReturnTypeWillChange] public function offsetGet($name) { if (!isset($this->fields[$name])) @@ -144,6 +146,7 @@ public function offsetGet($name) * * @throws LogicException */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new LogicException('Cannot update form fields (read-only).'); @@ -156,6 +159,7 @@ public function offsetSet($offset, $value) * * @throws LogicException */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { throw new LogicException('Cannot remove form fields (read-only).'); @@ -164,6 +168,7 @@ public function offsetUnset($offset) /** * Resets the field names array to the beginning (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function rewind() { reset($this->fieldNames); @@ -175,6 +180,7 @@ public function rewind() * * @return string The key */ + #[\ReturnTypeWillChange] public function key() { return current($this->fieldNames); @@ -185,6 +191,7 @@ public function key() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return $this[current($this->fieldNames)]; @@ -193,6 +200,7 @@ public function current() /** * Moves to the next form field (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function next() { next($this->fieldNames); @@ -204,6 +212,7 @@ public function next() * * @return boolean The validity of the current element; true if it is valid */ + #[\ReturnTypeWillChange] public function valid() { return $this->count > 0; @@ -214,6 +223,7 @@ public function valid() * * @return integer The number of embedded form fields */ + #[\ReturnTypeWillChange] public function count() { return count($this->fieldNames); diff --git a/lib/plugins/sfDoctrinePlugin/lib/generator/sfDoctrineColumn.class.php b/lib/plugins/sfDoctrinePlugin/lib/generator/sfDoctrineColumn.class.php index 6611f26a3..f693ebb55 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/generator/sfDoctrineColumn.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/generator/sfDoctrineColumn.class.php @@ -349,23 +349,27 @@ public function getTable() return $this->table; } + #[\ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->definition[$offset]); } + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->definition[$offset] = $value; } + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->definition[$offset]; } + #[\ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->definition[$offset]); } -} \ No newline at end of file +} diff --git a/lib/request/sfRequest.class.php b/lib/request/sfRequest.class.php index b7249728b..ac6928e20 100644 --- a/lib/request/sfRequest.class.php +++ b/lib/request/sfRequest.class.php @@ -173,6 +173,7 @@ public function setMethod($method) * * @return bool true if the request parameter exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return $this->hasParameter($name); @@ -185,6 +186,7 @@ public function offsetExists($name) * * @return mixed The request parameter if exists, null otherwise */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return $this->getParameter($name, false); @@ -196,6 +198,7 @@ public function offsetGet($name) * @param string $offset The parameter name * @param string $value The parameter value */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->setParameter($offset, $value); @@ -206,6 +209,7 @@ public function offsetSet($offset, $value) * * @param string $offset The parameter name */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { $this->getParameterHolder()->remove($offset); diff --git a/lib/routing/sfRouteCollection.class.php b/lib/routing/sfRouteCollection.class.php index ee0117185..f95d2dbbb 100644 --- a/lib/routing/sfRouteCollection.class.php +++ b/lib/routing/sfRouteCollection.class.php @@ -61,6 +61,7 @@ public function getOptions() /** * Reset the error array to the beginning (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function rewind() { reset($this->routes); @@ -73,6 +74,7 @@ public function rewind() * * @return string The key */ + #[\ReturnTypeWillChange] public function key() { return key($this->routes); @@ -83,6 +85,7 @@ public function key() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return current($this->routes); @@ -91,6 +94,7 @@ public function current() /** * Moves to the next route (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function next() { next($this->routes); @@ -103,6 +107,7 @@ public function next() * * @return boolean The validity of the current route; true if it is valid */ + #[\ReturnTypeWillChange] public function valid() { return $this->count > 0; diff --git a/lib/user/sfUser.class.php b/lib/user/sfUser.class.php index 2b65fa065..47d122a20 100644 --- a/lib/user/sfUser.class.php +++ b/lib/user/sfUser.class.php @@ -227,6 +227,7 @@ public function getCulture() * * @return Boolean true if the user attribute exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return $this->hasAttribute($name); @@ -239,6 +240,7 @@ public function offsetExists($name) * * @return mixed The user attribute if exists, null otherwise */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return $this->getAttribute($name, false); @@ -250,6 +252,7 @@ public function offsetGet($name) * @param string $offset The parameter name * @param string $value The parameter value */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->setAttribute($offset, $value); @@ -260,6 +263,7 @@ public function offsetSet($offset, $value) * * @param string $offset The parameter name */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { $this->getAttributeHolder()->remove($offset); diff --git a/lib/util/sfContext.class.php b/lib/util/sfContext.class.php index 439cbf5a6..b0128afc7 100644 --- a/lib/util/sfContext.class.php +++ b/lib/util/sfContext.class.php @@ -508,6 +508,7 @@ public function getConfigCache() * * @return Boolean true if the context object exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return $this->has($name); @@ -520,6 +521,7 @@ public function offsetExists($name) * * @return mixed The context object if exists, null otherwise */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return $this->get($name); @@ -531,6 +533,7 @@ public function offsetGet($name) * @param string $offset Service name * @param mixed $value Service */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->set($offset, $value); @@ -541,6 +544,7 @@ public function offsetSet($offset, $value) * * @param string $offset The parameter name */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->factories[$offset]); diff --git a/lib/util/sfDomCssSelector.class.php b/lib/util/sfDomCssSelector.class.php index 8a6d2362f..a207f4e75 100644 --- a/lib/util/sfDomCssSelector.class.php +++ b/lib/util/sfDomCssSelector.class.php @@ -563,6 +563,7 @@ protected function nth($cur, $result = 1, $dir = 'nextSibling') /** * Reset the array to the beginning (as required for the Iterator interface). */ + #[\ReturnTypeWillChange] public function rewind() { reset($this->nodes); @@ -575,6 +576,7 @@ public function rewind() * * @return string The key */ + #[\ReturnTypeWillChange] public function key() { return key($this->nodes); @@ -585,6 +587,7 @@ public function key() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return current($this->nodes); @@ -593,6 +596,7 @@ public function current() /** * Moves to the next element (as required by the Iterator interface). */ + #[\ReturnTypeWillChange] public function next() { next($this->nodes); @@ -609,6 +613,7 @@ public function next() * * @return bool The validity of the current element; true if it is valid */ + #[\ReturnTypeWillChange] public function valid() { return $this->count > 0; @@ -619,6 +624,7 @@ public function valid() * * @param integer The number of matching nodes */ + #[\ReturnTypeWillChange] public function count() { return count($this->nodes); diff --git a/lib/validator/sfValidatorErrorSchema.class.php b/lib/validator/sfValidatorErrorSchema.class.php index d722102ac..f0175d226 100644 --- a/lib/validator/sfValidatorErrorSchema.class.php +++ b/lib/validator/sfValidatorErrorSchema.class.php @@ -176,6 +176,7 @@ public function getMessageFormat() * * @return int The number of array */ + #[\ReturnTypeWillChange] public function count() { return count($this->errors); @@ -184,6 +185,7 @@ public function count() /** * Reset the error array to the beginning (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function rewind() { reset($this->errors); @@ -196,6 +198,7 @@ public function rewind() * * @return string The key */ + #[\ReturnTypeWillChange] public function key() { return key($this->errors); @@ -206,6 +209,7 @@ public function key() * * @return mixed The escaped value */ + #[\ReturnTypeWillChange] public function current() { return current($this->errors); @@ -214,6 +218,7 @@ public function current() /** * Moves to the next error (implements the Iterator interface). */ + #[\ReturnTypeWillChange] public function next() { next($this->errors); @@ -226,6 +231,7 @@ public function next() * * @return boolean The validity of the current element; true if it is valid */ + #[\ReturnTypeWillChange] public function valid() { return $this->count > 0; @@ -238,6 +244,7 @@ public function valid() * * @return bool true if the error exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->errors[$name]); @@ -250,6 +257,7 @@ public function offsetExists($name) * * @return sfValidatorError A sfValidatorError instance */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return isset($this->errors[$name]) ? $this->errors[$name] : null; @@ -263,6 +271,7 @@ public function offsetGet($name) * * @throws LogicException */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new LogicException('Unable update an error.'); @@ -273,6 +282,7 @@ public function offsetSet($offset, $value) * * @param string $offset (ignored) */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { } diff --git a/lib/validator/sfValidatorSchema.class.php b/lib/validator/sfValidatorSchema.class.php index bbd215203..34c97180e 100644 --- a/lib/validator/sfValidatorSchema.class.php +++ b/lib/validator/sfValidatorSchema.class.php @@ -309,6 +309,7 @@ public function getPostValidator() * * @return bool true if the schema has a field with the given name, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->fields[$name]); @@ -321,6 +322,7 @@ public function offsetExists($name) * * @return sfValidatorBase The sfValidatorBase instance associated with the given name, null if it does not exist */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return isset($this->fields[$name]) ? $this->fields[$name] : null; @@ -332,6 +334,7 @@ public function offsetGet($name) * @param string $name The field name * @param sfValidatorBase $validator An sfValidatorBase instance */ + #[\ReturnTypeWillChange] public function offsetSet($name, $validator) { if (!$validator instanceof sfValidatorBase) @@ -347,6 +350,7 @@ public function offsetSet($name, $validator) * * @param string $name */ + #[\ReturnTypeWillChange] public function offsetUnset($name) { unset($this->fields[$name]); diff --git a/lib/widget/sfWidgetFormSchema.class.php b/lib/widget/sfWidgetFormSchema.class.php index acc3090d4..079db376f 100644 --- a/lib/widget/sfWidgetFormSchema.class.php +++ b/lib/widget/sfWidgetFormSchema.class.php @@ -659,6 +659,7 @@ public function generateName($name) * * @return bool true if the schema has a field with the given name, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->fields[$name]); @@ -671,6 +672,7 @@ public function offsetExists($name) * * @return sfWidget|null The sfWidget instance associated with the given name, null if it does not exist */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return isset($this->fields[$name]) ? $this->fields[$name] : null; @@ -684,6 +686,7 @@ public function offsetGet($name) * * @throws InvalidArgumentException when the field is not instance of sfWidget */ + #[\ReturnTypeWillChange] public function offsetSet($name, $widget) { if (!$widget instanceof sfWidget) @@ -710,6 +713,7 @@ public function offsetSet($name, $widget) * * @param string $name field name */ + #[\ReturnTypeWillChange] public function offsetUnset($name) { unset($this->fields[$name]); diff --git a/lib/widget/sfWidgetFormSchemaDecorator.class.php b/lib/widget/sfWidgetFormSchemaDecorator.class.php index c5d414068..5bc26bc5c 100644 --- a/lib/widget/sfWidgetFormSchemaDecorator.class.php +++ b/lib/widget/sfWidgetFormSchemaDecorator.class.php @@ -346,6 +346,7 @@ public function moveField($field, $action, $pivot = null) * @see sfWidgetFormSchema * @inheritdoc */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->widget[$name]); @@ -355,6 +356,7 @@ public function offsetExists($name) * @see sfWidgetFormSchema * @inheritdoc */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return $this->widget[$name]; @@ -364,6 +366,7 @@ public function offsetGet($name) * @see sfWidgetFormSchema * @inheritdoc */ + #[\ReturnTypeWillChange] public function offsetSet($name, $widget) { $this->widget[$name] = $widget; @@ -373,6 +376,7 @@ public function offsetSet($name, $widget) * @see sfWidgetFormSchema * @inheritdoc */ + #[\ReturnTypeWillChange] public function offsetUnset($name) { unset($this->widget[$name]); diff --git a/test/unit/escaper/sfOutputEscaperObjectDecoratorTest.php b/test/unit/escaper/sfOutputEscaperObjectDecoratorTest.php index 967bde98a..caff163b2 100644 --- a/test/unit/escaper/sfOutputEscaperObjectDecoratorTest.php +++ b/test/unit/escaper/sfOutputEscaperObjectDecoratorTest.php @@ -74,6 +74,7 @@ class Foo class FooCountable implements Countable { + #[\ReturnTypeWillChange] public function count() { return 2; From 6401fcc10f19b227af1227f1f3a808963558a968 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 19 May 2022 18:07:47 +0200 Subject: [PATCH 02/23] PHP 8.1 > Serializable Phase Out https://wiki.php.net/rfc/phase_out_serializable PHP 7.4 add a new Serialize mecanism PHP 8.1 made old method, "Serializable implementation" deprecated PHP 9.0 (no release date at this moment) will drop the support. Temporary Fix: Adding both method serialize/unserialize and __serialize/__unserialize In order to be compatible with future PHP 9.0, once it will be release, we will have to drop the support to PHP Version before 7.4. Currently a lot of Unix distribution in LTS are running a PHP Version older than 7.4 so moving to the final solution of "add return type" should break a lot of setup for the moment. Each class has been serialized/unserialized and compared on PHP 8.1.2 and 5.6.30 --- .../lib/pager/sfDoctrinePager.class.php | 33 +++++++++++++++---- lib/response/sfResponse.class.php | 21 +++++++++++- lib/response/sfWebResponse.class.php | 22 +++++++++++-- lib/routing/sfRoute.class.php | 28 ++++++++++++++-- .../sfNamespacedParameterHolder.class.php | 29 +++++++++++++--- lib/util/sfParameterHolder.class.php | 28 +++++++++++++--- lib/validator/sfValidatorError.class.php | 29 ++++++++++++++-- lib/view/sfViewParameterHolder.class.php | 27 ++++++++++++--- test/unit/response/sfResponseTest.php | 4 ++- .../validator/sfValidatorErrorSchemaTest.php | 10 ++++++ test/unit/validator/sfValidatorErrorTest.php | 10 ++++++ 11 files changed, 212 insertions(+), 29 deletions(-) diff --git a/lib/plugins/sfDoctrinePlugin/lib/pager/sfDoctrinePager.class.php b/lib/plugins/sfDoctrinePlugin/lib/pager/sfDoctrinePager.class.php index 9592575f1..b63cd66c0 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/pager/sfDoctrinePager.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/pager/sfDoctrinePager.class.php @@ -52,9 +52,7 @@ public function setTableMethod($tableMethodName) */ public function serialize() { - $vars = get_object_vars($this); - unset($vars['query']); - return serialize($vars); + return serialize($this->__serialize()); } /** @@ -66,12 +64,35 @@ public function unserialize($serialized) { $array = unserialize($serialized); - foreach ($array as $name => $values) + return $this->__unserialize($array); + } + + /** + * Serializes the current instance for php 7.4+ + * + * @return array + */ + public function __serialize() + { + $vars = get_object_vars($this); + unset($vars['query']); + return $vars; + } + + /** + * Unserializes a sfDoctrinePager instance for php 7.4+ + * + * @param array $data + */ + public function __unserialize($data) + { + + foreach ($data as $name => $values) { - $this->$name = $values; + $this->$name = $values; } - $this->tableMethodCalled = false; + $this->tableMethodCalled = false; } /** diff --git a/lib/response/sfResponse.class.php b/lib/response/sfResponse.class.php index 0dac345cb..905d07996 100644 --- a/lib/response/sfResponse.class.php +++ b/lib/response/sfResponse.class.php @@ -152,7 +152,7 @@ public function __call($method, $arguments) /** * Serializes the current instance. * - * @return array Objects instance + * @return string Objects instance */ public function serialize() { @@ -171,4 +171,23 @@ public function unserialize($serialized) { $this->content = unserialize($serialized); } + + /** + * Serializes the current instance for php 7.4+ + * + * @return array + */ + public function __serialize() { + return array('content' => $this->content); + } + + /** + * Unserializes a sfResponse instance for php 7.4+ + * + * @param array $data + */ + public function __unserialize($data) + { + $this->content = $data['content']; + } } diff --git a/lib/response/sfWebResponse.class.php b/lib/response/sfWebResponse.class.php index 4a9a6585a..9f25c50f3 100644 --- a/lib/response/sfWebResponse.class.php +++ b/lib/response/sfWebResponse.class.php @@ -876,7 +876,7 @@ public function merge(sfWebResponse $response) */ public function serialize() { - return serialize(array($this->content, $this->statusCode, $this->statusText, $this->options, $this->headerOnly, $this->headers, $this->metas, $this->httpMetas, $this->stylesheets, $this->javascripts, $this->slots)); + return serialize($this->__serialize()); } /** @@ -885,7 +885,25 @@ public function serialize() */ public function unserialize($serialized) { - list($this->content, $this->statusCode, $this->statusText, $this->options, $this->headerOnly, $this->headers, $this->metas, $this->httpMetas, $this->stylesheets, $this->javascripts, $this->slots) = unserialize($serialized); + $this->__unserialize(unserialize($serialized)); + } + + /** + * @see sfResponse + * @return array + */ + public function __serialize() + { + return array($this->content, $this->statusCode, $this->statusText, $this->options, $this->headerOnly, $this->headers, $this->metas, $this->httpMetas, $this->stylesheets, $this->javascripts, $this->slots); + } + + /** + * @see sfResponse + * @param array $data + */ + public function __unserialize($data) + { + list($this->content, $this->statusCode, $this->statusText, $this->options, $this->headerOnly, $this->headers, $this->metas, $this->httpMetas, $this->stylesheets, $this->javascripts, $this->slots) = $data; } /** diff --git a/lib/routing/sfRoute.class.php b/lib/routing/sfRoute.class.php index 6887e4e24..5a0f0e508 100644 --- a/lib/routing/sfRoute.class.php +++ b/lib/routing/sfRoute.class.php @@ -847,15 +847,37 @@ protected function fixSuffix() public function serialize() { + return serialize($this->__serialize()); + } + + public function unserialize($serialized) + { + $array = unserialize($serialized); + + $this->__unserialize($array); + } + + /** + * Serializes the current instance for php 7.4+ + * + * @return array + */ + public function __serialize() { // always serialize compiled routes $this->compile(); // sfPatternRouting will always re-set defaultParameters, so no need to serialize them - return serialize(array($this->tokens, $this->defaultOptions, $this->options, $this->pattern, $this->staticPrefix, $this->regex, $this->variables, $this->defaults, $this->requirements, $this->suffix, $this->customToken)); + return array($this->tokens, $this->defaultOptions, $this->options, $this->pattern, $this->staticPrefix, $this->regex, $this->variables, $this->defaults, $this->requirements, $this->suffix, $this->customToken); } - public function unserialize($data) + /** + * Unserializes a sfRoute instance for php 7.4+ + * + * @param array $data + */ + public function __unserialize($data) { - list($this->tokens, $this->defaultOptions, $this->options, $this->pattern, $this->staticPrefix, $this->regex, $this->variables, $this->defaults, $this->requirements, $this->suffix, $this->customToken) = unserialize($data); + list($this->tokens, $this->defaultOptions, $this->options, $this->pattern, $this->staticPrefix, $this->regex, $this->variables, $this->defaults, $this->requirements, $this->suffix, $this->customToken) = $data; + $this->compiled = true; } } diff --git a/lib/util/sfNamespacedParameterHolder.class.php b/lib/util/sfNamespacedParameterHolder.class.php index 18eb76c67..757d86edd 100644 --- a/lib/util/sfNamespacedParameterHolder.class.php +++ b/lib/util/sfNamespacedParameterHolder.class.php @@ -366,11 +366,11 @@ public function addByRef(& $parameters, $ns = null) /** * Serializes the current instance. * - * @return array Objects instance + * @return string Objects instance */ public function serialize() { - return serialize(array($this->default_namespace, $this->parameters)); + return serialize($this->__serialize()); } /** @@ -380,9 +380,28 @@ public function serialize() */ public function unserialize($serialized) { - $data = unserialize($serialized); + $this->__unserialize(unserialize($serialized)); + } + + + /** + * Serializes the current instance for PHP 7.4+ + * + * @return array + */ + public function __serialize() + { + return array($this->default_namespace, $this->parameters); + } - $this->default_namespace = $data[0]; - $this->parameters = $data[1]; + /** + * Unserializes a sfParameterHolder instance. for PHP 7.4 + * + * @param array $data + */ + public function __unserialize($data) + { + $this->default_namespace = $data[0]; + $this->parameters = $data[1]; } } diff --git a/lib/util/sfParameterHolder.class.php b/lib/util/sfParameterHolder.class.php index 6f46b64f3..aecd57435 100644 --- a/lib/util/sfParameterHolder.class.php +++ b/lib/util/sfParameterHolder.class.php @@ -4,7 +4,7 @@ * This file is part of the symfony package. * (c) 2004-2006 Fabien Potencier * (c) 2004-2006 Sean Kerr - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -181,11 +181,11 @@ public function addByRef(& $parameters) /** * Serializes the current instance. * - * @return array Objects instance + * @return string Objects instance */ public function serialize() { - return serialize($this->parameters); + return serialize($this->__serialize()); } /** @@ -195,6 +195,26 @@ public function serialize() */ public function unserialize($serialized) { - $this->parameters = unserialize($serialized); + $this->__unserialize(unserialize($serialized)); + } + + /** + * Serializes the current instance for PHP 7.4+ + * + * @return Array + */ + public function __serialize() { + + return $this->parameters; + } + + /** + * Unserializes a sfParameterHolder instance. for PHP 7.4 + * + * @param array $data + */ + public function __unserialize($data) + { + $this->parameters = $data; } } diff --git a/lib/validator/sfValidatorError.class.php b/lib/validator/sfValidatorError.class.php index 5eab900ae..fc4fc6c33 100644 --- a/lib/validator/sfValidatorError.class.php +++ b/lib/validator/sfValidatorError.class.php @@ -109,7 +109,7 @@ public function getArguments($raw = false) * error messages: * * $i18n->__($error->getMessageFormat(), $error->getArguments()); - * + * * If no message format has been set in the validator, the exception standard * message is returned. * @@ -140,7 +140,7 @@ public function getMessageFormat() */ public function serialize() { - return serialize(array($this->validator, $this->arguments, $this->code, $this->message)); + return serialize($this->__serialize()); } /** @@ -151,6 +151,29 @@ public function serialize() */ public function unserialize($serialized) { - list($this->validator, $this->arguments, $this->code, $this->message) = unserialize($serialized); + $array = unserialize($serialized); + + $this->__unserialize($array); + } + + /** + * Serializes the current instance for php 7.4+ + * + * @return array + */ + public function __serialize() + { + return array($this->validator, $this->arguments, $this->code, $this->message); } + + /** + * Unserializes a sfValidatorError instance for php 7.4+ + * + * @param string $serialized A serialized sfValidatorError instance + */ + public function __unserialize($data) + { + list($this->validator, $this->arguments, $this->code, $this->message) = $data; + } + } diff --git a/lib/view/sfViewParameterHolder.class.php b/lib/view/sfViewParameterHolder.class.php index 5172c8aac..4cc6d636c 100644 --- a/lib/view/sfViewParameterHolder.class.php +++ b/lib/view/sfViewParameterHolder.class.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -165,11 +165,11 @@ public function setEscapingMethod($method) /** * Serializes the current instance. * - * @return array Objects instance + * @return string Objects instance */ public function serialize() { - return serialize(array($this->getAll(), $this->escapingMethod, $this->escaping)); + return serialize($this->__serialize()); } /** @@ -179,8 +179,27 @@ public function serialize() */ public function unserialize($serialized) { - list($this->parameters, $escapingMethod, $escaping) = unserialize($serialized); + $this->__unserialize(unserialize($serialized)); + } + + /** + * Serializes the current instance for PHP 7.4+ + * + * @return array + */ + public function __serialize() + { + return array($this->getAll(), $this->escapingMethod, $this->escaping); + } + /** + * Unserializes a sfParameterHolder instance. for PHP 7.4 + * + * @param array $data + */ + public function __unserialize($data) + { + list($this->parameters, $escapingMethod, $escaping) = $data; $this->initialize(sfContext::hasInstance() ? sfContext::getInstance()->getEventDispatcher() : new sfEventDispatcher()); $this->setEscapingMethod($escapingMethod); diff --git a/test/unit/response/sfResponseTest.php b/test/unit/response/sfResponseTest.php index 31aad5842..c6f357f41 100644 --- a/test/unit/response/sfResponseTest.php +++ b/test/unit/response/sfResponseTest.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) 2004-2006 Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -14,6 +14,8 @@ class myResponse extends sfResponse { function serialize() {} function unserialize($serialized) {} + function __serialize() {} + function __unserialize($data) {} } class fakeResponse diff --git a/test/unit/validator/sfValidatorErrorSchemaTest.php b/test/unit/validator/sfValidatorErrorSchemaTest.php index e7768a9a6..7ca40047f 100644 --- a/test/unit/validator/sfValidatorErrorSchemaTest.php +++ b/test/unit/validator/sfValidatorErrorSchemaTest.php @@ -187,6 +187,16 @@ public function unserialize($serialized) { throw new Exception('Not serializable'); } + + public function __serialize() + { + throw new Exception('Not serializable'); + } + + public function __unserialize($data) + { + throw new Exception('Not serializable'); + } } function will_crash($a) diff --git a/test/unit/validator/sfValidatorErrorTest.php b/test/unit/validator/sfValidatorErrorTest.php index 41b03f4c3..f3b37ea46 100644 --- a/test/unit/validator/sfValidatorErrorTest.php +++ b/test/unit/validator/sfValidatorErrorTest.php @@ -65,6 +65,16 @@ public function unserialize($serialized) { throw new Exception('Not serializable'); } + + public function __serialize() + { + throw new Exception('Not serializable'); + } + + public function __unserialize($data) + { + throw new Exception('Not serializable'); + } } function will_crash($a) From 029b0e7e03dd8a57a35a3ea41ec67a516bb14a1e Mon Sep 17 00:00:00 2001 From: Tybaze Date: Mon, 23 May 2022 10:41:36 +0200 Subject: [PATCH 03/23] PHP 8.0 & 8.1 > Deprecated of null to non-nullable internal function parameters Mainly ensure use of string instead of null / false by casting the variable into (string) Also fix method/function arguments with default value must be at the end. Thanks to @teymour https://github.com/FriendsOfSymfony1/symfony1/pull/265/commits/cba71a47894ca8a89f2a88a5cd9dcb637129dbeb --- lib/helper/DateHelper.php | 2 +- lib/helper/I18NHelper.php | 4 ++-- lib/i18n/sfDateFormat.class.php | 3 ++- .../lib/database/sfDoctrineConnectionProfiler.class.php | 2 +- .../lib/debug/sfWebDebugPanelDoctrine.class.php | 4 ++-- lib/routing/sfRoute.class.php | 4 ++-- lib/util/sfBrowserBase.class.php | 2 +- lib/util/sfInflector.class.php | 4 ++-- lib/util/sfToolkit.class.php | 2 +- lib/vendor/lime/lime.php | 2 +- lib/widget/sfWidgetFormDate.class.php | 2 +- lib/widget/sfWidgetFormTime.class.php | 4 ++-- lib/yaml/sfYamlInline.class.php | 2 +- lib/yaml/sfYamlParser.class.php | 2 +- .../apps/frontend/config/frontendConfiguration.class.php | 2 +- 15 files changed, 21 insertions(+), 20 deletions(-) diff --git a/lib/helper/DateHelper.php b/lib/helper/DateHelper.php index 564aae975..51265f48e 100644 --- a/lib/helper/DateHelper.php +++ b/lib/helper/DateHelper.php @@ -17,7 +17,7 @@ * @version SVN: $Id$ */ -function format_daterange($start_date, $end_date, $format = 'd', $full_text, $start_text, $end_text, $culture = null, $charset = null) +function format_daterange($start_date, $end_date, $format = 'd', $full_text = '', $start_text = '', $end_text = '', $culture = null, $charset = null) { if ($start_date != '' && $end_date != '') { diff --git a/lib/helper/I18NHelper.php b/lib/helper/I18NHelper.php index cde3e3352..95d285a32 100644 --- a/lib/helper/I18NHelper.php +++ b/lib/helper/I18NHelper.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) 2004-2006 Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -60,7 +60,7 @@ function __($text, $args = array(), $catalogue = 'messages') * * @return string Result of the translation */ -function format_number_choice($text, $args = array(), $number, $catalogue = 'messages') +function format_number_choice($text, $args = array(), $number = null, $catalogue = 'messages') { $translated = __($text, $args, $catalogue); diff --git a/lib/i18n/sfDateFormat.class.php b/lib/i18n/sfDateFormat.class.php index 80a5a571f..90b2aded3 100644 --- a/lib/i18n/sfDateFormat.class.php +++ b/lib/i18n/sfDateFormat.class.php @@ -239,9 +239,10 @@ public function format($time, $pattern = 'F', $inputPattern = null, $charset = ' } else { - $function = ucfirst($this->getFunctionName($pattern)); + $function = $this->getFunctionName($pattern); if ($function != null) { + $function = ucfirst($function); $fName = 'get'.$function; if (in_array($fName, $this->methods)) { diff --git a/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineConnectionProfiler.class.php b/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineConnectionProfiler.class.php index 0643cab71..e3824c7c2 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineConnectionProfiler.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineConnectionProfiler.class.php @@ -200,7 +200,7 @@ static public function fixParams($params) foreach ($params as $key => $param) { - if (strlen($param) >= 255) + if ($param && strlen($param) >= 255) { $params[$key] = '['.number_format(strlen($param) / 1024, 2).'Kb]'; } diff --git a/lib/plugins/sfDoctrinePlugin/lib/debug/sfWebDebugPanelDoctrine.class.php b/lib/plugins/sfDoctrinePlugin/lib/debug/sfWebDebugPanelDoctrine.class.php index e7477b34d..9c4bacf7d 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/debug/sfWebDebugPanelDoctrine.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/debug/sfWebDebugPanelDoctrine.class.php @@ -68,7 +68,7 @@ static public function listenToAddPanelEvent(sfEvent $event) /** * Returns an array of Doctrine query events. - * + * * @return array */ protected function getDoctrineEvents() @@ -116,7 +116,7 @@ protected function getSqlLogs() // interpolate parameters foreach ($params as $param) { - $param = htmlspecialchars($param, ENT_QUOTES, sfConfig::get('sf_charset')); + $param = htmlspecialchars((string) $param, ENT_QUOTES, sfConfig::get('sf_charset')); $query = join(var_export(is_scalar($param) ? $param : (string) $param, true), explode('?', $query, 2)); } diff --git a/lib/routing/sfRoute.class.php b/lib/routing/sfRoute.class.php index 5a0f0e508..05385fe6c 100644 --- a/lib/routing/sfRoute.class.php +++ b/lib/routing/sfRoute.class.php @@ -285,7 +285,7 @@ protected function generateWithTokens($parameters) switch ($token[0]) { case 'variable': - if (!$optional || !isset($this->defaults[$token[3]]) || $parameters[$token[3]] != $this->defaults[$token[3]]) + if (!$optional || !isset($this->defaults[$token[3]]) || (isset($parameters[$token[3]]) && $parameters[$token[3]] != $this->defaults[$token[3]])) { $url[] = urlencode($parameters[$token[3]]); $optional = false; @@ -791,7 +791,7 @@ protected function fixDefaults() } else { - $this->defaults[$key] = urldecode($value); + $this->defaults[$key] = urldecode((string) $value); } } } diff --git a/lib/util/sfBrowserBase.class.php b/lib/util/sfBrowserBase.class.php index 21d3de7da..c02c97e4f 100755 --- a/lib/util/sfBrowserBase.class.php +++ b/lib/util/sfBrowserBase.class.php @@ -908,7 +908,7 @@ public function doClickElement(DOMElement $item, $arguments = array(), $options } else { - $queryString = http_build_query($arguments, null, '&'); + $queryString = (is_array($arguments)) ? http_build_query($arguments, null, '&') : ''; $sep = false === strpos($url, '?') ? '?' : '&'; return array($url.($queryString ? $sep.$queryString : ''), 'get', array()); diff --git a/lib/util/sfInflector.class.php b/lib/util/sfInflector.class.php index 378d5e79e..f1676eb06 100644 --- a/lib/util/sfInflector.class.php +++ b/lib/util/sfInflector.class.php @@ -28,7 +28,7 @@ class sfInflector public static function camelize($lower_case_and_underscored_word) { - return strtr(ucwords(strtr($lower_case_and_underscored_word, array('/' => ':: ', '_' => ' ', '-' => ' '))), array(' ' => '')); + return strtr(ucwords(strtr((string) $lower_case_and_underscored_word, array('/' => ':: ', '_' => ' ', '-' => ' '))), array(' ' => '')); } /** @@ -40,7 +40,7 @@ public static function camelize($lower_case_and_underscored_word) */ public static function underscore($camel_cased_word) { - $tmp = $camel_cased_word; + $tmp = (string) $camel_cased_word; $tmp = str_replace('::', '/', $tmp); $tmp = sfToolkit::pregtr($tmp, array('/([A-Z]+)([A-Z][a-z])/' => '\\1_\\2', '/([a-z\d])([A-Z])/' => '\\1_\\2')); diff --git a/lib/util/sfToolkit.class.php b/lib/util/sfToolkit.class.php index b3bda1000..811df0edb 100644 --- a/lib/util/sfToolkit.class.php +++ b/lib/util/sfToolkit.class.php @@ -366,7 +366,7 @@ public static function replaceConstants($value) */ public static function pregtr($search, $replacePairs) { - return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search); + return preg_replace(array_keys($replacePairs), array_values($replacePairs), (string) $search); } /** diff --git a/lib/vendor/lime/lime.php b/lib/vendor/lime/lime.php index 53fdd0dd1..d087dd631 100644 --- a/lib/vendor/lime/lime.php +++ b/lib/vendor/lime/lime.php @@ -564,7 +564,7 @@ protected function find_caller($traces) return array($traces[$last]['file'], $traces[$last]['line']); } - public function handle_error($code, $message, $file, $line, $context) + public function handle_error($code, $message, $file, $line, $context = null) { if (!$this->options['error_reporting'] || ($code & error_reporting()) == 0) { diff --git a/lib/widget/sfWidgetFormDate.class.php b/lib/widget/sfWidgetFormDate.class.php index 96eba1a5d..c8ed674df 100644 --- a/lib/widget/sfWidgetFormDate.class.php +++ b/lib/widget/sfWidgetFormDate.class.php @@ -70,7 +70,7 @@ public function render($name, $value = null, $attributes = array(), $errors = ar } else { - $value = (string) $value == (string) (integer) $value ? (integer) $value : strtotime($value); + $value = (string) $value == (string) (integer) $value ? (integer) $value : strtotime( (string) $value); if (false === $value) { $value = $default; diff --git a/lib/widget/sfWidgetFormTime.class.php b/lib/widget/sfWidgetFormTime.class.php index d68f375df..5917ed841 100644 --- a/lib/widget/sfWidgetFormTime.class.php +++ b/lib/widget/sfWidgetFormTime.class.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -72,7 +72,7 @@ public function render($name, $value = null, $attributes = array(), $errors = ar } else { - $value = ctype_digit($value) ? (integer) $value : strtotime($value); + $value = ctype_digit( (string) $value) ? (integer) $value : strtotime( (string) $value); if (false === $value) { $value = $default; diff --git a/lib/yaml/sfYamlInline.class.php b/lib/yaml/sfYamlInline.class.php index ad9342099..2b7ccd6c5 100644 --- a/lib/yaml/sfYamlInline.class.php +++ b/lib/yaml/sfYamlInline.class.php @@ -97,7 +97,7 @@ static public function dump($value) return 'true'; case false === $value: return 'false'; - case ctype_digit($value): + case (is_string($value) && ctype_digit($value)): return is_string($value) ? "'$value'" : (int) $value; case is_numeric($value): return is_infinite($value) ? str_ireplace('INF', '.Inf', (string) $value) : (is_string($value) ? "'$value'" : $value); diff --git a/lib/yaml/sfYamlParser.class.php b/lib/yaml/sfYamlParser.class.php index 69b9f2651..58aa6b8eb 100644 --- a/lib/yaml/sfYamlParser.class.php +++ b/lib/yaml/sfYamlParser.class.php @@ -421,7 +421,7 @@ protected function parseValue($value) { $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : ''; - return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers)); + return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs((int) $modifiers)); } else { diff --git a/test/functional/fixtures/apps/frontend/config/frontendConfiguration.class.php b/test/functional/fixtures/apps/frontend/config/frontendConfiguration.class.php index 58e520532..9b0b90c90 100644 --- a/test/functional/fixtures/apps/frontend/config/frontendConfiguration.class.php +++ b/test/functional/fixtures/apps/frontend/config/frontendConfiguration.class.php @@ -11,7 +11,7 @@ public function configure() public function filter_parameters(sfEvent $event, $parameters) { - if (false !== stripos($event->getSubject()->getHttpHeader('user-agent'), 'iPhone')) + if (false !== stripos((string) $event->getSubject()->getHttpHeader('user-agent'), 'iPhone')) { $event->getSubject()->setRequestFormat('iphone'); } From dcb1ce3a6ed98127b604e1bc7b2c380367a1d581 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Mon, 23 May 2022 12:59:20 +0200 Subject: [PATCH 04/23] PHP 8.1 > strftime deprecated. 2 possible workaround, use partial implementation with php date method or use IntlDateFormatter. As symfony1 is not intended to evolve, it should not rely on currently unused PHP-Extension (nor update composer.json). I propose a fix to replace "strftime" by "date", with a translation of format for PHP 8.1+ It will lose the ability of translating date of logs (does anybody use it ?) and it will deprecated a few strftime format (probably not used) Performances should remains OK I only tested it with a few formats (the default one and a few others) If you need some missing strftime formats, please add them. --- lib/log/sfFileLogger.class.php | 60 +++++++++++++++++++++++++++++- test/unit/log/sfFileLoggerTest.php | 8 ++-- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/lib/log/sfFileLogger.class.php b/lib/log/sfFileLogger.class.php index dfb610a8e..eceb47255 100644 --- a/lib/log/sfFileLogger.class.php +++ b/lib/log/sfFileLogger.class.php @@ -92,7 +92,7 @@ public function initialize(sfEventDispatcher $dispatcher, $options = array()) * Logs a message. * * @param string $message Message - * @param int $priority Message priority + * @param int $priority Message priority */ protected function doLog($message, $priority) { @@ -100,7 +100,7 @@ protected function doLog($message, $priority) fwrite($this->fp, strtr($this->format, array( '%type%' => $this->type, '%message%' => $message, - '%time%' => strftime($this->timeFormat), + '%time%' => self::strftime($this->timeFormat), '%priority%' => $this->getPriority($priority), '%EOL%' => PHP_EOL, ))); @@ -129,4 +129,60 @@ public function shutdown() fclose($this->fp); } } + + /** + * @param $format + * @return false|string + */ + public static function strftime($format) + { + if (version_compare(PHP_VERSION, '8.1.0') < 0) { + return strftime($format); + } + return date(self::_strftimeFormatToDateFormat($format)); + } + + /** + * Try to Convert a strftime to date format + * + * Unable to find a perfect implementation, based on those one (Each contains some errors) + * https://github.com/Fabrik/fabrik/blob/master/plugins/fabrik_element/date/date.php + * https://gist.github.com/mcaskill/02636e5970be1bb22270 + * https://stackoverflow.com/questions/22665959/using-php-strftime-using-date-format-string + * + * Limitation: + * - Do not apply translation + * - Some few strftime format could be broken (low probability to be used on logs) + * + * Private: because it should not be used outside of this scope + * + * A better solution is to use : IntlDateFormatter, but it will require to load a new php extension, which could break some setup. + * + * @return array|string|string[] + */ + private static function _strftimeFormatToDateFormat($strftimeFormat) { + + // Missing %V %C %g %G + $search = array( + '%a', '%A', '%d', '%e', '%u', + '%w', '%W', '%b', '%h', '%B', + '%m', '%y', '%Y', '%D', '%F', + '%x', '%n', '%t', '%H', '%k', + '%I', '%l', '%M', '%p', '%P', + '%r' /* %I:%M:%S %p */, '%R' /* %H:%M */, '%S', '%T' /* %H:%M:%S */, '%X', '%z', '%Z', + '%c', '%s', '%j', + '%%'); + + $replace = array( + 'D', 'l', 'd', 'j', 'N', + 'w', 'W', 'M', 'M', 'F', + 'm', 'y', 'Y', 'm/d/y', 'Y-m-d', + 'm/d/y', "\n", "\t", 'H', 'G', + 'h', 'g', 'i', 'A', 'a', + 'h:i:s A', 'H:i', 's', 'H:i:s', 'H:i:s', 'O', 'T', + 'D M j H:i:s Y' /*Tue Feb 5 00:45:10 2009*/, 'U', 'z', + '%'); + + return str_replace($search, $replace, $strftimeFormat); + } } diff --git a/test/unit/log/sfFileLoggerTest.php b/test/unit/log/sfFileLoggerTest.php index 81fa52a58..3fbb66f9b 100644 --- a/test/unit/log/sfFileLoggerTest.php +++ b/test/unit/log/sfFileLoggerTest.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) 2004-2006 Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -61,7 +61,7 @@ protected function getPriority($priority) unlink($file); $logger = new TestLogger($dispatcher, array('file' => $file)); $logger->log('foo'); -$t->is(file_get_contents($file), strftime($logger->getTimeFormat()).' symfony [*6*] foo'.PHP_EOL, '->initialize() can take a format option'); +$t->is(file_get_contents($file), TestLogger::strftime($logger->getTimeFormat()).' symfony [*6*] foo'.PHP_EOL, '->initialize() can take a format option'); unlink($file); $logger = new TestLogger($dispatcher, array('file' => $file, 'format' => '%message%')); @@ -73,14 +73,14 @@ protected function getPriority($priority) unlink($file); $logger = new TestLogger($dispatcher, array('file' => $file, 'time_format' => '%Y %m %d')); $logger->log('foo'); -$t->is(file_get_contents($file), strftime($logger->getTimeFormat()).' symfony [*6*] foo'.PHP_EOL, '->initialize() can take a format option'); +$t->is(file_get_contents($file), TestLogger::strftime($logger->getTimeFormat()).' symfony [*6*] foo'.PHP_EOL, '->initialize() can take a format option'); // option: type $t->diag('option: type'); unlink($file); $logger = new TestLogger($dispatcher, array('file' => $file, 'type' => 'foo')); $logger->log('foo'); -$t->is(file_get_contents($file), strftime($logger->getTimeFormat()).' foo [*6*] foo'.PHP_EOL, '->initialize() can take a format option'); +$t->is(file_get_contents($file), TestLogger::strftime($logger->getTimeFormat()).' foo [*6*] foo'.PHP_EOL, '->initialize() can take a format option'); // ->shutdown() $t->diag('->shutdown()'); From 8450b13a012ac8fc216231571f95630eb073a354 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 14:31:05 +0200 Subject: [PATCH 05/23] PHP 8.1 > Unit Test sfException> fileExcerpt file can be null, and PHP 8.1 do not allow null on is_readable() sfBrowser> Move sf_test conf before getContext, because getContext can throw some sfException, which will raise some printStackTrace, hidden by another Exception "header already sent ..." lime.php> some trace can have no "file" (internal methods call) lime.php> handle_exception can handle Error/Throwable, not avaialble under php7.2: remove typing sfTestFunctionalBase> can throw exception Fix Select Unit test NewActivePendingExpired. DomDocument on recent php return a list of values, not concatened ones. Fix SessionStorage UnitTest. sfSessionStorage could not be restarted. Flag $sessionStarted as false when shutdown to avoid error during unit test which can start several sfSessionStorage Storage need to be shutdown to avoid: PHP Warning: session_name(): Session name cannot be changed when a session is active --- lib/exception/sfException.class.php | 4 ++++ .../test/functional/AdminGenBrowser.class.php | 4 ++-- lib/storage/sfSessionStorage.class.php | 1 + lib/test/sfTestFunctionalBase.class.php | 2 +- lib/util/sfBrowser.class.php | 5 +++-- lib/vendor/lime/lime.php | 19 ++++++++++++------- test/unit/storage/sfSessionStorageTest.php | 1 + 7 files changed, 24 insertions(+), 12 deletions(-) diff --git a/lib/exception/sfException.class.php b/lib/exception/sfException.class.php index 3611caada..fbd742596 100644 --- a/lib/exception/sfException.class.php +++ b/lib/exception/sfException.class.php @@ -366,6 +366,10 @@ static protected function formatArrayAsHtml($values) */ static protected function fileExcerpt($file, $line) { + // $file can be null for RuntimeException + if($file === null) { + return ''; + } if (is_readable($file)) { $content = preg_split('#
#', preg_replace('/^(.*)<\/code>$/s', '$1', highlight_file($file, true))); diff --git a/lib/plugins/sfDoctrinePlugin/test/functional/AdminGenBrowser.class.php b/lib/plugins/sfDoctrinePlugin/test/functional/AdminGenBrowser.class.php index a5efd75f7..cb29fe83e 100644 --- a/lib/plugins/sfDoctrinePlugin/test/functional/AdminGenBrowser.class.php +++ b/lib/plugins/sfDoctrinePlugin/test/functional/AdminGenBrowser.class.php @@ -152,7 +152,7 @@ protected function _testEnumDropdown() $this-> get('/subscriptions/new')-> with('response')->begin()-> - checkElement('select', 'NewActivePendingExpired')-> + checkElement('select', '/^New\R?Active\R?Pending\R?Expired\R?$/m')-> end() ; } @@ -237,7 +237,7 @@ protected function _runAdminGenModuleSanityCheck($model, $module) } protected function _generateAdminGenModule($model, $module) - { + { $this->info('Generating admin gen module "' . $module . '"'); $task = new sfDoctrineGenerateAdminTask($this->getContext()->getEventDispatcher(), new sfFormatter()); $task->run(array('application' => 'backend', 'route_or_model' => $model)); diff --git a/lib/storage/sfSessionStorage.class.php b/lib/storage/sfSessionStorage.class.php index 57ff59973..f11337d39 100644 --- a/lib/storage/sfSessionStorage.class.php +++ b/lib/storage/sfSessionStorage.class.php @@ -190,5 +190,6 @@ public function shutdown() { // don't need a shutdown procedure because read/write do it in real-time session_write_close(); + self::$sessionStarted = false; } } diff --git a/lib/test/sfTestFunctionalBase.class.php b/lib/test/sfTestFunctionalBase.class.php index 2f3da782c..97ac815a6 100644 --- a/lib/test/sfTestFunctionalBase.class.php +++ b/lib/test/sfTestFunctionalBase.class.php @@ -478,7 +478,7 @@ static public function handlePhpError($errno, $errstr, $errfile, $errline) /** * Exception handler for the current test browser instance. * - * @param Exception $exception The exception + * @param Throwable $exception The exception */ function handleException($exception) { diff --git a/lib/util/sfBrowser.class.php b/lib/util/sfBrowser.class.php index a4f89691c..ad45e1225 100644 --- a/lib/util/sfBrowser.class.php +++ b/lib/util/sfBrowser.class.php @@ -28,11 +28,12 @@ class sfBrowser extends sfBrowserBase */ protected function doCall() { + // Before getContext, it can trigger some + sfConfig::set('sf_test', true); + // recycle our context object $this->context = $this->getContext(true); - sfConfig::set('sf_test', true); - // we register a fake rendering filter sfConfig::set('sf_rendering_filter', array('sfFakeRenderingFilter', null)); diff --git a/lib/vendor/lime/lime.php b/lib/vendor/lime/lime.php index d087dd631..8020c94b5 100644 --- a/lib/vendor/lime/lime.php +++ b/lib/vendor/lime/lime.php @@ -520,11 +520,11 @@ public function error($message, $file = null, $line = null, array $traces = arra { $this->output->error($message, $file, $line, $traces); - $this->results['stats']['errors'][] = array( - 'message' => $message, - 'file' => $file, - 'line' => $line, - ); + $this->results['stats']['errors'][] = array( + 'message' => $message, + 'file' => $file, + 'line' => $line, + ); } protected function update_stats() @@ -553,7 +553,8 @@ protected function find_caller($traces) $t = array_reverse($traces); foreach ($t as $trace) { - if (isset($trace['object']) && $this->is_test_object($trace['object'])) + // In internal calls, like error_handle, 'file' will be missing + if (isset($trace['object']) && $this->is_test_object($trace['object']) && isset($trace['file'])) { return array($trace['file'], $trace['line']); } @@ -587,7 +588,11 @@ public function handle_error($code, $message, $file, $line, $context = null) $this->error($type.': '.$message, $file, $line, $trace); } - public function handle_exception(Throwable $exception) + /** + * @param Throwable $exception only available on php7 + * @return bool + */ + public function handle_exception($exception) { $this->error(get_class($exception).': '.$exception->getMessage(), $exception->getFile(), $exception->getLine(), $exception->getTrace()); diff --git a/test/unit/storage/sfSessionStorageTest.php b/test/unit/storage/sfSessionStorageTest.php index ddc1f4a6b..2349ee02b 100644 --- a/test/unit/storage/sfSessionStorageTest.php +++ b/test/unit/storage/sfSessionStorageTest.php @@ -26,6 +26,7 @@ { $storage = new sfSessionStorage(); $t->pass('->__construct() does not throw an exception when not provided with options'); + $storage->shutdown(); } catch (InvalidArgumentException $e) { From 9cb7fb482b1b91fa22a7f5f78f3055a3def5130f Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 15:31:25 +0200 Subject: [PATCH 06/23] Fix lime message: "An uncaught exception has been thrown" do not have "error" value uncaught exception does not populate error field --- lib/vendor/lime/lime.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/vendor/lime/lime.php b/lib/vendor/lime/lime.php index 8020c94b5..5b3c16560 100644 --- a/lib/vendor/lime/lime.php +++ b/lib/vendor/lime/lime.php @@ -1103,7 +1103,9 @@ function lime_shutdown() $this->output->comment(sprintf(' at %s line %s', $this->get_relative_file($testsuite['tests'][$testcase]['file']).$this->extension, $testsuite['tests'][$testcase]['line'])); $this->output->info(' '.$testsuite['tests'][$testcase]['message']); - $this->output->echoln($testsuite['tests'][$testcase]['error'], null, false); + if(isset($testsuite['tests'][$testcase]['error'])) { + $this->output->echoln($testsuite['tests'][$testcase]['error'], null, false); + } } } } From 25a5e71b67b0522d93ad9a0130b20826a6d57e90 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 18:12:21 +0200 Subject: [PATCH 07/23] PHP 8.1 > uasort(): Returning bool from comparison function is deprecated, return an integer less than, equal to, or greater than zero --- lib/routing/sfRoute.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/routing/sfRoute.class.php b/lib/routing/sfRoute.class.php index 05385fe6c..a0093b18e 100644 --- a/lib/routing/sfRoute.class.php +++ b/lib/routing/sfRoute.class.php @@ -264,7 +264,7 @@ public function generate($params, $context = array(), $absolute = false) static private function generateCompareVarsByStrlen($a, $b) { - return strlen($a) < strlen($b); + return (strlen($a) < strlen($b)) ? 1 : -1; } /** From 09fc710a73336971f816f991b8a1011c1d31c2e0 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 18:30:50 +0200 Subject: [PATCH 08/23] Fix ValueError: DOMDocument::loadHTML(): Argument #1 ($source) must not be empty --- lib/test/sfTesterResponse.class.php | 12 +++++++----- lib/util/sfBrowserBase.class.php | 4 +++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/test/sfTesterResponse.class.php b/lib/test/sfTesterResponse.class.php index 4fca01923..1a1c7a86a 100644 --- a/lib/test/sfTesterResponse.class.php +++ b/lib/test/sfTesterResponse.class.php @@ -49,7 +49,9 @@ public function initialize() } else { - @$this->dom->loadHTML($this->response->getContent()); + if($this->response->getContent()) { + @$this->dom->loadHTML($this->response->getContent()); + } } $this->domCssSelector = new sfDomCssSelector($this->dom); } @@ -120,10 +122,10 @@ public function checkElement($selector, $value = true, $options = array()) /** * Checks that a form is rendered correctly. - * + * * @param sfForm|string $form A form object or the name of a form class * @param string $selector CSS selector for the root form element for this form - * + * * @return sfTestFunctionalBase|sfTester */ public function checkForm($form, $selector = 'form') @@ -333,11 +335,11 @@ public function isHeader($key, $value) /** * Tests if a cookie was set. - * + * * @param string $name * @param string $value * @param array $attributes Other cookie attributes to check (expires, path, domain, etc) - * + * * @return sfTestFunctionalBase|sfTester */ public function setsCookie($name, $value = null, $attributes = array()) diff --git a/lib/util/sfBrowserBase.class.php b/lib/util/sfBrowserBase.class.php index c02c97e4f..4ec39098a 100755 --- a/lib/util/sfBrowserBase.class.php +++ b/lib/util/sfBrowserBase.class.php @@ -363,7 +363,9 @@ public function call($uri, $method = 'get', $parameters = array(), $changeStack } else { - @$this->dom->loadHTML($response->getContent()); + if($response->getContent()) { + @$this->dom->loadHTML($response->getContent()); + } } $this->domCssSelector = new sfDomCssSelector($this->dom); } From df2ec65dbe8729ef7495a8a7f45b44c823dc7e72 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 19:36:56 +0200 Subject: [PATCH 09/23] PHP 8.0 > fread()/count() behavior ValueError: fread(): Argument #2 ($length) must be greater than 0 TypeError: count(): Argument #1 ($value) must be of type Countable|array Foo Given Use Symfony Polyfill https://github.com/symfony/polyfill/commit/d330c0094a47d8edceeea1ed553d6e08215a9fc2 TypeError: count(): Argument #1 ($value) must be of type Countable|array, string given Do not use Symfony pollyfill, is_array is enought --- lib/cache/sfFileCache.class.php | 6 +++- .../sfOutputEscaperObjectDecorator.class.php | 8 ++++-- lib/i18n/sfCultureInfo.class.php | 28 +++++++++---------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/lib/cache/sfFileCache.class.php b/lib/cache/sfFileCache.class.php index dcd03f345..2997d6c96 100644 --- a/lib/cache/sfFileCache.class.php +++ b/lib/cache/sfFileCache.class.php @@ -256,7 +256,11 @@ protected function read($path, $type = self::READ_DATA) fseek($fp, 0, SEEK_END); $length = ftell($fp) - 24; fseek($fp, 24); - $data[self::READ_DATA] = @fread($fp, $length); + if($length > 0) { + $data[self::READ_DATA] = @fread($fp, $length); + } else { + $data[self::READ_DATA] = ''; + } } } else diff --git a/lib/escaper/sfOutputEscaperObjectDecorator.class.php b/lib/escaper/sfOutputEscaperObjectDecorator.class.php index fe506d9c1..86d0ae71e 100644 --- a/lib/escaper/sfOutputEscaperObjectDecorator.class.php +++ b/lib/escaper/sfOutputEscaperObjectDecorator.class.php @@ -111,13 +111,17 @@ public function __isset($key) /** * Returns the size of the object if it implements Countable (is required by the Countable interface). * - * It returns 1 if other cases (which is the default PHP behavior in such a case). + * It returns 1 if other cases (which was the default PHP behavior in such a case before php 7.3). * * @return int The size of the object */ #[\ReturnTypeWillChange] public function count() { - return count($this->value); + // See https://github.com/symfony/polyfill/commit/d330c0094a47d8edceeea1ed553d6e08215a9fc2 + if(is_array($this->value) || $this->value instanceof Countable || $this->value instanceof ResourceBundle || $this->value instanceof SimpleXmlElement) { + return count($this->value); + } + return 1; } } diff --git a/lib/i18n/sfCultureInfo.class.php b/lib/i18n/sfCultureInfo.class.php index a14fd7c0f..aaf8d3bb7 100644 --- a/lib/i18n/sfCultureInfo.class.php +++ b/lib/i18n/sfCultureInfo.class.php @@ -92,11 +92,11 @@ class sfCultureInfo * @var sfNumberFormatInfo */ protected $numberFormat; - + /** * A list of properties that are accessable/writable. * @var array - */ + */ protected $properties = array(); /** @@ -191,9 +191,9 @@ public function __set($name, $value) } /** - * Initializes a new instance of the sfCultureInfo class based on the + * Initializes a new instance of the sfCultureInfo class based on the * culture specified by name. E.g. new sfCultureInfo('en_AU'); - * The culture indentifier must be of the form + * The culture indentifier must be of the form * "_(country/region/variant)". * * @param string $culture a culture name, e.g. "en_AU". @@ -323,7 +323,7 @@ protected function loadCultureData($culture) * this function. * * @param string $filename the ICU data filename - * @return array ICU data + * @return array ICU data */ protected function &getData($filename) { @@ -347,7 +347,7 @@ protected function &getData($filename) * Use merge=true to return the ICU including the parent culture. * E.g. The currency data for a variant, say "en_AU" contains one * entry, the currency for AUD, the other currency data are stored - * in the "en" data file. Thus to retrieve all the data regarding + * in the "en" data file. Thus to retrieve all the data regarding * currency for "en_AU", you need to use findInfo("Currencies,true);. * * @param string $path the data you want to find. @@ -429,9 +429,9 @@ protected function searchArray($info, $path = '/') } } } - + /** - * Gets the culture name in the format + * Gets the culture name in the format * "_(country/regioncode2)". * * @return string culture name. @@ -516,7 +516,7 @@ public function getEnglishName() $culture = $this->getInvariantCulture(); $language = $culture->findInfo("Languages/{$lang}"); - if (count($language) == 0) + if (is_array($language) && count($language) == 0) { return $this->culture; } @@ -547,7 +547,7 @@ static function getInvariantCulture() } /** - * Gets a value indicating whether the current sfCultureInfo + * Gets a value indicating whether the current sfCultureInfo * represents a neutral culture. Returns true if the culture * only contains two characters. * @@ -590,7 +590,7 @@ public function setNumberFormat($numberFormat) } /** - * Gets the sfCultureInfo that represents the parent culture of the + * Gets the sfCultureInfo that represents the parent culture of the * current sfCultureInfo * * @return sfCultureInfo parent culture information. @@ -606,14 +606,14 @@ public function getParent() } /** - * Gets the list of supported cultures filtered by the specified + * Gets the list of supported cultures filtered by the specified * culture type. This is an EXPENSIVE function, it needs to traverse * a list of ICU files in the data directory. * This function can be called statically. * * @param int $type culture type, sfCultureInfo::ALL, sfCultureInfo::NEUTRAL * or sfCultureInfo::SPECIFIC. - * @return array list of culture information available. + * @return array list of culture information available. */ static function getCultures($type = sfCultureInfo::ALL) { @@ -719,7 +719,7 @@ public function getLanguage($code) * * @param array $countries An array of countries used to restrict the returned array (null by default, which means all countries) * - * @return array a list of localized country names. + * @return array a list of localized country names. */ public function getCountries($countries = null) { From 42112ab7f22b6b5d4523d51e190511f1bb11912c Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 22:25:36 +0200 Subject: [PATCH 10/23] Fix Declaration of sfPearRestTest::downloadHttp($url, $lastmodified = null, $accept = false) must be compatible with sfPearRest::downloadHttp($url, $lastmodified = null, $accept = false, $channel = false) --- lib/plugin/sfPearRest.class.php | 4 ++-- test/unit/plugin/sfPearRestTest.class.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/plugin/sfPearRest.class.php b/lib/plugin/sfPearRest.class.php index f17b6deb3..72cb66960 100644 --- a/lib/plugin/sfPearRest.class.php +++ b/lib/plugin/sfPearRest.class.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -23,7 +23,7 @@ class sfPearRest extends PEAR_REST /** * @see PEAR_REST::downloadHttp() */ - public function downloadHttp($url, $lastmodified = null, $accept = false) + public function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false) { return parent::downloadHttp($url, $lastmodified, array_merge(false !== $accept ? $accept : array(), array("\r\nX-SYMFONY-VERSION: ".SYMFONY_VERSION))); } diff --git a/test/unit/plugin/sfPearRestTest.class.php b/test/unit/plugin/sfPearRestTest.class.php index 251f913fc..df3138708 100644 --- a/test/unit/plugin/sfPearRestTest.class.php +++ b/test/unit/plugin/sfPearRestTest.class.php @@ -3,7 +3,7 @@ /* * This file is part of the symfony package. * (c) Fabien Potencier - * + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -21,7 +21,7 @@ class sfPearRestTest extends sfPearRest /** * @see PEAR_REST::downloadHttp() */ - public function downloadHttp($url, $lastmodified = null, $accept = false) + public function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false) { try { From 29ab2a79aa8e25d1df2a430a86a01f528ff5d730 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 9 Jun 2022 22:00:51 +0200 Subject: [PATCH 11/23] PHP 8.0 > mktime update 8.0.0 hour is no longer optional. 8.0.0 minute, second, month, day and year are nullable now. --- lib/i18n/sfI18N.class.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/i18n/sfI18N.class.php b/lib/i18n/sfI18N.class.php index b64ebccb4..5478e6d73 100644 --- a/lib/i18n/sfI18N.class.php +++ b/lib/i18n/sfI18N.class.php @@ -271,6 +271,15 @@ public function getTimestampForCulture($dateTime, $culture = null) list($day, $month, $year) = $this->getDateForCulture($dateTime, null === $culture ? $this->culture : $culture); list($hour, $minute) = $this->getTimeForCulture($dateTime, null === $culture ? $this->culture : $culture); + // mktime behavior change with php8 + // $hour become not nullable + if (!$hour) { + $hour = 0; + } + // Before 8.0, $minutes value to null, was casted as (int)0 + if (!$minute) { + $minute = 0; + } return null === $day ? null : mktime($hour, $minute, 0, $month, $day, $year); } From 12f7b4caae6dd33a3b609ca6b9a4e5e0c671f5be Mon Sep 17 00:00:00 2001 From: Tybaze Date: Fri, 10 Jun 2022 08:53:35 +0200 Subject: [PATCH 12/23] Fix sfWebResponse->getContentType() return a string not an array --- lib/response/sfWebResponse.class.php | 2 +- test/unit/response/sfWebResponseTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/response/sfWebResponse.class.php b/lib/response/sfWebResponse.class.php index 9f25c50f3..af69e38e2 100644 --- a/lib/response/sfWebResponse.class.php +++ b/lib/response/sfWebResponse.class.php @@ -312,7 +312,7 @@ public function getCharset() /** * Gets response content type. * - * @return array + * @return string */ public function getContentType() { diff --git a/test/unit/response/sfWebResponseTest.php b/test/unit/response/sfWebResponseTest.php index 0697da8d8..916a8298c 100644 --- a/test/unit/response/sfWebResponseTest.php +++ b/test/unit/response/sfWebResponseTest.php @@ -132,7 +132,7 @@ public function normalizeHeaderName($name) $response->setContentType('text/xml'); $response->setContentType('text/html'); -$t->is(count($response->getHttpHeader('content-type')), 1, '->setContentType() overrides previous content type if replace is true'); +$t->is($response->getHttpHeader('content-type'), 'text/html; charset=ISO-8859-1', '->setContentType() overrides previous content type if replace is true'); // ->getTitle() ->setTitle() ->prependTitle $t->diag('->getTitle() ->setTitle() ->prependTitle()'); From cae793e1ac19124d1251420bb0833d840355ca63 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Fri, 10 Jun 2022 09:26:26 +0200 Subject: [PATCH 13/23] Fix sfDoctrineTester, string cannot be accessed as array --- .../sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php b/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php index 8ce1c985c..48fd0374b 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php @@ -65,7 +65,7 @@ public function check($model, $query, $value = true) } $operator = '='; - if ('!' == $condition[0]) + if (strlen($condition) && '!' == substr($condition,0,1)) { $operator = false !== strpos($condition, '%') ? 'NOT LIKE' : '!='; $condition = substr($condition, 1); @@ -103,7 +103,7 @@ public function check($model, $query, $value = true) /** * Outputs some debug information about queries run during the current request. - * + * * @param integer|string $limit Either an integer to return the last many queries, a regular expression or a substring to search for */ public function debug($limit = null) From 7341b43844efd3720c706f48e3c9341f7861e478 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Fri, 10 Jun 2022 12:52:25 +0200 Subject: [PATCH 14/23] PHP 8.0 > Fix is_numeric behavior with trailing empty char Numeric strings ending with whitespace ("42 ") will now return true. Previously, false was return instead. Use same fix has main maintened Yaml lib : https://github.com/symfony/yaml/commit/4152e36b0f305c2a57aa0233dee56ec27bca4f06 + performance improvement https://github.com/symfony/yaml/commit/2b5f2ae892b489e51d81616fbc475c8238b533dc --- lib/yaml/sfYamlInline.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yaml/sfYamlInline.class.php b/lib/yaml/sfYamlInline.class.php index 2b7ccd6c5..840f3fa7a 100644 --- a/lib/yaml/sfYamlInline.class.php +++ b/lib/yaml/sfYamlInline.class.php @@ -99,7 +99,7 @@ static public function dump($value) return 'false'; case (is_string($value) && ctype_digit($value)): return is_string($value) ? "'$value'" : (int) $value; - case is_numeric($value): + case is_numeric($value) && false === strpbrk($value, "\f\n\r\t\v"): return is_infinite($value) ? str_ireplace('INF', '.Inf', (string) $value) : (is_string($value) ? "'$value'" : $value); case false !== strpos($value, "\n") || false !== strpos($value, "\r"): return sprintf('"%s"', str_replace(array('"', "\n", "\r"), array('\\"', '\n', '\r'), $value)); From b191cb8a43789dde46435b472edeff268f7642a2 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Fri, 10 Jun 2022 14:31:05 +0200 Subject: [PATCH 15/23] PHP 8.0 > String to Number Comparison. When $previousIndent was equal to 0, and $matches['indent'] = " " PHP(before 8.0)> (0 != " ") ==> false PHP8.0+ > (0 != " ") ==> true In order to keep "false" value we avoid "0" as a valid value. More details here why here: https://www.php.net/manual/en/migration80.incompatible.php --- lib/yaml/sfYamlParser.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yaml/sfYamlParser.class.php b/lib/yaml/sfYamlParser.class.php index 58aa6b8eb..ed5b179ee 100644 --- a/lib/yaml/sfYamlParser.class.php +++ b/lib/yaml/sfYamlParser.class.php @@ -474,7 +474,7 @@ protected function parseFoldedScalar($separator, $indicator = '', $indentation = if (preg_match('#^(?P {'.strlen($textIndent).',})(?P.+)$#u', $this->currentLine, $matches)) { - if (' ' == $separator && $previousIndent != $matches['indent']) + if (' ' == $separator && ($previousIndent && $previousIndent != $matches['indent'])) { $text = substr($text, 0, -1)."\n"; } From 956cb1aaef2543f56cfb18bf91f91cac66e00b4a Mon Sep 17 00:00:00 2001 From: Tybaze Date: Mon, 23 May 2022 13:00:35 +0200 Subject: [PATCH 16/23] PHP 8.1 > Change support to PHP 8.1 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 900179110..e5147ca4d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ All the enhancements and BC breaks are listed in the [WHATS_NEW](https://github. - [DIC](https://github.com/FriendsOfSymfony1/symfony1/wiki/ServiceContainer) - Composer support -- PHP 7.2 support +- PHP 8.1 support - performance boost - new widgets & validators - some tickets fixed from the symfony trac From b0cb92e75edcc8dd7e8186e7b31a67bd1768c675 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Fri, 10 Jun 2022 19:00:21 +0200 Subject: [PATCH 17/23] Fix UnitTest application/x-sharedlib /bin/ls can be reported as: - application/x-sharedlib - application/x-executable - application/x-pie-executable --- test/unit/validator/sfValidatorFileTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/validator/sfValidatorFileTest.php b/test/unit/validator/sfValidatorFileTest.php index 42463acfa..d7d101d6d 100755 --- a/test/unit/validator/sfValidatorFileTest.php +++ b/test/unit/validator/sfValidatorFileTest.php @@ -105,7 +105,7 @@ public function getMimeTypesFromCategory($category) $v = new testValidatorFile(); $t->is($v->guessFromFileBinary($tmpDir.'/test.txt'), 'text/plain', '->guessFromFileBinary() guesses the type of a given file'); $t->is($v->guessFromFileBinary($tmpDir.'/foo.txt'), null, '->guessFromFileBinary() returns null if the file type is not guessable'); -$t->is($v->guessFromFileBinary('/bin/ls'), (PHP_OS != 'Darwin') ? 'application/x-pie-executable' : 'application/octet-stream', '->guessFromFileBinary() returns correct type if file is guessable'); +$t->like($v->guessFromFileBinary('/bin/ls'), (PHP_OS != 'Darwin') ? '/^application\/x-(pie-executable|executable|sharedlib)$/' : '/^application/octet-stream$/', '->guessFromFileBinary() returns correct type if file is guessable'); $t->is($v->guessFromFileBinary('-test'), null, '->guessFromFileBinary() returns null if file path has leading dash'); // ->getMimeType() From bb221418824b1251d9ff5964ff3295285ede2f32 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Fri, 10 Jun 2022 19:26:51 +0200 Subject: [PATCH 18/23] PHP 8.1 > mysqli_report revert to off https://php.watch/versions/8.1/mysqli-error-mode --- lib/database/sfMySQLiDatabase.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/database/sfMySQLiDatabase.class.php b/lib/database/sfMySQLiDatabase.class.php index e4814794a..bdc8be447 100644 --- a/lib/database/sfMySQLiDatabase.class.php +++ b/lib/database/sfMySQLiDatabase.class.php @@ -29,6 +29,9 @@ class sfMySQLiDatabase extends sfMySQLDatabase */ protected function getConnectMethod($persistent) { + // PHP 8.1 Activate Exception per default, revert behavior to "return false" + mysqli_report(MYSQLI_REPORT_OFF); + return 'mysqli_connect'; } From d0d0d122e8bb2b5197be327ff89ab3a2291b0ca0 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Thu, 7 Jul 2022 11:13:16 +0200 Subject: [PATCH 19/23] Refactor code and apply Coding Style fixes --- lib/cache/sfFileCache.class.php | 8 ++++++-- lib/escaper/sfOutputEscaperObjectDecorator.class.php | 3 ++- lib/event/sfEvent.class.php | 2 +- lib/exception/sfException.class.php | 4 +++- lib/i18n/sfDateFormat.class.php | 3 +-- lib/i18n/sfI18N.class.php | 10 ++-------- lib/log/sfFileLogger.class.php | 7 ++++--- .../lib/test/sfTesterDoctrine.class.php | 2 +- lib/response/sfResponse.class.php | 3 ++- lib/routing/sfRoute.class.php | 3 ++- lib/test/sfTestFunctionalBase.class.php | 2 +- lib/test/sfTesterResponse.class.php | 5 +++-- lib/util/sfBrowserBase.class.php | 7 ++++--- lib/util/sfNamespacedParameterHolder.class.php | 2 +- lib/util/sfParameterHolder.class.php | 6 +++--- lib/vendor/lime/lime.php | 5 +++-- lib/view/sfViewParameterHolder.class.php | 2 +- lib/widget/sfWidgetFormDate.class.php | 2 +- lib/widget/sfWidgetFormTime.class.php | 2 +- lib/yaml/sfYamlParser.class.php | 2 +- 20 files changed, 43 insertions(+), 37 deletions(-) diff --git a/lib/cache/sfFileCache.class.php b/lib/cache/sfFileCache.class.php index 2997d6c96..f84be899f 100644 --- a/lib/cache/sfFileCache.class.php +++ b/lib/cache/sfFileCache.class.php @@ -256,9 +256,13 @@ protected function read($path, $type = self::READ_DATA) fseek($fp, 0, SEEK_END); $length = ftell($fp) - 24; fseek($fp, 24); - if($length > 0) { + + if ($length > 0) + { $data[self::READ_DATA] = @fread($fp, $length); - } else { + } + else + { $data[self::READ_DATA] = ''; } } diff --git a/lib/escaper/sfOutputEscaperObjectDecorator.class.php b/lib/escaper/sfOutputEscaperObjectDecorator.class.php index 86d0ae71e..ea4adcc57 100644 --- a/lib/escaper/sfOutputEscaperObjectDecorator.class.php +++ b/lib/escaper/sfOutputEscaperObjectDecorator.class.php @@ -119,7 +119,8 @@ public function __isset($key) public function count() { // See https://github.com/symfony/polyfill/commit/d330c0094a47d8edceeea1ed553d6e08215a9fc2 - if(is_array($this->value) || $this->value instanceof Countable || $this->value instanceof ResourceBundle || $this->value instanceof SimpleXmlElement) { + if (is_array($this->value) || $this->value instanceof Countable || $this->value instanceof ResourceBundle || $this->value instanceof SimpleXmlElement) + { return count($this->value); } return 1; diff --git a/lib/event/sfEvent.class.php b/lib/event/sfEvent.class.php index 750b28023..67415e7ee 100644 --- a/lib/event/sfEvent.class.php +++ b/lib/event/sfEvent.class.php @@ -83,7 +83,7 @@ public function getReturnValue() /** * Sets the processed flag. * - * @param boolean $processed The processed flag value + * @param bool $processed The processed flag value */ public function setProcessed($processed) { diff --git a/lib/exception/sfException.class.php b/lib/exception/sfException.class.php index fbd742596..9ade775db 100644 --- a/lib/exception/sfException.class.php +++ b/lib/exception/sfException.class.php @@ -367,9 +367,11 @@ static protected function formatArrayAsHtml($values) static protected function fileExcerpt($file, $line) { // $file can be null for RuntimeException - if($file === null) { + if (null === $file) + { return ''; } + if (is_readable($file)) { $content = preg_split('#
#', preg_replace('/^(.*)<\/code>$/s', '$1', highlight_file($file, true))); diff --git a/lib/i18n/sfDateFormat.class.php b/lib/i18n/sfDateFormat.class.php index 90b2aded3..91f827081 100644 --- a/lib/i18n/sfDateFormat.class.php +++ b/lib/i18n/sfDateFormat.class.php @@ -239,8 +239,7 @@ public function format($time, $pattern = 'F', $inputPattern = null, $charset = ' } else { - $function = $this->getFunctionName($pattern); - if ($function != null) + if (null !== $function = $this->getFunctionName($pattern)) { $function = ucfirst($function); $fName = 'get'.$function; diff --git a/lib/i18n/sfI18N.class.php b/lib/i18n/sfI18N.class.php index 5478e6d73..c236c9d2a 100644 --- a/lib/i18n/sfI18N.class.php +++ b/lib/i18n/sfI18N.class.php @@ -272,14 +272,8 @@ public function getTimestampForCulture($dateTime, $culture = null) list($hour, $minute) = $this->getTimeForCulture($dateTime, null === $culture ? $this->culture : $culture); // mktime behavior change with php8 - // $hour become not nullable - if (!$hour) { - $hour = 0; - } - // Before 8.0, $minutes value to null, was casted as (int)0 - if (!$minute) { - $minute = 0; - } + $hour = null !== $hour ? $hour : 0; + $minute = null !== $minute ? $minute : 0; return null === $day ? null : mktime($hour, $minute, 0, $month, $day, $year); } diff --git a/lib/log/sfFileLogger.class.php b/lib/log/sfFileLogger.class.php index eceb47255..35d269a5a 100644 --- a/lib/log/sfFileLogger.class.php +++ b/lib/log/sfFileLogger.class.php @@ -136,7 +136,8 @@ public function shutdown() */ public static function strftime($format) { - if (version_compare(PHP_VERSION, '8.1.0') < 0) { + if (version_compare(PHP_VERSION, '8.1.0') < 0) + { return strftime($format); } return date(self::_strftimeFormatToDateFormat($format)); @@ -160,8 +161,8 @@ public static function strftime($format) * * @return array|string|string[] */ - private static function _strftimeFormatToDateFormat($strftimeFormat) { - + private static function _strftimeFormatToDateFormat($strftimeFormat) + { // Missing %V %C %g %G $search = array( '%a', '%A', '%d', '%e', '%u', diff --git a/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php b/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php index 48fd0374b..f8392c7ae 100644 --- a/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php +++ b/lib/plugins/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php @@ -65,7 +65,7 @@ public function check($model, $query, $value = true) } $operator = '='; - if (strlen($condition) && '!' == substr($condition,0,1)) + if (strlen($condition) && '!' == substr($condition, 0, 1)) { $operator = false !== strpos($condition, '%') ? 'NOT LIKE' : '!='; $condition = substr($condition, 1); diff --git a/lib/response/sfResponse.class.php b/lib/response/sfResponse.class.php index 905d07996..1c8e3d48c 100644 --- a/lib/response/sfResponse.class.php +++ b/lib/response/sfResponse.class.php @@ -177,7 +177,8 @@ public function unserialize($serialized) * * @return array */ - public function __serialize() { + public function __serialize() + { return array('content' => $this->content); } diff --git a/lib/routing/sfRoute.class.php b/lib/routing/sfRoute.class.php index a0093b18e..fd2ac0319 100644 --- a/lib/routing/sfRoute.class.php +++ b/lib/routing/sfRoute.class.php @@ -862,7 +862,8 @@ public function unserialize($serialized) * * @return array */ - public function __serialize() { + public function __serialize() + { // always serialize compiled routes $this->compile(); // sfPatternRouting will always re-set defaultParameters, so no need to serialize them diff --git a/lib/test/sfTestFunctionalBase.class.php b/lib/test/sfTestFunctionalBase.class.php index 97ac815a6..fc83df3b5 100644 --- a/lib/test/sfTestFunctionalBase.class.php +++ b/lib/test/sfTestFunctionalBase.class.php @@ -478,7 +478,7 @@ static public function handlePhpError($errno, $errstr, $errfile, $errline) /** * Exception handler for the current test browser instance. * - * @param Throwable $exception The exception + * @param Throwable|Exception $exception The exception */ function handleException($exception) { diff --git a/lib/test/sfTesterResponse.class.php b/lib/test/sfTesterResponse.class.php index 1a1c7a86a..7409dfc2d 100644 --- a/lib/test/sfTesterResponse.class.php +++ b/lib/test/sfTesterResponse.class.php @@ -49,8 +49,9 @@ public function initialize() } else { - if($this->response->getContent()) { - @$this->dom->loadHTML($this->response->getContent()); + if ($content = $this->response->getContent()) + { + @$this->dom->loadHTML($content); } } $this->domCssSelector = new sfDomCssSelector($this->dom); diff --git a/lib/util/sfBrowserBase.class.php b/lib/util/sfBrowserBase.class.php index 4ec39098a..535d8ac45 100755 --- a/lib/util/sfBrowserBase.class.php +++ b/lib/util/sfBrowserBase.class.php @@ -363,8 +363,9 @@ public function call($uri, $method = 'get', $parameters = array(), $changeStack } else { - if($response->getContent()) { - @$this->dom->loadHTML($response->getContent()); + if ($content = $response->getContent()) + { + @$this->dom->loadHTML($content); } } $this->domCssSelector = new sfDomCssSelector($this->dom); @@ -910,7 +911,7 @@ public function doClickElement(DOMElement $item, $arguments = array(), $options } else { - $queryString = (is_array($arguments)) ? http_build_query($arguments, null, '&') : ''; + $queryString = is_array($arguments) ? http_build_query($arguments, null, '&') : ''; $sep = false === strpos($url, '?') ? '?' : '&'; return array($url.($queryString ? $sep.$queryString : ''), 'get', array()); diff --git a/lib/util/sfNamespacedParameterHolder.class.php b/lib/util/sfNamespacedParameterHolder.class.php index 757d86edd..03008a030 100644 --- a/lib/util/sfNamespacedParameterHolder.class.php +++ b/lib/util/sfNamespacedParameterHolder.class.php @@ -395,7 +395,7 @@ public function __serialize() } /** - * Unserializes a sfParameterHolder instance. for PHP 7.4 + * Unserializes a sfParameterHolder instance for PHP 7.4+ * * @param array $data */ diff --git a/lib/util/sfParameterHolder.class.php b/lib/util/sfParameterHolder.class.php index aecd57435..b4d57b6d5 100644 --- a/lib/util/sfParameterHolder.class.php +++ b/lib/util/sfParameterHolder.class.php @@ -203,13 +203,13 @@ public function unserialize($serialized) * * @return Array */ - public function __serialize() { - + public function __serialize() + { return $this->parameters; } /** - * Unserializes a sfParameterHolder instance. for PHP 7.4 + * Unserializes a sfParameterHolder instance for PHP 7.4+ * * @param array $data */ diff --git a/lib/vendor/lime/lime.php b/lib/vendor/lime/lime.php index 5b3c16560..2d5f8986e 100644 --- a/lib/vendor/lime/lime.php +++ b/lib/vendor/lime/lime.php @@ -589,7 +589,7 @@ public function handle_error($code, $message, $file, $line, $context = null) } /** - * @param Throwable $exception only available on php7 + * @param Throwable|Exception $exception * @return bool */ public function handle_exception($exception) @@ -1103,7 +1103,8 @@ function lime_shutdown() $this->output->comment(sprintf(' at %s line %s', $this->get_relative_file($testsuite['tests'][$testcase]['file']).$this->extension, $testsuite['tests'][$testcase]['line'])); $this->output->info(' '.$testsuite['tests'][$testcase]['message']); - if(isset($testsuite['tests'][$testcase]['error'])) { + if (isset($testsuite['tests'][$testcase]['error'])) + { $this->output->echoln($testsuite['tests'][$testcase]['error'], null, false); } } diff --git a/lib/view/sfViewParameterHolder.class.php b/lib/view/sfViewParameterHolder.class.php index 4cc6d636c..3d8c63f18 100644 --- a/lib/view/sfViewParameterHolder.class.php +++ b/lib/view/sfViewParameterHolder.class.php @@ -193,7 +193,7 @@ public function __serialize() } /** - * Unserializes a sfParameterHolder instance. for PHP 7.4 + * Unserializes a sfParameterHolder instance for PHP 7.4+ * * @param array $data */ diff --git a/lib/widget/sfWidgetFormDate.class.php b/lib/widget/sfWidgetFormDate.class.php index c8ed674df..9c87946b7 100644 --- a/lib/widget/sfWidgetFormDate.class.php +++ b/lib/widget/sfWidgetFormDate.class.php @@ -70,7 +70,7 @@ public function render($name, $value = null, $attributes = array(), $errors = ar } else { - $value = (string) $value == (string) (integer) $value ? (integer) $value : strtotime( (string) $value); + $value = (string) $value == (string) (integer) $value ? (integer) $value : strtotime((string) $value); if (false === $value) { $value = $default; diff --git a/lib/widget/sfWidgetFormTime.class.php b/lib/widget/sfWidgetFormTime.class.php index 5917ed841..4a90d957b 100644 --- a/lib/widget/sfWidgetFormTime.class.php +++ b/lib/widget/sfWidgetFormTime.class.php @@ -72,7 +72,7 @@ public function render($name, $value = null, $attributes = array(), $errors = ar } else { - $value = ctype_digit( (string) $value) ? (integer) $value : strtotime( (string) $value); + $value = ctype_digit((string) $value) ? (integer) $value : strtotime((string) $value); if (false === $value) { $value = $default; diff --git a/lib/yaml/sfYamlParser.class.php b/lib/yaml/sfYamlParser.class.php index ed5b179ee..3cf5580b1 100644 --- a/lib/yaml/sfYamlParser.class.php +++ b/lib/yaml/sfYamlParser.class.php @@ -421,7 +421,7 @@ protected function parseValue($value) { $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : ''; - return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs((int) $modifiers)); + return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), abs((int) $modifiers)); } else { From 01fadb98ff556c2d66988941dddc5090d8e830d9 Mon Sep 17 00:00:00 2001 From: Tybaze Date: Tue, 2 Aug 2022 14:34:54 +0200 Subject: [PATCH 20/23] PHP 8.1 > Better MYSQLI_REPORT_OFF implementations for php8.1 compat Thanks @mentalstring --- lib/database/sfMySQLiDatabase.class.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/database/sfMySQLiDatabase.class.php b/lib/database/sfMySQLiDatabase.class.php index bdc8be447..cb13c1edc 100644 --- a/lib/database/sfMySQLiDatabase.class.php +++ b/lib/database/sfMySQLiDatabase.class.php @@ -18,6 +18,18 @@ class sfMySQLiDatabase extends sfMySQLDatabase { + /** + * @return void + * @throws sfDatabaseException + */ + public function connect() + { + // PHP 8.1 Activate Exception per default, revert behavior to "return false" + mysqli_report(MYSQLI_REPORT_OFF); + + parent::connect(); + } + /** * Returns the appropriate connect method. * @@ -29,9 +41,6 @@ class sfMySQLiDatabase extends sfMySQLDatabase */ protected function getConnectMethod($persistent) { - // PHP 8.1 Activate Exception per default, revert behavior to "return false" - mysqli_report(MYSQLI_REPORT_OFF); - return 'mysqli_connect'; } From 3bb8339eb0e7401f2ed3fed9de861b4b2ebd8064 Mon Sep 17 00:00:00 2001 From: Paulo Magalhaes Date: Fri, 12 Aug 2022 22:37:57 +0100 Subject: [PATCH 21/23] PHP 8.1 > remove full_path from uploads added on PHP v8.1 --- lib/request/sfWebRequest.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/request/sfWebRequest.class.php b/lib/request/sfWebRequest.class.php index bf35cbcb4..cf7549fad 100644 --- a/lib/request/sfWebRequest.class.php +++ b/lib/request/sfWebRequest.class.php @@ -872,6 +872,9 @@ static public function convertFileInformation(array $taintedFiles) */ static protected function fixPhpFilesArray(array $data) { + // remove full_path added on php8.1 + unset($data['full_path']); + $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type'); $keys = array_keys($data); sort($keys); From 77983281163bcab2969dbbf33ee5e2ee8bc86671 Mon Sep 17 00:00:00 2001 From: Paulo Magalhaes Date: Fri, 12 Aug 2022 23:40:02 +0200 Subject: [PATCH 22/23] Fix use of null on string parameter on multiple classes --- lib/generator/sfModelGenerator.class.php | 2 +- lib/util/sfBrowserBase.class.php | 2 +- lib/view/sfViewCacheManager.class.php | 4 ++-- test/unit/sfNoRouting.class.php | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/generator/sfModelGenerator.class.php b/lib/generator/sfModelGenerator.class.php index b52a2570a..e84a7e1fc 100644 --- a/lib/generator/sfModelGenerator.class.php +++ b/lib/generator/sfModelGenerator.class.php @@ -273,7 +273,7 @@ public function renderField($field) } else if ('Date' == $field->getType()) { - $html = sprintf("false !== strtotime($html) ? format_date(%s, \"%s\") : ' '", $html, $field->getConfig('date_format', 'f')); + $html = sprintf("is_string($html) && false !== strtotime($html) ? format_date(%s, \"%s\") : ' '", $html, $field->getConfig('date_format', 'f')); } else if ('Boolean' == $field->getType()) { diff --git a/lib/util/sfBrowserBase.class.php b/lib/util/sfBrowserBase.class.php index 535d8ac45..4267bb0a9 100755 --- a/lib/util/sfBrowserBase.class.php +++ b/lib/util/sfBrowserBase.class.php @@ -911,7 +911,7 @@ public function doClickElement(DOMElement $item, $arguments = array(), $options } else { - $queryString = is_array($arguments) ? http_build_query($arguments, null, '&') : ''; + $queryString = is_array($arguments) ? http_build_query($arguments, '', '&') : ''; $sep = false === strpos($url, '?') ? '?' : '&'; return array($url.($queryString ? $sep.$queryString : ''), 'get', array()); diff --git a/lib/view/sfViewCacheManager.class.php b/lib/view/sfViewCacheManager.class.php index f055e50f1..70198e10f 100644 --- a/lib/view/sfViewCacheManager.class.php +++ b/lib/view/sfViewCacheManager.class.php @@ -1005,8 +1005,8 @@ public function getCurrentCacheKey() if ($getParameters = $this->request->getGetParameters()) { - $cacheKey .= false === strpos($cacheKey, '?') ? '?' : '&'; - $cacheKey .= http_build_query($getParameters, null, '&'); + $cacheKey .= false === strpos((string) $cacheKey, '?') ? '?' : '&'; + $cacheKey .= http_build_query($getParameters, '', '&'); } return $cacheKey; diff --git a/test/unit/sfNoRouting.class.php b/test/unit/sfNoRouting.class.php index 2899cccb0..fc13704c4 100644 --- a/test/unit/sfNoRouting.class.php +++ b/test/unit/sfNoRouting.class.php @@ -29,7 +29,7 @@ public function getCurrentInternalUri($with_route_name = false) // other parameters unset($parameters['module'], $parameters['action']); ksort($parameters); - $parameters = count($parameters) ? '?'.http_build_query($parameters, null, '&') : ''; + $parameters = count($parameters) ? '?'.http_build_query($parameters, '', '&') : ''; return sprintf('%s%s', $action, $parameters); } @@ -49,7 +49,7 @@ public function generate($name, $params = array(), $absolute = false) unset($parameters['action']); } - $parameters = http_build_query($parameters, null, '&'); + $parameters = http_build_query($parameters, '', '&'); return $this->fixGeneratedUrl('/'.($parameters ? '?'.$parameters : ''), $absolute); } From 1e9b188eeccb5185d70e49d5737fd408ef79e6e8 Mon Sep 17 00:00:00 2001 From: thePanz Date: Fri, 25 Nov 2022 16:34:43 +0100 Subject: [PATCH 23/23] Github Actions: enable testing on PHP v8.0 and v8.1 (for PRs too) --- .github/workflows/continuous-integration.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 13d1bdfa7..78e07a5d0 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -1,6 +1,10 @@ name: "Continuous Integration" -on: [push] +on: + push: + branches: + - master + pull_request: env: fail-fast: true @@ -14,8 +18,8 @@ jobs: matrix: php-version: - "7.4" - # - "8.0" - # - "8.1" + - "8.0" + - "8.1" memcached-version: - "1.6"