fix PHP 8.1 Deprecated by adding return type declarations

This commit is contained in:
ralf 2022-04-24 18:15:47 +02:00
parent 92922acfd4
commit c19eb3cb02
6 changed files with 252 additions and 26 deletions

View File

@ -118,9 +118,9 @@ class CallbackIterator implements \Iterator
/**
* Return the current element
*
* @return array
* @return mixed
*/
public function current()
public function current(): mixed
{
if (is_a($this->rs,'iterator'))
{
@ -136,7 +136,7 @@ class CallbackIterator implements \Iterator
*
* @return int
*/
public function key()
public function key(): int
{
if (is_a($this->rs,'iterator'))
{
@ -150,22 +150,22 @@ class CallbackIterator implements \Iterator
/**
* Move forward to next element (called after each foreach loop)
*/
public function next()
public function next(): void
{
if (is_a($this->rs,'iterator'))
{
return $this->rs->next();
$this->rs->next();
}
}
/**
* Rewind the Iterator to the first element (called at beginning of foreach loop)
*/
public function rewind()
public function rewind(): void
{
if (is_a($this->rs,'iterator'))
{
return $this->rs->rewind();
$this->rs->rewind();
}
}
@ -174,7 +174,7 @@ class CallbackIterator implements \Iterator
*
* @return boolean
*/
public function valid ()
public function valid (): bool
{
if (is_a($this->rs,'iterator'))
{
@ -182,4 +182,4 @@ class CallbackIterator implements \Iterator
}
return false;
}
}
}

View File

@ -908,7 +908,7 @@ class Account implements \ArrayAccess
* @param string $offset
* @return mixed
*/
public function offsetGet($offset)
public function offsetGet($offset): mixed
{
return $this->__get($offset);
}
@ -919,7 +919,7 @@ class Account implements \ArrayAccess
* @param string $offset
* @return boolean
*/
public function offsetExists($offset)
public function offsetExists($offset): bool
{
return $this->__isset($offset);
}
@ -933,7 +933,7 @@ class Account implements \ArrayAccess
* @param mixed $value
* @throws Api\Exception\WrongParameter
*/
public function offsetSet($offset, $value)
public function offsetSet($offset, $value): void
{
throw new Api\Exception\WrongParameter(__METHOD__."($offset, $value) No write access through ArrayAccess interface of Account!");
}
@ -946,7 +946,7 @@ class Account implements \ArrayAccess
* @param string $offset
* @throws Api\Exception\WrongParameter
*/
public function offsetUnset($offset)
public function offsetUnset($offset): void
{
throw new Api\Exception\WrongParameter(__METHOD__."($offset) No write access through ArrayAccess interface of Account!");
}

2
api/src/Storage/Customfields.php Executable file → Normal file
View File

@ -94,7 +94,7 @@ class Customfields implements \IteratorAggregate
*
* @return Api\Db\CallbackIterator
*/
function getIterator()
function getIterator(): Api\Db\CallbackIterator
{
return new Api\Db\CallbackIterator($this->iterator, function($_row)
{

View File

@ -1401,7 +1401,7 @@ class calendar_boupdate extends calendar_bo
$rrule->next_no_exception();
$occurrence = $rrule->current();
}
while ($rrule->valid($event['whole_day']) && ($enddate = $occurrence));
while ($rrule->validDate($event['whole_day']) && ($enddate = $occurrence));
$enddate->modify(($event['end'] - $event['start']).' second');
$event['recur_enddate'] = $save_event['recur_enddate'] = $enddate->format('ts');
//error_log(__METHOD__."($event[title]) start=".Api\DateTime::to($event['start'],'string').', end='.Api\DateTime::to($event['end'],'string').', range_end='.Api\DateTime::to($event['recur_enddate'],'string'));
@ -3180,4 +3180,4 @@ class calendar_boupdate extends calendar_bo
return $status_reset;
}
}
}

View File

@ -385,9 +385,9 @@ class calendar_rrule implements Iterator
/**
* Return the current element
*
* @return DateTime
* @return Api\DateTime
*/
public function current()
public function current(): Api\DateTime
{
return clone $this->current;
}
@ -397,7 +397,7 @@ class calendar_rrule implements Iterator
*
* @return int
*/
public function key()
public function key(): int
{
return (int)$this->current->format('Ymd');
}
@ -476,9 +476,9 @@ class calendar_rrule implements Iterator
}
/**
* Move forward to next recurence, taking into account exceptions
* Move forward to next recurrence, taking into account exceptions
*/
public function next()
public function next(): void
{
do
{
@ -555,7 +555,7 @@ class calendar_rrule implements Iterator
/**
* Rewind the Iterator to the first element (called at beginning of foreach loop)
*/
public function rewind()
public function rewind(): void
{
$this->current = clone $this->time;
while ($this->valid() &&
@ -569,20 +569,30 @@ class calendar_rrule implements Iterator
/**
* Checks if current position is valid
*
* @param boolean $use_just_date =false default use also time
* @param boolean? $use_just_date true: use just date, false|null: use also time
* @return boolean
*/
public function valid($use_just_date=false)
public function validDate(bool $use_just_date=null): bool
{
if ($use_just_date)
{
return $this->current->format('Ymd') <= $this->enddate_ymd;
}
return $this->valid();
}
/**
* Checks if current position is valid
*
* @return boolean
*/
public function valid(): bool
{
return $this->current->format('ts') < $this->enddate_ts;
}
/**
* Return string represenation of RRule
* Return string representation of RRule
*
* @return string
*/
@ -592,7 +602,7 @@ class calendar_rrule implements Iterator
// Repeated Events
if($this->type != self::NONE)
{
$str = lang(self::$types[$this->type]);
$str = (string)lang(self::$types[$this->type]);
$str_extra = array();
switch ($this->type)
@ -1186,6 +1196,7 @@ if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE_
$rrule = new calendar_rrule($time,$_REQUEST['type'],$_REQUEST['interval'],$enddate,$weekdays,$exceptions);
echo "<h3>".$time->format('l').', '.$time.' ('.$tz->getName().') '.$rrule."</h3>\n";
$n = 0;
foreach($rrule as $rtime)
{
$rtime->setTimezone(Api\DateTime::$user_timezone);

View File

@ -0,0 +1,215 @@
#!/usr/bin/php -qC
<?php
/**
* EGroupware - fix deprecated PHP functions and constructs
*
* The deprecated warnings fill up the log files, as they can not be switched off in the logs.
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @author RalfBecker@outdoor-training.de
* @copyright 2022 by rb@egroupware.org
*/
if (php_sapi_name() !== 'cli') // security precaution: forbid calling as web-page
{
die('<h1>fix_depricated.php must NOT be called as web-page --> exiting !!!</h1>');
}
/**
* Interfaces which methods require return types to avoid deprecated warnings
*
* As 'mixed' return type is only available since PHP 8.0, we need to add '#[\ReturnTypeWillChange]' annotation instead,
* for EGroupware versions not requiring PHP 8.0+ / 21.1.
*/
$interfaces = [
'Iterator' => [
'current' => 'mixed',
'key' => 'mixed',
'next' => 'void',
'rewind' => 'void',
'valid' => 'bool',
],
'IteratorAggregate' => [
'getIterator' => 'Traversable',
],
'ArrayAccess' => [
'offsetExists' => 'bool',
'offsetGet' => 'mixed',
'offsetSet' => 'void',
'offsetUnset' => 'void',
],
'Serializable' => [
'serialize' => '?string',
'unserialize' => 'void',
],
'JsonSerializable' => [
'jsonSerialize' => 'mixed',
],
];
/**
* Fix deprecated stuff in a given file
*
* @param string $file filename
* @param boolean $replace_file =false replace existing file if modifications are necessary, otherwise .php53 file is created
* @return boolean false on error
*/
function fix_depricated($file,$replace_file=false)
{
global $interfaces;
$orig = $lines = file_get_contents($file);
if ($lines === false) return false;
global $prog;
if (basename($file) == $prog) return true; // dont fix ourself ;-)
// match "variables" like: $var, $obj->attr, $arr['key']
$variable = '\$[a-z_0-9\[\]\'>-]+';
foreach($interfaces as $interface => $methods)
{
// class Account implements \ArrayAccess
if (!preg_match('/class\\s+([a-z_0-9]+)\s+implements\s+(\\\\?[a-z_0-9]+\s*,\s*)*\\\\?'.preg_quote($interface, '/').'/i', $lines, $matches))
{
//error_log("$file does NOT implement $interface: ".json_encode($matches));
continue;
}
error_log("$file DOES implement $interface: ".json_encode($matches));
//$phpdoc = "(\s*\\/\\*\\*.*\\*\\/\n)?";
$phpdoc = '';
$lines = preg_replace_callback("/^(\\s*((static|public|private|protected)\\s+)*function\\s+([a-z_0-9]+)\\s*)\\(\\s*([^)]*)\\s*\\)(\\s*:\\s*([a-z]+))?/msi",
static function(array $matches) use ($methods, $lines)
{
global $mixed_annotation;
if (isset($matches[6]) || !isset($methods[$matches[4]]))
{
//error_log($matches[0].' already fixed --> nothing to do');
return $matches[0];
}
//error_log(json_encode($matches)." --> need fixing");
if ($methods[$matches[4]] !== 'mixed')
{
return $matches[0].': '.$methods[$matches[4]];
}
//$phpdoc = "\s*\\/\\*\\*.*?(@return\s+([a-z]+)).*?\\*\\/\n";
$phpdoc = "\s+\\*\s+@return\s+([a-z]+).*\n\s+\\*\\/\n";
if (preg_match('/^'.$phpdoc.preg_quote($matches[0], '/').'/mi', $lines, $phpdoc_matches) &&
$phpdoc_matches[1] !== 'mixed')
{
switch($type = $phpdoc_matches[1])
{
case 'boolean': $type = 'bool'; break;
case 'integer': $type = 'int'; break;
case 'double': $type = 'float'; break;
}
return $matches[0].': '.$type;
}
if (!$mixed_annotation)
{
return $matches[0].': '.$methods[$matches[4]];
}
return "\t#[\\ReturnTypeWillChange]\n".$matches[0];
}, $lines);
}
if ($lines !== $orig)
{
file_put_contents($file.'.new',$lines);
$ret = null;
system('/usr/bin/php -l '.$file.'.new',$ret);
system('/usr/bin/diff -u '.$file.' '.$file.'.new');
if (!$ret && $replace_file)
{
unlink($file);
rename($file.'.new',$file);
}
return !$ret;
}
return true;
}
/**
* Loop recursive through directory and call fix_depricated for each php file
*
* @param string $dir
* @param boolean $replace_file =false replace existing file if modifications are necessary, otherwise .php53 file is created
* @return boolean false on error
*/
function fix_depricated_recursive($dir,$replace_file=false)
{
if (!is_dir($dir)) return false;
foreach(scandir($dir) as $file)
{
if ($file == '.' || $file == '..') continue;
if (is_dir($dir.'/'.$file))
{
fix_depricated_recursive($dir.'/'.$file,$replace_file);
}
elseif(substr($file,-4) == '.php')
{
echo "\r".str_repeat(' ',100)."\r".$dir.'/'.$file.': ';
fix_depricated($dir.'/'.$file,$replace_file);
}
}
echo "\r".str_repeat(' ',100)."\r";
return true;
}
/**
* Give usage
*
* @param string $error =null
*/
function usage($error=null)
{
global $prog;
echo "Usage: $prog [--replace] [--mixed-annotation] [-h|--help] file or dir\n\n";
if ($error) echo $error."\n\n";
exit($error ? 1 : 0);
}
$args = $_SERVER['argv'];
$prog = basename(array_shift($args));
if (!$args) usage();
$replace_file = false;
$mixed_annotation = false;
while(($arg = array_shift($args)))
{
switch($arg)
{
case '-h':
case '--help':
usage();
break;
case '--replace':
$replace_file = true;
break;
case '--mixed-annotation':
$mixed_annotation = true;
break;
default:
if ($args) // not last argument
{
usage("Unknown argument '$arg'!");
}
break 2;
}
}
if (!file_exists($arg)) usage("Error: $arg not found!");
if (!is_dir($arg))
{
fix_depricated($arg,$replace_file);
}
else
{
fix_depricated_recursive($arg,$replace_file);
}