diff --git a/composer.json b/composer.json index 6fe00d85..fa5319ba 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,6 @@ "generated/curl.php", "generated/datetime.php", "generated/dir.php", - "generated/dom.php", "generated/eio.php", "generated/errorfunc.php", "generated/exec.php", @@ -62,7 +61,6 @@ "generated/opcache.php", "generated/openssl.php", "generated/outcontrol.php", - "generated/password.php", "generated/pcntl.php", "generated/pcre.php", "generated/pgsql.php", diff --git a/generated/Exceptions/DomException.php b/generated/Exceptions/DomException.php deleted file mode 100644 index 401173cb..00000000 --- a/generated/Exceptions/DomException.php +++ /dev/null @@ -1,11 +0,0 @@ -...` section of the doc page. + // This minimizes 'false positives', where text such as "returns false when ..." could be matched outside + // the function's dedicated Return Values section. + $returnValuesSection = $this->extractSection('returnvalues', $file); + + if (preg_match('/[Tt]he function returns &false;/m', $returnValuesSection)) { return true; } - if (preg_match('/&false;\s+on\s+failure/m', $file)) { + + if (preg_match('/&false;\s+on\s+error/m', $returnValuesSection)) { return true; } - if (preg_match('/&false;\s+otherwise/m', $file) && !preg_match('/(returns\s+&true;|&true;\s+on\s+success|&true;\s+if)/im', $file)) { + if (preg_match('/&false;\s+on\s+failure/m', $returnValuesSection)) { return true; } - if (preg_match('/may\s+return\s+&false;/m', $file) && !preg_match('/(returns\s+&true;|&true;\s+on\s+success|&true;\s+if)/im', $file)) { + if (preg_match('/&false;\s+otherwise/m', $returnValuesSection) && !preg_match('/(returns\s+&true;|&true;\s+on\s+success|&true;\s+if)/im', $returnValuesSection)) { return true; } - if (preg_match('/&false;\s+if\s+an\s+error\s+occurred/m', $file)) { + if (preg_match('/may\s+return\s+&false;/m', $returnValuesSection) && !preg_match('/(returns\s+&true;|&true;\s+on\s+success|&true;\s+if)/im', $returnValuesSection)) { return true; } - if (preg_match('/&return.success;/m', $file)) { + if (preg_match('/&false;\s+if\s+an\s+error\s+occurred/m', $returnValuesSection)) { return true; } - if (preg_match('/&return.nullorfalse;/m', $file)) { + if (preg_match('/&return.success;/m', $returnValuesSection)) { return true; } - if (preg_match('/&return.falseforfailure;/m', $file)) { + if (preg_match('/&return.nullorfalse;/m', $returnValuesSection)) { return true; } - if (preg_match('/&date.datetime.return.modifiedobjectorfalseforfailure;/m', $file)) { + if (preg_match('/&return.falseforfailure;/m', $returnValuesSection)) { return true; } - if (preg_match('/ or &false; \\(and generates an error/m', $file)) { + if (preg_match('/&date.datetime.return.modifiedobjectorfalseforfailure;/m', $returnValuesSection)) { return true; } - if (preg_match('/&false;\s+if\s+the\s+number\s+of\s+elements\s+for\s+each\s+array\s+isn\'t\s+equal/m', $file)) { + if (preg_match('/ or &false; \\(and generates an error/m', $returnValuesSection)) { return true; } - if (preg_match('/If\s+the\s+call\s+fails,\s+it\s+will\s+return\s+&false;/m', $file)) { + if (preg_match('/&false;\s+if\s+the\s+number\s+of\s+elements\s+for\s+each\s+array\s+isn\'t\s+equal/m', $returnValuesSection)) { return true; } - if (preg_match('/Upon\s+failure,?\s+\[\w_]{1,15}?\<\/function\>\s+returns\s+&false;/m', $file)) { + if (preg_match('/If\s+the\s+call\s+fails,\s+it\s+will\s+return\s+&false;/m', $returnValuesSection)) { return true; } - if (preg_match('/On\s+failure,\s+&false;\s+is\s+returned/m', $file)) { + if (preg_match('/Upon\s+failure,?\s+\[\w_]{1,15}?\<\/function\>\s+returns\s+&false;/m', $returnValuesSection)) { return true; } - if (preg_match('/on\s+success,\s+otherwise\s+&false;\s+is\s+returned/m', $file)) { + if (preg_match('/On\s+failure,\s+&false;\s+is\s+returned/m', $returnValuesSection)) { return true; } - if (preg_match('/Returns.*on success[.\s\S]+Returns &false;\s+if/m', $file)) { + if (preg_match('/on\s+success,\s+otherwise\s+&false;\s+is\s+returned/m', $returnValuesSection)) { + return true; + } + if (preg_match('/Returns.*on success[.\s\S]+Returns &false;\s+if/m', $returnValuesSection)) { return true; } - if (preg_match('/&gd\.return\.identifier;/m', $file)) { + if (preg_match('/&gd\.return\.identifier;/m', $returnValuesSection)) { return true; } - if (preg_match('/&gd\.return\.identifier;/m', $file)) { + if (preg_match('/&gd\.return\.identifier;/m', $returnValuesSection)) { return true; } //used for date if (preg_match('/If a non-numeric value is used for - \timestamp\<\/parameter\>, &false; is returned/m', $file)) { + \timestamp\<\/parameter\>, &false; is returned/m', $returnValuesSection)) { return true; } //used to detect imagecreatefromstring - if (preg_match('/If the arguments are invalid, the function returns &false;/m', $file)) { + if (preg_match('/If the arguments are invalid, the function returns &false;/m', $returnValuesSection)) { return true; } //used to detect class_implements - if (preg_match("/&false; when the given class doesn't exist/m", $file)) { + if (preg_match("/&false; when the given class doesn't exist/m", $returnValuesSection)) { return true; } //used to detect get_headers and ldap_search - if (preg_match("/&false; on failure/m", $file)) { + if (preg_match("/&false; on failure/m", $returnValuesSection)) { return true; } @@ -150,10 +159,15 @@ public function detectNullsyFunction(): bool return false; } - if (preg_match('/&null;\s+on\s+failure/', $file)) { + // Only evaluate the text inside the `...` section of the doc page. + // This minimizes 'false positives', where text such as "returns false when ..." could be matched outside + // the function's dedicated Return Values section. + $returnValuesSection = $this->extractSection('returnvalues', $file); + + if (preg_match('/&null;\s+on\s+failure/', $returnValuesSection)) { return true; } - if (preg_match('/&null;\s+if\s+an\s+error\s+occurs/', $file)) { + if (preg_match('/&null;\s+if\s+an\s+error\s+occurs/', $returnValuesSection)) { return true; } @@ -173,14 +187,15 @@ public function detectEmptyFunction(): bool return false; } - if (preg_match('/an\s+empty\s+string\s+on\s+error/', $file)) { + $returnValuesSection = $this->extractSection('returnvalues', $file); + + if (preg_match('/an\s+empty\s+string\s+on\s+error/', $returnValuesSection)) { return true; } return false; } - /** * @return \SimpleXMLElement[] */ @@ -197,8 +212,7 @@ public function getMethodSynopsis(): array // Only evaluate the synopsis inside the `...` section of the doc page. // Other synopses might occur in the `...` section, but these describe // handlers, callbacks, and other callable-type arguments, not the function itself. - preg_match_all('/[\s\S]*?<\/refsect1>/m', $file, $fileDescriptionSection); - $fileDescriptionSection = implode('', $this->arrayFlatten((array) $fileDescriptionSection)); + $fileDescriptionSection = $this->extractSection('description', $file); if (!preg_match_all('/<\/?methodsynopsis[\s\S]*?>[\s\S]*?<\/methodsynopsis>/m', $fileDescriptionSection, $functions, PREG_SET_ORDER, 0)) { return []; @@ -265,6 +279,15 @@ public function getModule(): string return $this->toCamelCase(\basename(\dirname($this->path, 2))); } + private function extractSection(string $sectionName, string $file): string + { + $regexpBase = '/[\s\S]*?<\/refsect1>/m'; + $regexpString = sprintf($regexpBase, preg_quote($sectionName, '/')); + preg_match_all($regexpString, $file, $output); + $output = implode('', $this->arrayFlatten((array) $output)); + return $output; + } + private function toCamelCase(string $str): string { $tokens = preg_split("/[_ ]+/", $str); diff --git a/generator/tests/DocPageTest.php b/generator/tests/DocPageTest.php index b5b4dbe7..c1c88f2c 100644 --- a/generator/tests/DocPageTest.php +++ b/generator/tests/DocPageTest.php @@ -20,6 +20,7 @@ public function testDetectFalsyFunction() $date = new DocPage(__DIR__ . '/../doc/doc-en/en/reference/datetime/functions/date.xml'); $classImplement = new DocPage(__DIR__ . '/../doc/doc-en/en/reference/spl/functions/class-implements.xml'); $getHeaders = new DocPage(__DIR__ . '/../doc/doc-en/en/reference/url/functions/get-headers.xml'); + $gzopen = new DocPage(__DIR__ . '/../doc/doc-en/en/reference/zlib/functions/gzopen.xml'); //$ldapSearch = new DocPage(__DIR__ . '/../doc/doc-en/en/reference/ldap/functions/ldap-search.xml'); $this->assertTrue($pregMatch->detectFalsyFunction()); @@ -34,6 +35,7 @@ public function testDetectFalsyFunction() $this->assertTrue($date->detectFalsyFunction()); $this->assertTrue($classImplement->detectFalsyFunction()); $this->assertTrue($getHeaders->detectFalsyFunction()); + $this->assertTrue($gzopen->detectFalsyFunction()); //$this->assertTrue($ldapSearch->detectFalsyFunction()); } diff --git a/lib/special_cases.php b/lib/special_cases.php index ecfab1b9..70d403d7 100644 --- a/lib/special_cases.php +++ b/lib/special_cases.php @@ -7,8 +7,11 @@ namespace Safe; -use Safe\Exceptions\SocketsException; use const PREG_NO_ERROR; + +use Safe\Exceptions\MiscException; +use Safe\Exceptions\PosixException; +use Safe\Exceptions\SocketsException; use Safe\Exceptions\ApcException; use Safe\Exceptions\ApcuException; use Safe\Exceptions\JsonException; @@ -321,3 +324,42 @@ function simplexml_load_string(string $data, string $class_name = \SimpleXMLElem } return $result; } + +/** + * Returns three samples representing the average system load + * (the number of processes in the system run queue) over the last 1, 5 and 15 + * minutes, respectively. Returns FALSE on failure. + * + * @return array Returns an array with three samples (last 1, 5 and 15 + * minutes). + * @throws MiscException + * + */ +function sys_getloadavg(): array +{ + error_clear_last(); + $result = \sys_getloadavg(); + if ($result === false) { + throw MiscException::createFromPhpError(); + } + return $result; +} + +/** + * Returns the process group identifier of the process + * process_id. + * + * @param int $process_id The process id. + * @return int Returns the identifier, as an int. + * @throws PosixException + * + */ +function posix_getpgid(int $process_id): int +{ + error_clear_last(); + $result = \posix_getpgid($process_id); + if ($result === false) { + throw PosixException::createFromPhpError(); + } + return $result; +} diff --git a/rector-migrate.php b/rector-migrate.php index f075867e..7420c7f3 100644 --- a/rector-migrate.php +++ b/rector-migrate.php @@ -53,7 +53,6 @@ 'com_print_typeinfo' => 'Safe\com_print_typeinfo', 'convert_uudecode' => 'Safe\convert_uudecode', 'copy' => 'Safe\copy', - 'count_chars' => 'Safe\count_chars', 'create_function' => 'Safe\create_function', 'cubrid_bind' => 'Safe\cubrid_bind', 'cubrid_column_names' => 'Safe\cubrid_column_names', @@ -114,7 +113,6 @@ 'curl_exec' => 'Safe\curl_exec', 'curl_getinfo' => 'Safe\curl_getinfo', 'curl_init' => 'Safe\curl_init', - 'curl_multi_errno' => 'Safe\curl_multi_errno', 'curl_multi_info_read' => 'Safe\curl_multi_info_read', 'curl_multi_init' => 'Safe\curl_multi_init', 'curl_multi_setopt' => 'Safe\curl_multi_setopt', @@ -148,7 +146,6 @@ 'disk_total_space' => 'Safe\disk_total_space', 'dl' => 'Safe\dl', 'dns_get_record' => 'Safe\dns_get_record', - 'dom_import_simplexml' => 'Safe\dom_import_simplexml', 'eio_busy' => 'Safe\eio_busy', 'eio_chmod' => 'Safe\eio_chmod', 'eio_chown' => 'Safe\eio_chown', @@ -260,9 +257,6 @@ 'get_meta_tags' => 'Safe\get_meta_tags', 'glob' => 'Safe\glob', 'gmmktime' => 'Safe\gmmktime', - 'gmp_binomial' => 'Safe\gmp_binomial', - 'gmp_export' => 'Safe\gmp_export', - 'gmp_import' => 'Safe\gmp_import', 'gmp_random_seed' => 'Safe\gmp_random_seed', 'gmstrftime' => 'Safe\gmstrftime', 'gnupg_adddecryptkey' => 'Safe\gnupg_adddecryptkey', @@ -282,6 +276,7 @@ 'gzgets' => 'Safe\gzgets', 'gzgetss' => 'Safe\gzgetss', 'gzinflate' => 'Safe\gzinflate', + 'gzopen' => 'Safe\gzopen', 'gzpassthru' => 'Safe\gzpassthru', 'gzread' => 'Safe\gzread', 'gzrewind' => 'Safe\gzrewind', @@ -465,7 +460,6 @@ 'inotify_rm_watch' => 'Safe\inotify_rm_watch', 'iptcembed' => 'Safe\iptcembed', 'iptcparse' => 'Safe\iptcparse', - 'jdtounix' => 'Safe\jdtounix', 'jpeg2wbmp' => 'Safe\jpeg2wbmp', 'json_decode' => 'Safe\json_decode', 'json_encode' => 'Safe\json_encode', @@ -534,9 +528,7 @@ 'mb_regex_encoding' => 'Safe\mb_regex_encoding', 'mb_send_mail' => 'Safe\mb_send_mail', 'mb_split' => 'Safe\mb_split', - 'mb_str_split' => 'Safe\mb_str_split', 'md5_file' => 'Safe\md5_file', - 'metaphone' => 'Safe\metaphone', 'mime_content_type' => 'Safe\mime_content_type', 'mkdir' => 'Safe\mkdir', 'mktime' => 'Safe\mktime', @@ -710,7 +702,6 @@ 'parse_ini_file' => 'Safe\parse_ini_file', 'parse_ini_string' => 'Safe\parse_ini_string', 'parse_url' => 'Safe\parse_url', - 'password_hash' => 'Safe\password_hash', 'pcntl_getpriority' => 'Safe\pcntl_getpriority', 'pcntl_setpriority' => 'Safe\pcntl_setpriority', 'pcntl_signal' => 'Safe\pcntl_signal', @@ -766,7 +757,6 @@ 'posix_getgrnam' => 'Safe\posix_getgrnam', 'posix_getgroups' => 'Safe\posix_getgroups', 'posix_getlogin' => 'Safe\posix_getlogin', - 'posix_getpgid' => 'Safe\posix_getpgid', 'posix_getpwuid' => 'Safe\posix_getpwuid', 'posix_getrlimit' => 'Safe\posix_getrlimit', 'posix_getsid' => 'Safe\posix_getsid', @@ -979,7 +969,6 @@ 'solr_get_version' => 'Safe\solr_get_version', 'spl_autoload_register' => 'Safe\spl_autoload_register', 'spl_autoload_unregister' => 'Safe\spl_autoload_unregister', - 'sprintf' => 'Safe\sprintf', 'sqlsrv_begin_transaction' => 'Safe\sqlsrv_begin_transaction', 'sqlsrv_cancel' => 'Safe\sqlsrv_cancel', 'sqlsrv_client_info' => 'Safe\sqlsrv_client_info', @@ -1041,6 +1030,7 @@ 'stream_wrapper_register' => 'Safe\stream_wrapper_register', 'stream_wrapper_restore' => 'Safe\stream_wrapper_restore', 'stream_wrapper_unregister' => 'Safe\stream_wrapper_unregister', + 'strftime' => 'Safe\strftime', 'strptime' => 'Safe\strptime', 'strtotime' => 'Safe\strtotime', 'swoole_async_dns_lookup' => 'Safe\swoole_async_dns_lookup', @@ -1053,7 +1043,6 @@ 'symlink' => 'Safe\symlink', 'syslog' => 'Safe\syslog', 'system' => 'Safe\system', - 'sys_getloadavg' => 'Safe\sys_getloadavg', 'tempnam' => 'Safe\tempnam', 'timezone_name_from_abbr' => 'Safe\timezone_name_from_abbr', 'time_nanosleep' => 'Safe\time_nanosleep', @@ -1068,7 +1057,6 @@ 'variant_date_to_timestamp' => 'Safe\variant_date_to_timestamp', 'variant_round' => 'Safe\variant_round', 'virtual' => 'Safe\virtual', - 'vsprintf' => 'Safe\vsprintf', 'xdiff_file_bdiff' => 'Safe\xdiff_file_bdiff', 'xdiff_file_bpatch' => 'Safe\xdiff_file_bpatch', 'xdiff_file_diff' => 'Safe\xdiff_file_diff', @@ -1079,8 +1067,6 @@ 'xdiff_string_patch' => 'Safe\xdiff_string_patch', 'xdiff_string_patch_binary' => 'Safe\xdiff_string_patch_binary', 'xmlrpc_set_type' => 'Safe\xmlrpc_set_type', - 'xml_parser_create' => 'Safe\xml_parser_create', - 'xml_parser_create_ns' => 'Safe\xml_parser_create_ns', 'xml_parser_free' => 'Safe\xml_parser_free', 'xml_set_character_data_handler' => 'Safe\xml_set_character_data_handler', 'xml_set_default_handler' => 'Safe\xml_set_default_handler',