[ Index ]

PHP Cross Reference of GlotPress

title

Body

[close]

/gp-includes/ -> misc.php (source)

   1  <?php
   2  
   3  /**
   4   * Retrieves a value from $_POST.
   5   *
   6   * @param string       $key     Name of post value.
   7   * @param string|array $default Optional. Value to return if `$_POST[ $key ]` doesn't exist. Default empty.
   8   * @return string|array Value of `$_POST[ $key ]` if exists or `$default`.
   9   */
  10  function gp_post( $key, $default = '' ) {
  11      // phpcs:ignore WordPress.Security.NonceVerification -- Helper to retrieve item from the request.
  12      return wp_unslash( gp_array_get( $_POST, $key, $default ) );
  13  }
  14  
  15  /**
  16   * Retrieves a value from $_GET.
  17   *
  18   * @param string       $key     Name of get value.
  19   * @param string|array $default Optional. Value to return if `$_GET[ $key ]` doesn't exist. Default empty.
  20   * @return string|array Value of `$_GET[ $key ]` if exists or `$default`.
  21   */
  22  function gp_get( $key, $default = '' ) {
  23      // phpcs:ignore WordPress.Security.NonceVerification -- Helper to retrieve item from the request.
  24      return wp_unslash( gp_array_get( $_GET, $key, $default ) );
  25  }
  26  
  27  /**
  28   * Prints a nonce hidden field for route actions.
  29   *
  30   * @since 2.0.0
  31   *
  32   * @see wp_nonce_field()
  33   *
  34   * @param int|string $action Action name.
  35   * @param bool       $echo   Optional. Whether to display or return hidden form field. Default true.
  36   * @return string Nonce field HTML markup.
  37   */
  38  function gp_route_nonce_field( $action, $echo = true ) {
  39      return wp_nonce_field( $action, '_gp_route_nonce', true, $echo );
  40  }
  41  
  42  /**
  43   * Retrieves a URL with a nonce added to URL query for route actions.
  44   *
  45   * @since 2.0.0
  46   *
  47   * @see wp_nonce_url()
  48   *
  49   * @param string     $url    URL to add nonce action.
  50   * @param int|string $action Action name.
  51   * @return string Escaped URL with nonce action added.
  52   */
  53  function gp_route_nonce_url( $url, $action ) {
  54      return wp_nonce_url( $url, $action, $name = '_gp_route_nonce' );
  55  }
  56  
  57  /**
  58   * Retrieves a value from $array
  59   *
  60   * @param array  $array
  61   * @param string $key name of array value
  62   * @param mixed  $default value to return if $array[$key] doesn't exist. Default is ''
  63   * @return mixed $array[$key] if exists or $default
  64   */
  65  function gp_array_get( $array, $key, $default = '' ) {
  66      return isset( $array[ $key ] ) ? $array[ $key ] : $default;
  67  }
  68  
  69  function gp_const_get( $name, $default = '' ) {
  70      return defined( $name ) ? constant( $name ) : $default;
  71  }
  72  
  73  function gp_const_set( $name, $value ) {
  74      if ( defined( $name ) ) {
  75          return false;
  76      }
  77      define( $name, $value );
  78      return true;
  79  }
  80  
  81  
  82  function gp_member_get( $object, $key, $default = '' ) {
  83      return isset( $object->$key ) ? $object->$key : $default;
  84  }
  85  
  86  /**
  87   * Makes from an array of arrays a flat array.
  88   *
  89   * @param array $array the arra to flatten
  90   * @return array flattenned array
  91   */
  92  function gp_array_flatten( $array ) {
  93      $res = array();
  94      foreach ( $array as $value ) {
  95          $res = array_merge( $res, is_array( $value ) ? gp_array_flatten( $value ) : array( $value ) );
  96      }
  97      return $res;
  98  }
  99  
 100  /**
 101   * Passes the message set through the next redirect.
 102   *
 103   * Works best for edit requests, which want to pass error message or notice back to the listing page.
 104   *
 105   * @param string $message The message to be passed.
 106   * @param string $key     Optional. Key for the message. You can pass several messages under different keys.
 107   *                        A key has one message. The default is 'notice'.
 108   */
 109  function gp_notice_set( $message, $key = 'notice' ) {
 110      $cookie_path = '/' . ltrim( gp_url_path(), '/' ); // Make sure that the cookie path is never empty.
 111      gp_set_cookie( '_gp_notice_' . $key, $message, 0, $cookie_path );
 112  }
 113  
 114  /**
 115   * Retrieves a notice message, set by {@link gp_notice()}
 116   *
 117   * @param string $key Optional. Message key. The default is 'notice'
 118   */
 119  function gp_notice( $key = 'notice' ) {
 120      // Sanitize fields
 121      $allowed_tags = array(
 122          'a'       => array( 'href' => true ),
 123          'abbr'    => array(),
 124          'acronym' => array(),
 125          'b'       => array(),
 126          'br'      => array(),
 127          'button'  => array(
 128              'disabled' => true,
 129              'name'     => true,
 130              'type'     => true,
 131              'value'    => true,
 132          ),
 133          'em'      => array(),
 134          'i'       => array(),
 135          'img'     => array(
 136              'src'    => true,
 137              'width'  => true,
 138              'height' => true,
 139          ),
 140          'p'       => array(),
 141          'pre'     => array(),
 142          's'       => array(),
 143          'strike'  => array(),
 144          'strong'  => array(),
 145          'sub'     => array(),
 146          'sup'     => array(),
 147          'u'       => array(),
 148      );
 149  
 150      // Adds class, id, style, title, role attributes to all of the above allowed tags.
 151      $allowed_tags = array_map( '_wp_add_global_attributes', $allowed_tags );
 152  
 153      return wp_kses( gp_array_get( GP::$redirect_notices, $key ), $allowed_tags );
 154  }
 155  
 156  function gp_populate_notices() {
 157      GP::$redirect_notices = array();
 158      $prefix               = '_gp_notice_';
 159      $cookie_path          = '/' . ltrim( gp_url_path(), '/' ); // Make sure that the cookie path is never empty.
 160      foreach ( $_COOKIE as $key => $value ) {
 161          if ( gp_startswith( $key, $prefix ) && $suffix = substr( $key, strlen( $prefix ) ) ) {
 162              GP::$redirect_notices[ $suffix ] = wp_unslash( $value );
 163              gp_set_cookie( $key, '', 0, $cookie_path );
 164          }
 165      }
 166  }
 167  
 168  /**
 169   * Returns an array of arrays, where the i-th array contains the i-th element from
 170   * each of the argument arrays. The returned array is truncated in length to the length
 171   * of the shortest argument array.
 172   *
 173   * Previously this function was documented as:
 174   *
 175   *      The function works only with numerical arrays.
 176   *
 177   * However this was incorrect, this function would only return an array of arrays with
 178   * numeric basic indexes, but would process any array whether it was numeric or reference
 179   * based, using the order in which the array was created as the index value to return.
 180   *
 181   * For example:
 182   *
 183   *      $first_array[] = "First"
 184   *      $first_array[] = "Second"
 185   *      $first_array[] = "Third"
 186   *
 187   *      $second_array[0]    = "Fourth"
 188   *      $second_array[test] = "Fifth"
 189   *      $second_array[1]    = "Sixth"
 190   *
 191   *      $result = gp_array_zip( $first_array, $second_array );
 192   *
 193   * Would produce:
 194   *
 195   *      $result[0][0] = "First"
 196   *      $result[0][1] = "Fourth"
 197   *      $result[1][0] = "Second"
 198   *      $result[1][1] = "Fifth"
 199   *      $result[2][0] = "Third"
 200   *      $result[2][1] = "Sixth"
 201   *
 202   * Instead of either failing (which is probably what should have happened) or something like:
 203   *
 204   *      $result[0][0] = "First"
 205   *      $result[0][1] = "Fourth"
 206   *      $result[1][0] = "Second"
 207   *      $result[1][1] = "Sixth"
 208   *
 209   * Or some other random result.
 210   *
 211   * @param array ...$args Array arguments.
 212   * @return array|false Array on success, false on failure.
 213   */
 214  function gp_array_zip( ...$args ) {
 215      if ( empty( $args ) ) {
 216          return array();
 217      }
 218  
 219      $depth = 0;
 220  
 221      foreach ( $args as &$array ) {
 222          if ( ! is_array( $array ) ) {
 223              return false;
 224          }
 225  
 226          $array_size = count( $array );
 227          reset( $array );
 228  
 229          if ( 0 === $depth || $depth > $array_size ) {
 230              $depth = $array_size;
 231          }
 232      }
 233  
 234      $res = array();
 235  
 236      $array_count = 0;
 237  
 238      foreach ( $args as &$array ) {
 239          for ( $i = 0; $i < $depth; $i++ ) {
 240              $res[ $i ][ $array_count ] = current( $array );
 241  
 242              next( $array );
 243          }
 244  
 245          $array_count++;
 246      }
 247  
 248      return $res;
 249  }
 250  
 251  function gp_array_any( $callback, $array, $arg = null ) {
 252      foreach ( $array as $item ) {
 253          if ( is_array( $callback ) ) {
 254              if ( $callback[0]->{$callback[1]}( $item, $arg ) ) {
 255                  return true;
 256              }
 257          } else {
 258              if ( $callback( $item, $arg ) ) {
 259                  return true;
 260              }
 261          }
 262      }
 263      return false;
 264  }
 265  
 266  function gp_array_all( $callback, $array ) {
 267      foreach ( $array as $item ) {
 268          if ( ! $callback( $item ) ) {
 269              return false;
 270          }
 271      }
 272      return true;
 273  }
 274  
 275  function gp_error_log_dump( $value ) {
 276      if ( is_array( $value ) || is_object( $value ) ) {
 277          $value = print_r( $value, true );
 278      }
 279      error_log( $value );
 280  }
 281  
 282  function gp_object_has_var( $object, $var_name ) {
 283      return in_array( $var_name, array_keys( get_object_vars( $object ) ), true );
 284  }
 285  
 286  /**
 287   * Has this translation been updated since the passed timestamp?
 288   *
 289   * @param GP_Translation_Set $translation_set Translation to check
 290   * @param int                $timestamp Optional; unix timestamp to compare against. Defaults to HTTP_IF_MODIFIED_SINCE if set.
 291   * @return bool
 292   */
 293  function gp_has_translation_been_updated( $translation_set, $timestamp = 0 ) {
 294  
 295      // If $timestamp isn't set, try to default to the HTTP_IF_MODIFIED_SINCE header.
 296      if ( ! $timestamp && isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) {
 297          $timestamp = gp_gmt_strtotime( wp_unslash( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) );
 298      }
 299  
 300      // If nothing to compare against, then always assume there's an update available
 301      if ( ! $timestamp ) {
 302          return true;
 303      }
 304  
 305      return gp_gmt_strtotime( GP::$translation->last_modified( $translation_set ) ) > $timestamp;
 306  }
 307  
 308  
 309  /**
 310   * Delete translation set counts cache.
 311   *
 312   * @global bool $_wp_suspend_cache_invalidation
 313   *
 314   * @param int $id Translation set ID.
 315   */
 316  function gp_clean_translation_set_cache( $id ) {
 317      global $_wp_suspend_cache_invalidation;
 318  
 319      if ( ! empty( $_wp_suspend_cache_invalidation ) ) {
 320          return;
 321      }
 322  
 323      wp_cache_delete( $id, 'translation_set_status_breakdown' );
 324      wp_cache_delete( $id, 'translation_set_last_modified' );
 325  }
 326  
 327  /**
 328   * Delete counts cache for all translation sets of a project
 329   *
 330   * @param int $project_id project ID
 331   */
 332  function gp_clean_translation_sets_cache( $project_id ) {
 333      $translation_sets = GP::$translation_set->by_project_id( $project_id );
 334  
 335      if ( ! $translation_sets ) {
 336          return;
 337      }
 338  
 339      foreach ( $translation_sets as $set ) {
 340          gp_clean_translation_set_cache( $set->id );
 341      }
 342  }
 343  
 344  
 345  /**
 346   * Checks if the passed value is empty.
 347   *
 348   * @param string $value The value you want to check.
 349   * @return bool
 350   */
 351  function gp_is_empty( $value ) {
 352      return empty( $value );
 353  }
 354  
 355  /**
 356   * Checks if the passed value is an empty string.
 357   *
 358   * @param string $value The value you want to check.
 359   * @return bool
 360   */
 361  function gp_is_empty_string( $value ) {
 362      return '' === $value;
 363  }
 364  
 365  /**
 366   * Checks if the passed value isn't an empty string.
 367   *
 368   * @param string $value The value you want to check.
 369   * @return bool
 370   */
 371  function gp_is_not_empty_string( $value ) {
 372      return '' !== $value;
 373  }
 374  
 375  /**
 376   * Checks if the passed value is a positive integer.
 377   *
 378   * @param int $value The value you want to check.
 379   * @return bool
 380   */
 381  function gp_is_positive_int( $value ) {
 382      return (int) $value > 0;
 383  }
 384  
 385  /**
 386   * Checks if the passed value is an integer.
 387   *
 388   * @param int|string $value The value you want to check.
 389   * @return bool
 390   */
 391  function gp_is_int( $value ) {
 392      return (bool) preg_match( '/^-?\d+$/', $value );
 393  }
 394  
 395  /**
 396   * Checks if the passed value is null.
 397   *
 398   * @param string $value The value you want to check.
 399   * @return bool
 400   */
 401  function gp_is_null( $value ) {
 402      return null === $value;
 403  }
 404  
 405  /**
 406   * Checks if the passed value is not null.
 407   *
 408   * @param string $value The value you want to check.
 409   * @return bool
 410   */
 411  function gp_is_not_null( $value ) {
 412      return null !== $value;
 413  }
 414  
 415  /**
 416   * Checks if the passed value is between the start and end value or is the same.
 417   *
 418   * @param string $value The value you want to check.
 419   * @param string $value The lower value you want to check against.
 420   * @param string $value The upper value you want to check against.
 421   * @return bool
 422   */
 423  function gp_is_between( $value, $start, $end ) {
 424      return $value >= $start && $value <= $end;
 425  }
 426  
 427  /**
 428   * Checks if the passed value is between the start and end value.
 429   *
 430   * @param string $value The value you want to check.
 431   * @return bool
 432   */
 433  function gp_is_between_exclusive( $value, $start, $end ) {
 434      return $value > $start && $value < $end;
 435  }
 436  
 437  /**
 438   * Checks if the passed value is one of the values in the list.
 439   *
 440   * @since 3.0.0
 441   *
 442   * @param string $value The value you want to check.
 443   * @param array  $list  The list of values you want to check against.
 444   * @return bool
 445   */
 446  function gp_is_one_of( $value, $list ) {
 447      return in_array( $value, $list, true );
 448  }
 449  
 450  /**
 451   * Checks if the passed value has only ASCII characters.
 452   *
 453   * @since 3.0.0
 454   *
 455   * @param string $value The value you want to check.
 456   * @return bool
 457   */
 458  function gp_is_ascii_string( $value ) {
 459      return preg_replace( "/[^\x20-\x7E\p{L}]/", '', $value ) === $value;
 460  }
 461  
 462  /**
 463   * Checks if the passed value starts and ends with a word character.
 464   *
 465   * @since 3.0.0
 466   *
 467   * @param string $value The value you want to check.
 468   * @return bool
 469   */
 470  function gp_is_starting_and_ending_with_a_word_character( $value ) {
 471      return (bool) preg_match( '/\b' . preg_quote( $value, '/' ) . '\b/i', $value );
 472  }
 473  
 474  /**
 475   * Acts the same as core PHP setcookie() but its arguments are run through the gp_set_cookie filter.
 476   *
 477   * If the filter returns false, setcookie() isn't called.
 478   *
 479   * @param string $name    The name of the cookie.
 480   * @param mixed  ...$args Additional arguments to be passed to setcookie().
 481   */
 482  function gp_set_cookie( $name, ...$args ) {
 483      array_unshift( $args, $name );
 484  
 485      /**
 486       * Filter whether GlotPress should set a cookie.
 487       *
 488       * If the filter returns false, a cookie will not be set.
 489       *
 490       * @since 1.0.0
 491       *
 492       * @param array $args {
 493       *     The cookie that is about to be set.
 494       *
 495       *     @type string $name    The name of the cookie.
 496       *     @type string $value   The value of the cookie.
 497       *     @type int    $expires The time the cookie expires.
 498       *     @type string $path    The path on the server in which the cookie will be available on.
 499       * }
 500       */
 501      $args = apply_filters( 'gp_set_cookie', $args );
 502      if ( false === $args ) {
 503          return;
 504      }
 505  
 506      setcookie( ...$args );
 507  }
 508  
 509  /**
 510   * Converts a string represented time/date to a utime int, adding a GMT offset if not found.
 511   *
 512   * @since 1.0.0
 513   *
 514   * @param string $string The string representation of the time to convert.
 515   * @return int
 516   */
 517  function gp_gmt_strtotime( $string ) {
 518      if ( is_numeric( $string ) ) {
 519          return $string;
 520      }
 521      if ( ! is_string( $string ) ) {
 522          return -1;
 523      }
 524  
 525      if ( stristr( $string, 'utc' ) || stristr( $string, 'gmt' ) || stristr( $string, '+0000' ) ) {
 526          return strtotime( $string );
 527      }
 528  
 529      if ( -1 == $time = strtotime( $string . ' +0000' ) ) {
 530          return strtotime( $string );
 531      }
 532  
 533      return $time;
 534  }
 535  
 536  /**
 537   * Determines the format to use based on the selected format type or by auto detection based on the file name.
 538   *
 539   * Used during import of translations and originals.
 540   *
 541   * @param string $selected_format The format that the user selected on the import page.
 542   * @param string $filename The filname that was uploaded by the user.
 543   * @return object|null A GP_Format child object or null if not found.
 544   */
 545  function gp_get_import_file_format( $selected_format, $filename ) {
 546      $format = gp_array_get( GP::$formats, $selected_format, null );
 547  
 548      if ( ! $format ) {
 549          $matched_ext_len = 0;
 550  
 551          foreach ( GP::$formats as $format_entry ) {
 552              $format_extensions = $format_entry->get_file_extensions();
 553  
 554              foreach ( $format_extensions as $extension ) {
 555                  $current_ext_len = strlen( $extension );
 556  
 557                  if ( gp_endswith( $filename, $extension ) && $current_ext_len > $matched_ext_len ) {
 558                      $format          = $format_entry;
 559                      $matched_ext_len = $current_ext_len;
 560                  }
 561              }
 562          }
 563      }
 564  
 565      return $format;
 566  }
 567  
 568  /**
 569   * Displays the GlotPress administrator option in the user profile screen for WordPress administrators.
 570   *
 571   * @since 2.0.0
 572   *
 573   * @param WP_User $user The WP_User object to display the profile for.
 574   */
 575  function gp_wp_profile_options( $user ) {
 576      if ( ! current_user_can( 'manage_options' ) ) {
 577          return;
 578      }
 579  
 580      ?>
 581      <h2 id="glotpress"><?php _e( 'GlotPress', 'glotpress' ); ?></h2>
 582  
 583      <table class="form-table">
 584          <tr id="gp-admin">
 585              <th scope="row"><?php _e( 'Administrator', 'glotpress' ); ?></th>
 586              <td>
 587                  <fieldset>
 588                      <legend class="screen-reader-text"><span><?php _e( 'GlotPress Administrator', 'glotpress' ); ?></span></legend>
 589                      <label for="gp_administrator">
 590                          <input name="gp_administrator" type="checkbox" id="gp_administrator" value="1"<?php checked( GP::$permission->user_can( $user, 'admin' ) ); ?> />
 591                          <?php _e( 'Grant this user administrative privileges in GlotPress.', 'glotpress' ); ?>
 592                      </label>
 593                  </fieldset>
 594              </td>
 595          </tr>
 596      </table>
 597      <?php
 598  }
 599  
 600  /**
 601   * Saves the settings for the GlotPress administrator option in the user profile screen for WordPress administrators.
 602   *
 603   * @since 2.0.0
 604   *
 605   * @param int $user_id The WordPress user id to save the setting for.
 606   */
 607  function gp_wp_profile_options_update( $user_id ) {
 608      if ( ! current_user_can( 'manage_options' ) ) {
 609          return;
 610      }
 611  
 612      $is_user_gp_admin = GP::$permission->user_can( $user_id, 'admin' );
 613  
 614      // phpcs:ignore WordPress.Security.NonceVerification.Missing
 615      if ( array_key_exists( 'gp_administrator', $_POST ) && ! $is_user_gp_admin ) {
 616          GP::$administrator_permission->create(
 617              array(
 618                  'user_id'     => $user_id,
 619                  'action'      => 'admin',
 620                  'object_type' => null,
 621              )
 622          );
 623      }
 624  
 625      // phpcs:ignore WordPress.Security.NonceVerification.Missing
 626      if ( ! array_key_exists( 'gp_administrator', $_POST ) && $is_user_gp_admin ) {
 627          $current_perm = GP::$administrator_permission->find_one(
 628              array(
 629                  'user_id' => $user_id,
 630                  'action'  => 'admin',
 631              )
 632          );
 633          $current_perm->delete();
 634      }
 635  }
 636  
 637  /**
 638   * Returns a multi-dimensional array with the sort by types, descriptions and SQL query for each.
 639   *
 640   * @since 2.1.0
 641   *
 642   * @return array An array of sort by field types.
 643   */
 644  function gp_get_sort_by_fields() {
 645      $sort_fields = array(
 646          'original_date_added'       => array(
 647              'title'       => __( 'Date added (original)', 'glotpress' ),
 648              'sql_sort_by' => 'o.date_added %s',
 649          ),
 650          'translation_date_added'    => array(
 651              'title'       => __( 'Date added (translation)', 'glotpress' ),
 652              'sql_sort_by' => 't.date_added %s',
 653          ),
 654          'translation_date_modified' => array(
 655              'title'       => __( 'Date modified (translation)', 'glotpress' ),
 656              'sql_sort_by' => 't.date_modified %s',
 657          ),
 658          'original'                  => array(
 659              'title'       => __( 'Original string', 'glotpress' ),
 660              'sql_sort_by' => 'o.singular %s',
 661          ),
 662          'translation'               => array(
 663              'title'       => __( 'Translation', 'glotpress' ),
 664              'sql_sort_by' => 't.translation_0 %s',
 665          ),
 666          'priority'                  => array(
 667              'title'       => __( 'Priority', 'glotpress' ),
 668              'sql_sort_by' => 'o.priority %s, o.date_added DESC',
 669          ),
 670          'references'                => array(
 671              'title'       => __( 'Filename in source', 'glotpress' ),
 672              'sql_sort_by' => 'o.references',
 673          ),
 674          'random'                    => array(
 675              'title'       => __( 'Random', 'glotpress' ),
 676              'sql_sort_by' => 'o.priority DESC, RAND()',
 677          ),
 678      );
 679  
 680      /**
 681       * Filter the sort by list to allow plugins to add or remove sort by types.
 682       *
 683       * Plugins can add, remove or resort the sort by types array which is used to create
 684       * the sort by drop down in the translations page.
 685       *
 686       * @since 2.1.0
 687       *
 688       * @param array $sort_fields {
 689       *     A list of sort by types.
 690       *
 691       *     @type array $sort_type An array with two keys, 'title' is a translated description of the key and 'sql_sort_by' which is a partial SQL SORT BY clause to use.
 692       * }
 693       */
 694      return apply_filters( 'gp_sort_by_fields', $sort_fields );
 695  }
 696  
 697  /**
 698   * Sets the maximum memory limit available for translations imports.
 699   *
 700   * @since 3.0.0
 701   *
 702   * @return string The maximum memory limit.
 703   */
 704  function gp_set_translations_import_max_memory_limit() {
 705      return '256M';
 706  }


Generated: Sun Apr 28 01:01:17 2024 Cross-referenced by PHPXref 0.7.1