[ Index ]

PHP Cross Reference of WordPress

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


Generated: Tue Sep 28 01:00:02 2021 Cross-referenced by PHPXref 0.7.1