[ 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 or arrays.
  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 string[]
  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              $this->output = array();
 106              return $this->output;
 107          }
 108  
 109          $count    = count( $args );
 110          $filtered = array();
 111  
 112          foreach ( $this->output as $key => $obj ) {
 113              $matched = 0;
 114  
 115              foreach ( $args as $m_key => $m_value ) {
 116                  if ( is_array( $obj ) ) {
 117                      // Treat object as an array.
 118                      if ( array_key_exists( $m_key, $obj ) && ( $m_value == $obj[ $m_key ] ) ) {
 119                          $matched++;
 120                      }
 121                  } elseif ( is_object( $obj ) ) {
 122                      // Treat object as an object.
 123                      if ( isset( $obj->{$m_key} ) && ( $m_value == $obj->{$m_key} ) ) {
 124                          $matched++;
 125                      }
 126                  }
 127              }
 128  
 129              if ( ( 'AND' === $operator && $matched === $count )
 130                  || ( 'OR' === $operator && $matched > 0 )
 131                  || ( 'NOT' === $operator && 0 === $matched )
 132              ) {
 133                  $filtered[ $key ] = $obj;
 134              }
 135          }
 136  
 137          $this->output = $filtered;
 138  
 139          return $this->output;
 140      }
 141  
 142      /**
 143       * Plucks a certain field out of each element in the input array.
 144       *
 145       * This has the same functionality and prototype of
 146       * array_column() (PHP 5.5) but also supports objects.
 147       *
 148       * @since 4.7.0
 149       *
 150       * @param int|string $field     Field to fetch from the object or array.
 151       * @param int|string $index_key Optional. Field from the element to use as keys for the new array.
 152       *                              Default null.
 153       * @return array Array of found values. If `$index_key` is set, an array of found values with keys
 154       *               corresponding to `$index_key`. If `$index_key` is null, array keys from the original
 155       *               `$list` will be preserved in the results.
 156       */
 157  	public function pluck( $field, $index_key = null ) {
 158          $newlist = array();
 159  
 160          if ( ! $index_key ) {
 161              /*
 162               * This is simple. Could at some point wrap array_column()
 163               * if we knew we had an array of arrays.
 164               */
 165              foreach ( $this->output as $key => $value ) {
 166                  if ( is_object( $value ) ) {
 167                      $newlist[ $key ] = $value->$field;
 168                  } else {
 169                      $newlist[ $key ] = $value[ $field ];
 170                  }
 171              }
 172  
 173              $this->output = $newlist;
 174  
 175              return $this->output;
 176          }
 177  
 178          /*
 179           * When index_key is not set for a particular item, push the value
 180           * to the end of the stack. This is how array_column() behaves.
 181           */
 182          foreach ( $this->output as $value ) {
 183              if ( is_object( $value ) ) {
 184                  if ( isset( $value->$index_key ) ) {
 185                      $newlist[ $value->$index_key ] = $value->$field;
 186                  } else {
 187                      $newlist[] = $value->$field;
 188                  }
 189              } else {
 190                  if ( isset( $value[ $index_key ] ) ) {
 191                      $newlist[ $value[ $index_key ] ] = $value[ $field ];
 192                  } else {
 193                      $newlist[] = $value[ $field ];
 194                  }
 195              }
 196          }
 197  
 198          $this->output = $newlist;
 199  
 200          return $this->output;
 201      }
 202  
 203      /**
 204       * Sorts the input array based on one or more orderby arguments.
 205       *
 206       * @since 4.7.0
 207       *
 208       * @param string|array $orderby       Optional. Either the field name to order by or an array
 209       *                                    of multiple orderby fields as $orderby => $order.
 210       * @param string       $order         Optional. Either 'ASC' or 'DESC'. Only used if $orderby
 211       *                                    is a string.
 212       * @param bool         $preserve_keys Optional. Whether to preserve keys. Default false.
 213       * @return array The sorted array.
 214       */
 215  	public function sort( $orderby = array(), $order = 'ASC', $preserve_keys = false ) {
 216          if ( empty( $orderby ) ) {
 217              return $this->output;
 218          }
 219  
 220          if ( is_string( $orderby ) ) {
 221              $orderby = array( $orderby => $order );
 222          }
 223  
 224          foreach ( $orderby as $field => $direction ) {
 225              $orderby[ $field ] = 'DESC' === strtoupper( $direction ) ? 'DESC' : 'ASC';
 226          }
 227  
 228          $this->orderby = $orderby;
 229  
 230          if ( $preserve_keys ) {
 231              uasort( $this->output, array( $this, 'sort_callback' ) );
 232          } else {
 233              usort( $this->output, array( $this, 'sort_callback' ) );
 234          }
 235  
 236          $this->orderby = array();
 237  
 238          return $this->output;
 239      }
 240  
 241      /**
 242       * Callback to sort an array by specific fields.
 243       *
 244       * @since 4.7.0
 245       *
 246       * @see WP_List_Util::sort()
 247       *
 248       * @param object|array $a One object to compare.
 249       * @param object|array $b The other object to compare.
 250       * @return int 0 if both objects equal. -1 if second object should come first, 1 otherwise.
 251       */
 252  	private function sort_callback( $a, $b ) {
 253          if ( empty( $this->orderby ) ) {
 254              return 0;
 255          }
 256  
 257          $a = (array) $a;
 258          $b = (array) $b;
 259  
 260          foreach ( $this->orderby as $field => $direction ) {
 261              if ( ! isset( $a[ $field ] ) || ! isset( $b[ $field ] ) ) {
 262                  continue;
 263              }
 264  
 265              if ( $a[ $field ] == $b[ $field ] ) {
 266                  continue;
 267              }
 268  
 269              $results = 'DESC' === $direction ? array( 1, -1 ) : array( -1, 1 );
 270  
 271              if ( is_numeric( $a[ $field ] ) && is_numeric( $b[ $field ] ) ) {
 272                  return ( $a[ $field ] < $b[ $field ] ) ? $results[0] : $results[1];
 273              }
 274  
 275              return 0 > strcmp( $a[ $field ], $b[ $field ] ) ? $results[0] : $results[1];
 276          }
 277  
 278          return 0;
 279      }
 280  }


Generated: Mon Aug 8 01:00:03 2022 Cross-referenced by PHPXref 0.7.1