[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> class-wp-list-util.php (source)

   1  <?php
   2  /**
   3   * WordPress List utility class
   4   *
   5   * @package WordPress
   6   * @since 4.7.0
   7   */
   8  
   9  /**
  10   * List utility.
  11   *
  12   * Utility class to handle operations on an array of objects or arrays.
  13   *
  14   * @since 4.7.0
  15   */
  16  #[AllowDynamicProperties]
  17  class WP_List_Util {
  18      /**
  19       * The input array.
  20       *
  21       * @since 4.7.0
  22       * @var array
  23       */
  24      private $input = array();
  25  
  26      /**
  27       * The output array.
  28       *
  29       * @since 4.7.0
  30       * @var array
  31       */
  32      private $output = array();
  33  
  34      /**
  35       * Temporary arguments for sorting.
  36       *
  37       * @since 4.7.0
  38       * @var string[]
  39       */
  40      private $orderby = array();
  41  
  42      /**
  43       * Constructor.
  44       *
  45       * Sets the input array.
  46       *
  47       * @since 4.7.0
  48       *
  49       * @param array $input Array to perform operations on.
  50       */
  51  	public function __construct( $input ) {
  52          $this->output = $input;
  53          $this->input  = $input;
  54      }
  55  
  56      /**
  57       * Returns the original input array.
  58       *
  59       * @since 4.7.0
  60       *
  61       * @return array The input array.
  62       */
  63  	public function get_input() {
  64          return $this->input;
  65      }
  66  
  67      /**
  68       * Returns the output array.
  69       *
  70       * @since 4.7.0
  71       *
  72       * @return array The output array.
  73       */
  74  	public function get_output() {
  75          return $this->output;
  76      }
  77  
  78      /**
  79       * Filters the list, based on a set of key => value arguments.
  80       *
  81       * Retrieves the objects from the list that match the given arguments.
  82       * Key represents property name, and value represents property value.
  83       *
  84       * If an object has more properties than those specified in arguments,
  85       * that will not disqualify it. When using the 'AND' operator,
  86       * any missing properties will disqualify it.
  87       *
  88       * @since 4.7.0
  89       *
  90       * @param array  $args     Optional. An array of key => value arguments to match
  91       *                         against each object. Default empty array.
  92       * @param string $operator Optional. The logical operation to perform. 'AND' means
  93       *                         all elements from the array must match. 'OR' means only
  94       *                         one element needs to match. 'NOT' means no elements may
  95       *                         match. Default 'AND'.
  96       * @return array Array of found values.
  97       */
  98  	public function filter( $args = array(), $operator = 'AND' ) {
  99          if ( empty( $args ) ) {
 100              return $this->output;
 101          }
 102  
 103          $operator = strtoupper( $operator );
 104  
 105          if ( ! in_array( $operator, array( 'AND', 'OR', 'NOT' ), true ) ) {
 106              $this->output = array();
 107              return $this->output;
 108          }
 109  
 110          $count    = count( $args );
 111          $filtered = array();
 112  
 113          foreach ( $this->output as $key => $obj ) {
 114              $matched = 0;
 115  
 116              foreach ( $args as $m_key => $m_value ) {
 117                  if ( is_array( $obj ) ) {
 118                      // Treat object as an array.
 119                      if ( array_key_exists( $m_key, $obj ) && ( $m_value == $obj[ $m_key ] ) ) {
 120                          ++$matched;
 121                      }
 122                  } elseif ( is_object( $obj ) ) {
 123                      // Treat object as an object.
 124                      if ( isset( $obj->{$m_key} ) && ( $m_value == $obj->{$m_key} ) ) {
 125                          ++$matched;
 126                      }
 127                  }
 128              }
 129  
 130              if ( ( 'AND' === $operator && $matched === $count )
 131                  || ( 'OR' === $operator && $matched > 0 )
 132                  || ( 'NOT' === $operator && 0 === $matched )
 133              ) {
 134                  $filtered[ $key ] = $obj;
 135              }
 136          }
 137  
 138          $this->output = $filtered;
 139  
 140          return $this->output;
 141      }
 142  
 143      /**
 144       * Plucks a certain field out of each element in the input array.
 145       *
 146       * This has the same functionality and prototype of
 147       * array_column() (PHP 5.5) but also supports objects.
 148       *
 149       * @since 4.7.0
 150       *
 151       * @param int|string $field     Field to fetch from the object or array.
 152       * @param int|string $index_key Optional. Field from the element to use as keys for the new array.
 153       *                              Default null.
 154       * @return array Array of found values. If `$index_key` is set, an array of found values with keys
 155       *               corresponding to `$index_key`. If `$index_key` is null, array keys from the original
 156       *               `$list` will be preserved in the results.
 157       */
 158  	public function pluck( $field, $index_key = null ) {
 159          $newlist = array();
 160  
 161          if ( ! $index_key ) {
 162              /*
 163               * This is simple. Could at some point wrap array_column()
 164               * if we knew we had an array of arrays.
 165               */
 166              foreach ( $this->output as $key => $value ) {
 167                  if ( is_object( $value ) ) {
 168                      $newlist[ $key ] = $value->$field;
 169                  } elseif ( is_array( $value ) ) {
 170                      $newlist[ $key ] = $value[ $field ];
 171                  } else {
 172                      _doing_it_wrong(
 173                          __METHOD__,
 174                          __( 'Values for the input array must be either objects or arrays.' ),
 175                          '6.2.0'
 176                      );
 177                  }
 178              }
 179  
 180              $this->output = $newlist;
 181  
 182              return $this->output;
 183          }
 184  
 185          /*
 186           * When index_key is not set for a particular item, push the value
 187           * to the end of the stack. This is how array_column() behaves.
 188           */
 189          foreach ( $this->output as $value ) {
 190              if ( is_object( $value ) ) {
 191                  if ( isset( $value->$index_key ) ) {
 192                      $newlist[ $value->$index_key ] = $value->$field;
 193                  } else {
 194                      $newlist[] = $value->$field;
 195                  }
 196              } elseif ( is_array( $value ) ) {
 197                  if ( isset( $value[ $index_key ] ) ) {
 198                      $newlist[ $value[ $index_key ] ] = $value[ $field ];
 199                  } else {
 200                      $newlist[] = $value[ $field ];
 201                  }
 202              } else {
 203                  _doing_it_wrong(
 204                      __METHOD__,
 205                      __( 'Values for the input array must be either objects or arrays.' ),
 206                      '6.2.0'
 207                  );
 208              }
 209          }
 210  
 211          $this->output = $newlist;
 212  
 213          return $this->output;
 214      }
 215  
 216      /**
 217       * Sorts the input array based on one or more orderby arguments.
 218       *
 219       * @since 4.7.0
 220       *
 221       * @param string|array $orderby       Optional. Either the field name to order by or an array
 222       *                                    of multiple orderby fields as `$orderby => $order`.
 223       *                                    Default empty array.
 224       * @param string       $order         Optional. Either 'ASC' or 'DESC'. Only used if `$orderby`
 225       *                                    is a string. Default 'ASC'.
 226       * @param bool         $preserve_keys Optional. Whether to preserve keys. Default false.
 227       * @return array The sorted array.
 228       */
 229  	public function sort( $orderby = array(), $order = 'ASC', $preserve_keys = false ) {
 230          if ( empty( $orderby ) ) {
 231              return $this->output;
 232          }
 233  
 234          if ( is_string( $orderby ) ) {
 235              $orderby = array( $orderby => $order );
 236          }
 237  
 238          foreach ( $orderby as $field => $direction ) {
 239              $orderby[ $field ] = 'DESC' === strtoupper( $direction ) ? 'DESC' : 'ASC';
 240          }
 241  
 242          $this->orderby = $orderby;
 243  
 244          if ( $preserve_keys ) {
 245              uasort( $this->output, array( $this, 'sort_callback' ) );
 246          } else {
 247              usort( $this->output, array( $this, 'sort_callback' ) );
 248          }
 249  
 250          $this->orderby = array();
 251  
 252          return $this->output;
 253      }
 254  
 255      /**
 256       * Callback to sort an array by specific fields.
 257       *
 258       * @since 4.7.0
 259       *
 260       * @see WP_List_Util::sort()
 261       *
 262       * @param object|array $a One object to compare.
 263       * @param object|array $b The other object to compare.
 264       * @return int 0 if both objects equal. -1 if second object should come first, 1 otherwise.
 265       */
 266  	private function sort_callback( $a, $b ) {
 267          if ( empty( $this->orderby ) ) {
 268              return 0;
 269          }
 270  
 271          $a = (array) $a;
 272          $b = (array) $b;
 273  
 274          foreach ( $this->orderby as $field => $direction ) {
 275              if ( ! isset( $a[ $field ] ) || ! isset( $b[ $field ] ) ) {
 276                  continue;
 277              }
 278  
 279              if ( $a[ $field ] == $b[ $field ] ) {
 280                  continue;
 281              }
 282  
 283              $results = 'DESC' === $direction ? array( 1, -1 ) : array( -1, 1 );
 284  
 285              if ( is_numeric( $a[ $field ] ) && is_numeric( $b[ $field ] ) ) {
 286                  return ( $a[ $field ] < $b[ $field ] ) ? $results[0] : $results[1];
 287              }
 288  
 289              return 0 > strcmp( $a[ $field ], $b[ $field ] ) ? $results[0] : $results[1];
 290          }
 291  
 292          return 0;
 293      }
 294  }


Generated : Sun Apr 28 08:20:02 2024 Cross-referenced by PHPXref