diff options
author | ྅༻ Ǭɀħ ༄༆ཉ <ozh@ozh.org> | 2022-05-02 09:09:18 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-02 09:09:18 +0300 |
commit | 9def41dba83ad42232210139667528b4ac9bb3be (patch) | |
tree | 68c05e6e710a14271f14175ab361a6a578698a31 | |
parent | a2d0d2f626c7ee8fcd280eb91d08c61354578d04 (diff) |
Remove warnings on PHP 8.1 (#3317)
Also, minor code styles doc & typo
* Refactor yourls_filter_unique_id() to remove useless vars
* Comply with phpstan level 4
* add some tests to cover newly discovered potential issues
-rw-r--r-- | includes/Config/Config.php | 8 | ||||
-rw-r--r-- | includes/Config/Init.php | 2 | ||||
-rw-r--r-- | includes/Database/Logger.php | 2 | ||||
-rw-r--r-- | includes/Database/Profiler.php | 2 | ||||
-rw-r--r-- | includes/Views/AdminParams.php | 2 | ||||
-rw-r--r-- | includes/functions-auth.php | 33 | ||||
-rw-r--r-- | includes/functions-deprecated.php | 24 | ||||
-rw-r--r-- | includes/functions-formatting.php | 32 | ||||
-rw-r--r-- | includes/functions-html.php | 10 | ||||
-rw-r--r-- | includes/functions-http.php | 8 | ||||
-rw-r--r-- | includes/functions-l10n.php | 19 | ||||
-rw-r--r-- | includes/functions-plugins.php | 44 | ||||
-rw-r--r-- | includes/functions-upgrade.php | 5 | ||||
-rw-r--r-- | includes/functions.php | 30 | ||||
-rw-r--r-- | tests/data/auth/nopassword.php | 3 | ||||
-rw-r--r-- | tests/data/auth/preg_replace_problem.php | 9 | ||||
-rw-r--r-- | tests/tests/auth/auth.php | 14 | ||||
-rw-r--r-- | tests/tests/auth/logout.php | 2 | ||||
-rw-r--r-- | tests/tests/format/sanitizing.php | 1 | ||||
-rw-r--r-- | tests/tests/plugins/helpers.php | 13 | ||||
-rw-r--r-- | tests/tests/shorturl/crud.php | 7 |
21 files changed, 162 insertions, 108 deletions
diff --git a/includes/Config/Config.php b/includes/Config/Config.php index 5958d70f..c426b98e 100644 --- a/includes/Config/Config.php +++ b/includes/Config/Config.php @@ -11,12 +11,12 @@ use YOURLS\Exceptions\ConfigException; class Config { /** - * @param string + * @var string */ protected $root; /** - * @param mixed + * @var mixed */ protected $config; @@ -42,7 +42,7 @@ class Config { /** * @since 1.7.3 - * @param string path to config file + * @param string $config path to config file * @return void */ public function set_config($config) { @@ -51,7 +51,7 @@ class Config { /** * @since 1.7.3 - * @param string path to YOURLS root directory + * @param string $root path to YOURLS root directory * @return void */ public function set_root($root) { diff --git a/includes/Config/Init.php b/includes/Config/Init.php index f1b7e130..6cd05e7d 100644 --- a/includes/Config/Init.php +++ b/includes/Config/Init.php @@ -9,7 +9,7 @@ namespace YOURLS\Config; class Init { /** - * @param InitDefaults + * @var InitDefaults */ protected $actions; diff --git a/includes/Database/Logger.php b/includes/Database/Logger.php index 6f171b57..6c77adea 100644 --- a/includes/Database/Logger.php +++ b/includes/Database/Logger.php @@ -47,7 +47,7 @@ class Logger extends AbstractLogger { * ) * See finish() in Aura\Sql\Profiler\Profiler * - * @return null + * @return void */ public function log($level, $message, array $context = []) { // if it's an internal SQL query, format the message, otherwise store a string diff --git a/includes/Database/Profiler.php b/includes/Database/Profiler.php index 2b700b98..be8f56c2 100644 --- a/includes/Database/Profiler.php +++ b/includes/Database/Profiler.php @@ -21,7 +21,7 @@ class Profiler extends \Aura\Sql\Profiler\Profiler { * * @param string $statement The statement being profiled, if any. * @param array $values The values bound to the statement, if any. - * @return null + * @return void */ public function finish($statement = null, array $values = []) { diff --git a/includes/Views/AdminParams.php b/includes/Views/AdminParams.php index 65356936..8384039b 100644 --- a/includes/Views/AdminParams.php +++ b/includes/Views/AdminParams.php @@ -155,7 +155,7 @@ class AdminParams * * @since 1.8.2 * - * @return mixed + * @return string */ public function get_sort_by(): string { diff --git a/includes/functions-auth.php b/includes/functions-auth.php index 52a677a4..125b5d6e 100644 --- a/includes/functions-auth.php +++ b/includes/functions-auth.php @@ -37,7 +37,7 @@ function yourls_is_valid_user() { // The logout nonce is associated to fake user 'logout' since at this point we don't know the real user yourls_verify_nonce('admin_logout', $_REQUEST['nonce'], 'logout'); yourls_do_action( 'logout' ); - yourls_store_cookie( null ); + yourls_store_cookie( '' ); return yourls__( 'Logged out successfully' ); } @@ -173,11 +173,15 @@ function yourls_check_password_hash( $user, $submitted_password ) { * @return true|string if overwrite was successful, an error message otherwise */ function yourls_hash_passwords_now( $config_file ) { - if( !is_readable( $config_file ) ) - return 'cannot read file'; // not sure that can actually happen... + if( !is_readable( $config_file ) ) { + yourls_debug_log( 'Cannot hash passwords: cannot read file ' . $config_file ); + return 'cannot read file'; // not sure that can actually happen... + } - if( !is_writable( $config_file ) ) + if( !is_writable( $config_file ) ) { + yourls_debug_log( 'Cannot hash passwords: cannot write file ' . $config_file ); return 'cannot write file'; + } $yourls_user_passwords = []; // Include file to read value of $yourls_user_passwords @@ -188,11 +192,16 @@ function yourls_hash_passwords_now( $config_file ) { error_reporting( $errlevel ); $configdata = file_get_contents( $config_file ); - if( $configdata == false ) - return 'could not read file'; + + if( $configdata == false ) { + yourls_debug_log('Cannot hash passwords: file_get_contents() false with ' . $config_file); + return 'could not read file'; + } $to_hash = 0; // keep track of number of passwords that need hashing foreach ( $yourls_user_passwords as $user => $password ) { + // avoid "deprecated" warning when password is null -- see test case in tests/data/auth/preg_replace_problem.php + $password ??= ''; if ( !yourls_has_phpass_password( $user ) && !yourls_has_md5_password( $user ) ) { $to_hash++; $hash = yourls_phpass_hash( $password ); @@ -211,8 +220,10 @@ function yourls_hash_passwords_now( $config_file ) { } } - if( $to_hash == 0 ) - return 0; // There was no password to encrypt + if( $to_hash == 0 ) { + yourls_debug_log('Cannot hash passwords: no password found in ' . $config_file); + return 'no password found'; + } $success = file_put_contents( $config_file, $configdata ); if ( $success === FALSE ) { @@ -427,9 +438,9 @@ function yourls_check_timestamp( $time ) { /** * Store new cookie. No $user will delete the cookie. * - * @param mixed $user String, user login, or null to delete cookie + * @param string $user User login, or empty string to delete cookie */ -function yourls_store_cookie( $user = null ) { +function yourls_store_cookie( $user = '' ) { // No user will delete the cookie with a cookie time from the past if( !$user ) { @@ -554,7 +565,7 @@ function yourls_cookie_name() { * @return string cookie value */ function yourls_cookie_value( $user ) { - return yourls_apply_filter( 'set_cookie_value', yourls_salt( $user ), $user ); + return yourls_apply_filter( 'set_cookie_value', yourls_salt( $user ?? '' ), $user ); } /** diff --git a/includes/functions-deprecated.php b/includes/functions-deprecated.php index a481f771..65141f0c 100644 --- a/includes/functions-deprecated.php +++ b/includes/functions-deprecated.php @@ -10,6 +10,30 @@ // @codeCoverageIgnoreStart /** + * PHP emulation of JS's encodeURI + * + * @link https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURI + * @deprecated 1.9.1 + * @param string $url + * @return string + */ +function yourls_encodeURI($url) { + yourls_deprecated_function( __FUNCTION__, '1.9.1', 'no replacement needed' ); + // Decode URL all the way + $result = yourls_rawurldecode_while_encoded( $url ); + // Encode once + $result = strtr( rawurlencode( $result ), array ( + '%3B' => ';', '%2C' => ',', '%2F' => '/', '%3F' => '?', '%3A' => ':', '%40' => '@', + '%26' => '&', '%3D' => '=', '%2B' => '+', '%24' => '$', '%21' => '!', '%2A' => '*', + '%27' => '\'', '%28' => '(', '%29' => ')', '%23' => '#', + ) ); + // @TODO: + // Known limit: this will most likely break IDN URLs such as http://www.académie-française.fr/ + // To fully support IDN URLs, advocate use of a plugin. + return yourls_apply_filter( 'encodeURI', $result, $url ); +} + +/** * Check if a file is a plugin file * * @deprecated 1.8.3 diff --git a/includes/functions-formatting.php b/includes/functions-formatting.php index 08ac8d93..8e80544b 100644 --- a/includes/functions-formatting.php +++ b/includes/functions-formatting.php @@ -14,8 +14,8 @@ function yourls_int2string( $num, $chars = null ) { $string = ''; $len = strlen( $chars ); while( $num >= $len ) { - $mod = bcmod( $num, $len ); - $num = bcdiv( $num, $len ); + $mod = bcmod( (string)$num, (string)$len ); + $num = bcdiv( (string)$num, (string)$len ); $string = $chars[ $mod ] . $string; } $string = $chars[ intval( $num ) ] . $string; @@ -36,7 +36,7 @@ function yourls_string2int( $string, $chars = null ) { $inputlen = strlen( $string ); for ($i = 0; $i < $inputlen; $i++) { $index = strpos( $chars, $string[$i] ); - $integer = bcadd( $integer, bcmul( $index, bcpow( $baselen, $i ) ) ); + $integer = bcadd( (string)$integer, bcmul( (string)$index, bcpow( (string)$baselen, (string)$i ) ) ); } return yourls_apply_filter( 'string2int', $integer, $string, $chars ); @@ -417,6 +417,8 @@ function yourls_specialchars_decode( $string, $quote_style = ENT_NOQUOTES ) { $others = array( '<' => '<', '<' => '<', '>' => '>', '>' => '>', '&' => '&', '&' => '&', '&' => '&' ); $others_preg = array( '/�*60;/' => '<', '/�*62;/' => '>', '/�*38;/' => '&', '/�*26;/i' => '&' ); + $translation = $translation_preg = []; + if ( $quote_style === ENT_QUOTES ) { $translation = array_merge( $single, $double, $others ); $translation_preg = array_merge( $single_preg, $double_preg, $others_preg ); @@ -654,29 +656,6 @@ function yourls_esc_textarea( $text ) { return yourls_apply_filter( 'esc_textarea', $safe_text, $text ); } - -/** -* PHP emulation of JS's encodeURI -* -* @link https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURI -* @param $url -* @return string -*/ -function yourls_encodeURI( $url ) { - // Decode URL all the way - $result = yourls_rawurldecode_while_encoded( $url ); - // Encode once - $result = strtr( rawurlencode( $result ), array ( - '%3B' => ';', '%2C' => ',', '%2F' => '/', '%3F' => '?', '%3A' => ':', '%40' => '@', - '%26' => '&', '%3D' => '=', '%2B' => '+', '%24' => '$', '%21' => '!', '%2A' => '*', - '%27' => '\'', '%28' => '(', '%29' => ')', '%23' => '#', - ) ); - // @TODO: - // Known limit: this will most likely break IDN URLs such as http://www.académie-française.fr/ - // To fully support IDN URLs, advocate use of a plugin. - return yourls_apply_filter( 'encodeURI', $result, $url ); -} - /** * Adds backslashes before letters and before a number at the start of a string. Stolen from WP. * @@ -793,4 +772,3 @@ function yourls_get_date_format( $format ) { function yourls_get_time_format( $format ) { return yourls_apply_filter( 'get_time_format', (string)$format ); } - diff --git a/includes/functions-html.php b/includes/functions-html.php index 2ae620f8..4ec014f7 100644 --- a/includes/functions-html.php +++ b/includes/functions-html.php @@ -205,7 +205,7 @@ function yourls_html_addnew( $url = '', $keyword = '' ) { * The $param array is defined in /admin/index.php, check the yourls_html_tfooter() call * * @param array $params Array of all required parameters - * @return string Result + * @return void */ function yourls_html_tfooter( $params = array() ) { // Manually extract all parameters from the array. We prefer doing it this way, over using extract(), @@ -614,7 +614,7 @@ function yourls_table_add_row( $keyword, $url, $title, $ip, $clicks, $timestamp ), 'clicks' => array( 'template' => '%clicks%', - 'clicks' => yourls_number_format_i18n( $clicks, 0, '', '' ), + 'clicks' => yourls_number_format_i18n( $clicks, 0 ), ), 'actions' => array( 'template' => '%actions% <input type="hidden" id="keyword_%id%" value="%keyword%"/>', @@ -854,7 +854,7 @@ HTML; * were a standard short URL (ie http://sho.rt/$page) * * @since 1.0 - * @param $page PHP file to display + * @param string $page PHP file to display */ function yourls_page( $page ) { if( !yourls_is_page($page)) { @@ -920,7 +920,7 @@ function yourls_l10n_calendar_strings() { * @since 1.7 * @param string $compare_with Optional, YOURLS version to compare to */ -function yourls_new_core_version_notice($compare_with = false) { +function yourls_new_core_version_notice($compare_with = null) { $compare_with = $compare_with ?: YOURLS_VERSION; $checks = yourls_get_option( 'core_version_checks' ); @@ -971,7 +971,7 @@ function yourls_set_html_context($context) { * @return string */ function yourls_get_html_context() { - yourls_get_db()->get_html_context(); + return yourls_get_db()->get_html_context(); } /** diff --git a/includes/functions-http.php b/includes/functions-http.php index 16d7e71f..7621e7b7 100644 --- a/includes/functions-http.php +++ b/includes/functions-http.php @@ -360,8 +360,8 @@ function yourls_check_core_version() { * 3) the object should not contain any other key * * @since 1.7.7 - * @param $json JSON object to check - * @return bool true if seems legit, false otherwise + * @param object $json JSON object to check + * @return bool true if seems legit, false otherwise */ function yourls_validate_core_version_response($json) { return ( @@ -381,7 +381,7 @@ function yourls_validate_core_version_response($json) { */ function yourls_get_version_from_zipball_url($zipurl) { $version = ''; - $parts = explode('/', parse_url(yourls_sanitize_url($zipurl), PHP_URL_PATH)); + $parts = explode('/', parse_url(yourls_sanitize_url($zipurl), PHP_URL_PATH) ?? ''); // expect at least 1 slash in path, return last part if( count($parts) > 1 ) { $version = end($parts); @@ -395,7 +395,7 @@ function yourls_get_version_from_zipball_url($zipurl) { function yourls_is_valid_github_repo_url($url) { $url = yourls_sanitize_url($url); return ( - join('.',array_slice(explode('.',parse_url($url, PHP_URL_HOST)), -2, 2)) === 'github.com' + join('.',array_slice(explode('.', parse_url($url, PHP_URL_HOST) ?? ''), -2, 2)) === 'github.com' // explodes on '.' (['api','github','com']) and keeps the last two elements // to make sure domain is either github.com or one of its subdomain (api.github.com for instance) // TODO: keep an eye on Github API to make sure it doesn't change some day to another domain (githubapi.com, ...) diff --git a/includes/functions-l10n.php b/includes/functions-l10n.php index ead4c3c7..cbced0cf 100644 --- a/includes/functions-l10n.php +++ b/includes/functions-l10n.php @@ -32,7 +32,7 @@ use POMO\Translations\NOOPTranslations; * @uses yourls_apply_filter() Calls 'get_locale' hook on locale value. * @uses $yourls_locale Gets the locale stored in the global. * - * @return string The locale of the blog or from the 'get_locale' hook. + * @return string The locale of the YOURLS instance */ function yourls_get_locale() { global $yourls_locale; @@ -116,8 +116,7 @@ function yourls__( $text, $domain = 'default' ) { * @see sprintf() * @since 1.6 * - * @param string $pattern Text to translate - * @param string $arg1, $arg2... Optional: sprintf tokens, and translation domain + * @param mixed ...$pattern Text to translate, then $arg1: optional sprintf tokens, and $arg2: translation domain * @return string Translated text */ function yourls_s( $pattern ) { @@ -158,9 +157,8 @@ function yourls_s( $pattern ) { * @see sprintf() * @since 1.6 * - * @param string $pattern Text to translate - * @param string $arg1, $arg2... Optional: sprintf tokens, and translation domain - * @return string Translated text + * @param string ...$pattern Text to translate, then optional sprintf tokens, and optional translation domain + * @return void Translated text */ function yourls_se( $pattern ) { echo yourls_s( func_get_args() ); @@ -269,7 +267,7 @@ function yourls_x( $text, $context, $domain = 'default' ) { * @param string $text Text to translate * @param string $context Context information for the translators * @param string $domain Optional. Domain to retrieve the translated text - * @return string Translated context string + * @return void Echoes translated context string */ function yourls_xe( $text, $context, $domain = 'default' ) { echo yourls_x( $text, $context, $domain ); @@ -510,6 +508,8 @@ function yourls_load_default_textdomain() { if( !empty( $yourls_locale ) ) return yourls_load_textdomain( 'default', YOURLS_LANG_DIR . "/$yourls_locale.mo" ); + + return false; } /** @@ -605,6 +605,9 @@ function yourls_number_format_i18n( $number, $decimals = 0 ) { * @return string The date, translated if locale specifies it. */ function yourls_date_i18n( $dateformatstring, $timestamp = false ) { + /** + * @var YOURLS_Locale_Formats $yourls_locale_formats + */ global $yourls_locale_formats; if( !isset( $yourls_locale_formats ) ) $yourls_locale_formats = new YOURLS_Locale_Formats(); @@ -845,7 +848,7 @@ class YOURLS_Locale_Formats { * @since 1.6 * @access public * - * @param int $weekday_number 0 for Sunday through 6 Saturday + * @param int|string $weekday_number 0 for Sunday through 6 Saturday * @return string Full translated weekday */ function get_weekday( $weekday_number ) { diff --git a/includes/functions-plugins.php b/includes/functions-plugins.php index 6e64f94f..596d1cc6 100644 --- a/includes/functions-plugins.php +++ b/includes/functions-plugins.php @@ -55,7 +55,7 @@ * ) * ) * - * @var array + * @var array $yourls_filters */ if ( !isset( $yourls_filters ) ) { $yourls_filters = []; @@ -65,7 +65,7 @@ if ( !isset( $yourls_filters ) ) { * This global var will collect 'done' actions with the following structure: * $yourls_actions['hook'] => number of time this action was done * - * @var array + * @var array $yourls_actions */ if ( !isset( $yourls_actions ) ) { $yourls_actions = []; @@ -79,7 +79,7 @@ if ( !isset( $yourls_actions ) ) { * * @link https://docs.yourls.org/development/plugins.html * @param string $hook the name of the YOURLS element to be filtered or YOURLS action to be triggered - * @param callback $function_name the name of the function that is to be called. + * @param callable $function_name the name of the function that is to be called. * @param int $priority optional. Used to specify the order in which the functions associated with a * particular action are executed (default=10, lower=earlier execution, and functions * with the same priority are executed in the order in which they were added to the @@ -92,7 +92,7 @@ if ( !isset( $yourls_actions ) ) { function yourls_add_filter( $hook, $function_name, $priority = 10, $accepted_args = NULL, $type = 'filter' ) { global $yourls_filters; // At this point, we cannot check if the function exists, as it may well be defined later (which is OK) - $id = yourls_filter_unique_id( $hook, $function_name, $priority ); + $id = yourls_filter_unique_id($function_name); $yourls_filters[ $hook ][ $priority ][ $id ] = [ 'function' => $function_name, @@ -114,7 +114,7 @@ function yourls_add_filter( $hook, $function_name, $priority = 10, $accepted_arg * * @link https://docs.yourls.org/development/plugins.html * @param string $hook The name of the action to which the $function_to_add is hooked. - * @param callback $function_name The name of the function you wish to be called. + * @param callable $function_name The name of the function you wish to be called. * @param int $priority Optional. Used to specify the order in which the functions associated with a particular action * are executed (default: 10). Lower numbers correspond with earlier execution, and functions * with the same priority are executed in the order in which they were added to the action. @@ -142,14 +142,11 @@ function yourls_add_action( $hook, $function_name, $priority = 10, $accepted_arg * yourls_add_filter('my_hook_test', $my_callback_function); * * @link https://docs.yourls.org/development/hooks.html - * @param string $hook Hook to which the function is attached - * @param string|array $function Used for creating unique id - * @param int|bool $priority Used in counting how many hooks were applied. If === false and $function is an object reference, - * we return the unique id only if it already has one, false otherwise. + * @param string|array|object $function The callable used in a filter or action. * @return string unique ID for usage as array key */ -function yourls_filter_unique_id( $hook, $function, $priority ) { - // If function then just skip all of the tests and not overwrite the following. +function yourls_filter_unique_id($function) { + // If given a string (function name) if ( is_string( $function ) ) { return $function; } @@ -167,20 +164,12 @@ function yourls_filter_unique_id( $hook, $function, $priority ) { return spl_object_hash( $function[0] ).$function[1]; } - // Static Calling - if ( is_string( $function[0] ) ) { - return $function[0].'::'.$function[1]; - } - - /** - * There is no other possible case as of PHP 7.2-8.0 callables. Still, we're leaving the final - * `if` block (which could be remove to simply `return $function[0].'::'.$function[1]`) for readability - * and understanding the logic. - */ + // Last case, static Calling : $function[0] is a string (Class Name) and $function[1] is a string (Method Name) + return $function[0].'::'.$function[1]; } /** - * Performs a filtering operation on a YOURLS element or event. + * Performs a filtering operation on a value or an event. * * Typical use: * @@ -192,12 +181,12 @@ function yourls_filter_unique_id( $hook, $function, $priority ) { * yourls_apply_filter( 'yourls_event' ); * (see yourls_do_action() ) * - * Returns an element which may have been filtered by a filter. + * Returns a value which may have been modified by a filter. * * @global array $yourls_filters storage for all of the filters * @param string $hook the name of the YOURLS element or action * @param mixed $value the value of the element before filtering - * @param bool $is_action true if the function is called by yourls_do_action() + * @param true|mixed $is_action true if the function is called by yourls_do_action() - otherwise may be the second parameter of an arbitrary number of parameters * @return mixed */ function yourls_apply_filter( $hook, $value = '', $is_action = false ) { @@ -222,6 +211,7 @@ function yourls_apply_filter( $hook, $value = '', $is_action = false ) { reset( $yourls_filters[ $hook ] ); do { foreach ( (array)current( $yourls_filters[ $hook ] ) as $the_ ) { + $_value = ''; if ( !is_null($the_[ 'function' ]) ) { $args[ 1 ] = $value; $count = $the_[ 'accepted_args' ]; @@ -340,14 +330,14 @@ function yourls_call_all_hooks($type, $hook, ...$args) { * * @global array $yourls_filters storage for all of the filters * @param string $hook The filter hook to which the function to be removed is hooked. - * @param callback $function_to_remove The name of the function which should be removed. + * @param callable $function_to_remove The name of the function which should be removed. * @param int $priority optional. The priority of the function (default: 10). * @return bool Whether the function was registered as a filter before it was removed. */ function yourls_remove_filter( $hook, $function_to_remove, $priority = 10 ) { global $yourls_filters; - $function_to_remove = yourls_filter_unique_id( $hook, $function_to_remove, $priority ); + $function_to_remove = yourls_filter_unique_id($function_to_remove); $remove = isset( $yourls_filters[ $hook ][ $priority ][ $function_to_remove ] ); @@ -453,7 +443,7 @@ function yourls_has_filter( $hook, $function_to_check = false ) { return $has; } - if ( !$idx = yourls_filter_unique_id( $hook, $function_to_check, false ) ) { + if ( !$idx = yourls_filter_unique_id($function_to_check) ) { return false; } diff --git a/includes/functions-upgrade.php b/includes/functions-upgrade.php index 2de8e0e2..72703458 100644 --- a/includes/functions-upgrade.php +++ b/includes/functions-upgrade.php @@ -206,8 +206,8 @@ function yourls_upgrade_to_143( ) { */ function yourls_upgrade_to_141( ) { // Kill old cookies from 1.3 and prior - setcookie('yourls_username', null, time() - 3600 ); - setcookie('yourls_password', null, time() - 3600 ); + setcookie('yourls_username', '', time() - 3600 ); + setcookie('yourls_password', '', time() - 3600 ); // alter table URL yourls_alter_url_table_to_141(); // recreate the htaccess file if needed @@ -445,4 +445,3 @@ function yourls_clean_htaccess_for_14() { return $result; } - diff --git a/includes/functions.php b/includes/functions.php index 55860ea2..a7b74f4d 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -6,7 +6,8 @@ /** * Make an optimized regexp pattern from a string of characters - * @param $string + * + * @param string $string * @return string */ function yourls_make_regexp_pattern( $string ) { @@ -52,17 +53,17 @@ function yourls_get_next_decimal() { * Update id for next link with no custom keyword * * Note: this function relies upon yourls_update_option(), which will return either true or false - * depending if there has been an actual MySQL query updating the DB. + * depending upon if there has been an actual MySQL query updating the DB. * In other words, this function may return false yet this would not mean it has functionally failed - * In other words I'm not sure we really need this function to return something :face_with_eyes_looking_up: + * In other words I'm not sure if we really need this function to return something :face_with_eyes_looking_up: * See issue 2621 for more on this. * * @since 1.0 - * @param integer $int id for next link + * @param integer $int id for next link * @return bool true or false depending on if there has been an actual MySQL query. See note above. */ -function yourls_update_next_decimal( $int = '' ) { - $int = ( $int == '' ) ? yourls_get_next_decimal() + 1 : (int)$int ; +function yourls_update_next_decimal( $int = 0 ) { + $int = ( $int == 0 ) ? yourls_get_next_decimal() + 1 : (int)$int ; $update = yourls_update_option( 'next_id', $int ); yourls_do_action( 'update_next_decimal', $int, $update ); return $update; @@ -74,13 +75,14 @@ function yourls_update_next_decimal( $int = '' ) { * @return string */ function yourls_xml_encode( $array ) { - return (\Spatie\ArrayToXml\ArrayToXml::convert($array)); + return (\Spatie\ArrayToXml\ArrayToXml::convert($array, '', true, 'UTF-8')); } /** * Update click count on a short URL. Return 0/1 for error/success. - * @param string $keyword - * @param bool $clicks + * + * @param string $keyword + * @param false|int $clicks * @return mixed|string */ function yourls_update_clicks( $keyword, $clicks = false ) { @@ -175,7 +177,7 @@ function yourls_get_stats( $filter = 'top', $limit = 10, $start = 0 ) { * $where['sql'] will concatenate SQL clauses: $where['sql'] = ' AND something = :value AND otherthing < :othervalue'; * $where['binds'] will hold the (name => value) placeholder pairs: $where['binds'] = array('value' => $value, 'othervalue' => $value2) * - * @param $where array See comment above + * @param array $where See comment above * @return array */ function yourls_get_db_stats( $where = [ 'sql' => '', 'binds' => [] ] ) { @@ -935,7 +937,7 @@ function yourls_is_mobile_device() { * @param string $uri Optional, page requested (default to $_SERVER['REQUEST_URI'] eg '/yourls/abcd' ) * @return string request relative to YOURLS base (eg 'abdc') */ -function yourls_get_request($yourls_site = false, $uri = false) { +function yourls_get_request($yourls_site = '', $uri = '') { // Allow plugins to short-circuit the whole function $pre = yourls_apply_filter( 'shunt_get_request', false ); if ( false !== $pre ) { @@ -945,10 +947,10 @@ function yourls_get_request($yourls_site = false, $uri = false) { yourls_do_action( 'pre_get_request', $yourls_site, $uri ); // Default values - if ( false === $yourls_site ) { + if ( '' === $yourls_site ) { $yourls_site = yourls_get_yourls_site(); } - if ( false === $uri ) { + if ( '' === $uri ) { $uri = $_SERVER[ 'REQUEST_URI' ]; } @@ -1250,7 +1252,7 @@ function yourls_get_protocol_slashes_and_rest( $url, $array = [ 'protocol', 'sla * @param string $scheme scheme, either 'http' or 'https' * @return string URL with chosen scheme */ -function yourls_set_url_scheme( $url, $scheme = false ) { +function yourls_set_url_scheme( $url, $scheme = '' ) { if ( in_array( $scheme, [ 'http', 'https' ] ) ) { $url = preg_replace( '!^[a-zA-Z0-9+.-]+://!', $scheme.'://', $url ); } diff --git a/tests/data/auth/nopassword.php b/tests/data/auth/nopassword.php new file mode 100644 index 00000000..c4f37750 --- /dev/null +++ b/tests/data/auth/nopassword.php @@ -0,0 +1,3 @@ +<?php + +/** No password defined */ diff --git a/tests/data/auth/preg_replace_problem.php b/tests/data/auth/preg_replace_problem.php new file mode 100644 index 00000000..6639f971 --- /dev/null +++ b/tests/data/auth/preg_replace_problem.php @@ -0,0 +1,9 @@ +<?php + +/** Valid PHP syntax but too complicated for our parser */ + +$login = 'joe'; +$password = 'some_password'; +$yourls_user_passwords = [ + $login => $password, +]; diff --git a/tests/tests/auth/auth.php b/tests/tests/auth/auth.php index 3cd8b0f2..703acbb1 100644 --- a/tests/tests/auth/auth.php +++ b/tests/tests/auth/auth.php @@ -216,6 +216,20 @@ class Auth_Func_Tests extends PHPUnit\Framework\TestCase { } /** + * Check that encrypting file with no passwords returns expected error + */ + public function test_hash_passwords_now_no_pwd() { + $this->assertSame('no password found', yourls_hash_passwords_now( YOURLS_TESTDATA_DIR . '/auth/nopassword.php' ) ); + } + + /** + * Check that encrypting file with incorrect content returns expected error + */ + public function test_hash_passwords_now_bad_content() { + $this->assertSame('preg_replace problem', yourls_hash_passwords_now( YOURLS_TESTDATA_DIR . '/auth/preg_replace_problem.php' ) ); + } + + /** * Check that in-file password encryption works as expected with different kinds of passwords * * This test checks that encrypting the config file, with different kinds of pwd, results in a valid diff --git a/tests/tests/auth/logout.php b/tests/tests/auth/logout.php index a7153d9e..674d0097 100644 --- a/tests/tests/auth/logout.php +++ b/tests/tests/auth/logout.php @@ -51,7 +51,7 @@ class Logout_Func_Tests extends PHPUnit\Framework\TestCase { $_REQUEST['nonce'] = yourls_create_nonce('admin_logout', 'logout'); $invalid = yourls_is_valid_user(); $this->assertNotTrue( $invalid ); - $this->assertSame(self::$user, null); + $this->assertSame(self::$user, ''); } /** diff --git a/tests/tests/format/sanitizing.php b/tests/tests/format/sanitizing.php index fe48137e..31b9445a 100644 --- a/tests/tests/format/sanitizing.php +++ b/tests/tests/format/sanitizing.php @@ -34,6 +34,7 @@ class Format_Sanitize extends PHPUnit\Framework\TestCase { $unsane = '<tag></tag><omg>'; $this->assertSame( $expected, yourls_sanitize_title( $unsane ) ); $this->assertSame( $fallback, yourls_sanitize_title( $unsane, $fallback ) ); + $this->assertSame( $fallback, yourls_sanitize_title( '', $fallback ) ); } /** diff --git a/tests/tests/plugins/helpers.php b/tests/tests/plugins/helpers.php index b662e849..d954c0ce 100644 --- a/tests/tests/plugins/helpers.php +++ b/tests/tests/plugins/helpers.php @@ -30,4 +30,17 @@ class Plugin_Helpers_Tests extends PHPUnit\Framework\TestCase { $this->assertSame( $value, call_user_func($func) ); } + /** + * Test return values of yourls_filter_unique_id() + */ + function test_yourls_filter_unique_id() { + $func_name = rand_str(); + + $this->assertSame( $func_name, yourls_filter_unique_id($func_name) ); + $this->assertIsString( yourls_filter_unique_id( function(){return rand_str();} ) ); // unpredictable string + $this->assertSame('SomeClass::SomeMethod', yourls_filter_unique_id( 'SomeClass::SomeMethod' )); + $this->assertSame('SomeClass::SomeMethod', yourls_filter_unique_id( array( 'SomeClass', 'SomeMethod' ) )); + $this->assertIsString( yourls_filter_unique_id( array( $this, 'test_check_timestamp' ) )); // unpredictable string + } + } diff --git a/tests/tests/shorturl/crud.php b/tests/tests/shorturl/crud.php index 5335c1cd..57446738 100644 --- a/tests/tests/shorturl/crud.php +++ b/tests/tests/shorturl/crud.php @@ -68,10 +68,17 @@ class ShortURL_CRUD_Tests extends PHPUnit\Framework\TestCase { $cache = yourls_get_keyword_infos( $keyword, false ); $this->assertEquals( 0, yourls_get_keyword_clicks( $keyword ) ); + // Increment by 1 $this->assertEquals( 1, yourls_update_clicks( $keyword ) ); // purge cache yourls_get_keyword_infos( $keyword, false ); $this->assertEquals( 1, yourls_get_keyword_clicks( $keyword ) ); + + // Increment by specified number + $this->assertEquals( 1, yourls_update_clicks( $keyword, 10 ) ); + // purge cache + yourls_get_keyword_infos( $keyword, false ); + $this->assertEquals( 10, yourls_get_keyword_clicks( $keyword ) ); } /** |