Make WordPress Core

Changeset 36485


Ignore:
Timestamp:
02/06/2016 04:41:26 AM (11 years ago)
Author:
boonebgorges
Message:

Allow get_terms() results to ordered by metadata.

The $orderby parameter of get_terms() now accepts the following values,
related to term meta:

  • 'meta_value'
  • 'meta_value_num'
  • the value of the $meta_key parameter
  • any key from the $meta_query array

This brings order-by-meta support for terms in line with post, comment, and
user queries.

As a byproduct of these improvements, $meta_key and $meta_value parameters
have been introduced to get_terms(). They interact with $meta_query in the
same way as in WP_Query and other query classes.

Props jadpm, eherman24.
Fixes #34996.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/taxonomy.php

    r36400 r36485  
    10611061 *              Introduced the 'meta_query' and 'update_term_meta_cache' parameters. Converted to return
    10621062 *              a list of WP_Term objects.
     1063 * @since 4.5.0 Introduced 'meta_key' and 'meta_value' parameters. Introduced the ability to order results by metadata.
    10631064 *
    10641065 * @global wpdb  $wpdb WordPress database abstraction object.
     
    10721073 *                                                'term_group', 'term_id', 'id', 'description'), 'count' for term
    10731074 *                                                taxonomy count, 'include' to match the 'order' of the $include param,
    1074  *                                                or 'none' to skip ORDER BY. Defaults to 'name'.
     1075 *                                                'meta_value', 'meta_value_num', the value of `$meta_key`, the array
     1076 *                                                keys of `$meta_query`, or 'none' to omit the ORDER BY clause.
     1077 *                                                Defaults to 'name'.
    10751078 *     @type string       $order                  Whether to order terms in ascending or descending order.
    10761079 *                                                Accepts 'ASC' (ascending) or 'DESC' (descending).
     
    11201123 *     @type array        $meta_query             Meta query clauses to limit retrieved terms by.
    11211124 *                                                See `WP_Meta_Query`. Default empty.
     1125 *     @type string       $meta_key               Limit terms to those matching a specific metadata key. Can be used in
     1126 *                                                conjunction with `$meta_value`.
     1127 *     @type string       $meta_value             Limit terms to those matching a specific metadata value. Usually used
     1128 *                                                in conjunction with `$meta_key`.
    11221129 * }
    11231130 * @return array|int|WP_Error List of WP_Term instances and their children. Will return WP_Error, if any of $taxonomies
     
    14151422        $join = '';
    14161423        $distinct = '';
    1417         if ( ! empty( $args['meta_query'] ) ) {
    1418                 $mquery = new WP_Meta_Query( $args['meta_query'] );
    1419                 $mq_sql = $mquery->get_sql( 'term', 't', 'term_id' );
    1420 
     1424
     1425        $mquery = new WP_Meta_Query();
     1426        $mquery->parse_query_vars( $args );
     1427        $mq_sql = $mquery->get_sql( 'term', 't', 'term_id' );
     1428        $meta_clauses = $mquery->get_clauses();
     1429
     1430        if ( ! empty( $meta_clauses ) ) {
    14211431                $join  .= $mq_sql['join'];
    14221432                $where .= $mq_sql['where'];
    14231433                $distinct .= "DISTINCT";
     1434
     1435                // 'orderby' support.
     1436                $allowed_keys = array();
     1437                $primary_meta_key   = null;
     1438                $primary_meta_query = reset( $meta_clauses );
     1439                if ( ! empty( $primary_meta_query['key'] ) ) {
     1440                        $primary_meta_key = $primary_meta_query['key'];
     1441                        $allowed_keys[] = $primary_meta_key;
     1442                }
     1443                $allowed_keys[] = 'meta_value';
     1444                $allowed_keys[] = 'meta_value_num';
     1445                $allowed_keys   = array_merge( $allowed_keys, array_keys( $meta_clauses ) );
     1446
     1447                if ( ! empty( $args['orderby'] ) && in_array( $args['orderby'], $allowed_keys ) ) {
     1448                        switch( $args['orderby'] ) {
     1449                                case $primary_meta_key:
     1450                                case 'meta_value':
     1451                                        if ( ! empty( $primary_meta_query['type'] ) ) {
     1452                                                $orderby = "ORDER BY CAST({$primary_meta_query['alias']}.meta_value AS {$primary_meta_query['cast']})";
     1453                                        } else {
     1454                                                $orderby = "ORDER BY {$primary_meta_query['alias']}.meta_value";
     1455                                        }
     1456                                        break;
     1457
     1458                                case 'meta_value_num':
     1459                                        $orderby = "ORDER BY {$primary_meta_query['alias']}.meta_value+0";
     1460                                        break;
     1461
     1462                                default:
     1463                                        if ( array_key_exists( $args['orderby'], $meta_clauses ) ) {
     1464                                                // $orderby corresponds to a meta_query clause.
     1465                                                $meta_clause = $meta_clauses[ $args['orderby'] ];
     1466                                                $orderby = "ORDER BY CAST({$meta_clause['alias']}.meta_value AS {$meta_clause['cast']})";
     1467                                        }
     1468                                        break;
     1469                        }
     1470                }
    14241471        }
    14251472
  • trunk/tests/phpunit/tests/term/getTerms.php

    r36348 r36485  
    12341234        }
    12351235
     1236        /**
     1237         * @ticket 34996
     1238         */
     1239        public function test_orderby_meta_value() {
     1240                register_taxonomy( 'wptests_tax', 'post' );
     1241                $terms = self::factory()->term->create_many( 3, array( 'taxonomy' => 'wptests_tax' ) );
     1242                add_term_meta( $terms[0], 'foo', 'zzz' );
     1243                add_term_meta( $terms[0], 'fee', 'ber' );
     1244                add_term_meta( $terms[1], 'foo', 'aaa' );
     1245                add_term_meta( $terms[1], 'fee', 'ber' );
     1246                add_term_meta( $terms[2], 'foo', 'jjj' );
     1247                add_term_meta( $terms[2], 'fee', 'ber' );
     1248
     1249                // Matches the first meta query clause.
     1250                $found = get_terms( 'wptests_tax', array(
     1251                        'hide_empty' => false,
     1252                        'meta_query' => array(
     1253                                'relation' => 'AND',
     1254                                array(
     1255                                        'key' => 'foo',
     1256                                        'compare' => 'EXISTS',
     1257                                ),
     1258                                array(
     1259                                        'key' => 'fee',
     1260                                        'compare' => 'EXISTS',
     1261                                ),
     1262                        ),
     1263                        'orderby' => 'meta_value',
     1264                        'order' => 'ASC',
     1265                        'fields' => 'ids',
     1266                ) );
     1267
     1268                $this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
     1269        }
     1270
     1271        /**
     1272         * @ticket 34996
     1273         */
     1274        public function test_orderby_meta_value_num() {
     1275                register_taxonomy( 'wptests_tax', 'post' );
     1276                $terms = self::factory()->term->create_many( 3, array( 'taxonomy' => 'wptests_tax' ) );
     1277                add_term_meta( $terms[0], 'foo', '999' );
     1278                add_term_meta( $terms[0], 'fee', 'ber' );
     1279                add_term_meta( $terms[1], 'foo', '111' );
     1280                add_term_meta( $terms[1], 'fee', 'ber' );
     1281                add_term_meta( $terms[2], 'foo', '555' );
     1282                add_term_meta( $terms[2], 'fee', 'ber' );
     1283
     1284                // Matches the first meta query clause.
     1285                $found = get_terms( 'wptests_tax', array(
     1286                        'hide_empty' => false,
     1287                        'meta_query' => array(
     1288                                'relation' => 'AND',
     1289                                array(
     1290                                        'key' => 'foo',
     1291                                        'compare' => 'EXISTS',
     1292                                ),
     1293                                array(
     1294                                        'key' => 'fee',
     1295                                        'compare' => 'EXISTS',
     1296                                ),
     1297                        ),
     1298                        'orderby' => 'meta_value_num',
     1299                        'order' => 'ASC',
     1300                        'fields' => 'ids',
     1301                ) );
     1302
     1303                $this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
     1304        }
     1305
     1306        /**
     1307         * @ticket 34996
     1308         */
     1309        public function test_orderby_meta_value_with_meta_key() {
     1310                register_taxonomy( 'wptests_tax', 'post' );
     1311                $terms = self::factory()->term->create_many( 3, array( 'taxonomy' => 'wptests_tax' ) );
     1312                add_term_meta( $terms[0], 'foo', 'bar' );
     1313                add_term_meta( $terms[0], 'fee', 'zzz' );
     1314                add_term_meta( $terms[0], 'faa', 'jjj' );
     1315                add_term_meta( $terms[1], 'foo', 'bar' );
     1316                add_term_meta( $terms[1], 'fee', 'aaa' );
     1317                add_term_meta( $terms[1], 'faa', 'aaa' );
     1318                add_term_meta( $terms[2], 'foo', 'bar' );
     1319                add_term_meta( $terms[2], 'fee', 'jjj' );
     1320                add_term_meta( $terms[2], 'faa', 'zzz' );
     1321
     1322                $found = get_terms( 'wptests_tax', array(
     1323                        'hide_empty' => false,
     1324                        'meta_key' => 'fee',
     1325                        'orderby' => 'meta_value',
     1326                        'order' => 'ASC',
     1327                        'fields' => 'ids',
     1328                ) );
     1329
     1330                $this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
     1331
     1332                $found = get_terms( 'wptests_tax', array(
     1333                        'hide_empty' => false,
     1334                        'meta_query' => array(
     1335                                array(
     1336                                        'key' => 'foo',
     1337                                        'compare' => 'EXISTS',
     1338                                ),
     1339                        ),
     1340                        'meta_key' => 'fee',
     1341                        'orderby' => 'meta_value',
     1342                        'order' => 'ASC',
     1343                        'fields' => 'ids',
     1344                ) );
     1345
     1346                $this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
     1347
     1348                // Matches the first meta query clause.
     1349                $found = get_terms( 'wptests_tax', array(
     1350                        'hide_empty' => false,
     1351                        'meta_query' => array(
     1352                                'relation' => 'AND',
     1353                                array(
     1354                                        'key' => 'foo',
     1355                                        'compare' => 'EXISTS',
     1356                                ),
     1357                                array(
     1358                                        'key' => 'fee',
     1359                                        'compare' => 'EXISTS',
     1360                                ),
     1361                        ),
     1362                        'meta_key' => 'fee',
     1363                        'orderby' => 'meta_value',
     1364                        'order' => 'ASC',
     1365                        'fields' => 'ids',
     1366                ) );
     1367
     1368                $this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
     1369
     1370                // Matches the meta query clause corresponding to the 'meta_key' param.
     1371                $found = get_terms( 'wptests_tax', array(
     1372                        'hide_empty' => false,
     1373                        'meta_query' => array(
     1374                                'relation' => 'AND',
     1375                                array(
     1376                                        'key' => 'foo',
     1377                                        'compare' => 'EXISTS',
     1378                                ),
     1379                                array(
     1380                                        'key' => 'fee',
     1381                                        'compare' => 'EXISTS',
     1382                                ),
     1383                        ),
     1384                        'meta_key' => 'faa',
     1385                        'orderby' => 'meta_value',
     1386                        'order' => 'ASC',
     1387                        'fields' => 'ids',
     1388                ) );
     1389
     1390                $this->assertEqualSets( array( $terms[1], $terms[0], $terms[2] ), $found );
     1391        }
     1392
     1393        /**
     1394         * @ticket 34996
     1395         */
     1396        public function test_orderby_meta_value_num_with_meta_key() {
     1397                register_taxonomy( 'wptests_tax', 'post' );
     1398                $terms = self::factory()->term->create_many( 3, array( 'taxonomy' => 'wptests_tax' ) );
     1399                add_term_meta( $terms[0], 'foo', 'bar' );
     1400                add_term_meta( $terms[0], 'fee', '999' );
     1401                add_term_meta( $terms[0], 'faa', '555' );
     1402                add_term_meta( $terms[1], 'foo', 'bar' );
     1403                add_term_meta( $terms[1], 'fee', '111' );
     1404                add_term_meta( $terms[1], 'faa', '111' );
     1405                add_term_meta( $terms[2], 'foo', 'bar' );
     1406                add_term_meta( $terms[2], 'fee', '555' );
     1407                add_term_meta( $terms[2], 'faa', '999' );
     1408
     1409                $found = get_terms( 'wptests_tax', array(
     1410                        'hide_empty' => false,
     1411                        'meta_key' => 'fee',
     1412                        'orderby' => 'meta_value',
     1413                        'order' => 'ASC',
     1414                        'fields' => 'ids',
     1415                ) );
     1416
     1417                $this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
     1418
     1419                $found = get_terms( 'wptests_tax', array(
     1420                        'hide_empty' => false,
     1421                        'meta_query' => array(
     1422                                array(
     1423                                        'key' => 'foo',
     1424                                        'compare' => 'EXISTS',
     1425                                ),
     1426                        ),
     1427                        'meta_key' => 'fee',
     1428                        'orderby' => 'meta_value',
     1429                        'order' => 'ASC',
     1430                        'fields' => 'ids',
     1431                ) );
     1432
     1433                $this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
     1434
     1435                $found = get_terms( 'wptests_tax', array(
     1436                        'hide_empty' => false,
     1437                        'meta_query' => array(
     1438                                'relation' => 'AND',
     1439                                array(
     1440                                        'key' => 'foo',
     1441                                        'compare' => 'EXISTS',
     1442                                ),
     1443                                array(
     1444                                        'key' => 'fee',
     1445                                        'compare' => 'EXISTS',
     1446                                ),
     1447                        ),
     1448                        'meta_key' => 'fee',
     1449                        'orderby' => 'meta_value',
     1450                        'order' => 'ASC',
     1451                        'fields' => 'ids',
     1452                ) );
     1453
     1454                $this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
     1455
     1456                $found = get_terms( 'wptests_tax', array(
     1457                        'hide_empty' => false,
     1458                        'meta_query' => array(
     1459                                'relation' => 'AND',
     1460                                array(
     1461                                        'key' => 'foo',
     1462                                        'compare' => 'EXISTS',
     1463                                ),
     1464                                array(
     1465                                        'key' => 'fee',
     1466                                        'compare' => 'EXISTS',
     1467                                ),
     1468                        ),
     1469                        'meta_key' => 'faa',
     1470                        'orderby' => 'meta_value',
     1471                        'order' => 'ASC',
     1472                        'fields' => 'ids',
     1473                ) );
     1474
     1475                $this->assertEqualSets( array( $terms[1], $terms[0], $terms[2] ), $found );
     1476        }
     1477
     1478        /**
     1479         * @ticket 34996
     1480         */
     1481        public function test_orderby_clause_key() {
     1482                register_taxonomy( 'wptests_tax', 'post' );
     1483                $terms = self::factory()->term->create_many( 3, array( 'taxonomy' => 'wptests_tax' ) );
     1484                add_term_meta( $terms[0], 'foo', 'zzz' );
     1485                add_term_meta( $terms[0], 'fee', 'jjj' );
     1486                add_term_meta( $terms[1], 'foo', 'aaa' );
     1487                add_term_meta( $terms[1], 'fee', 'aaa' );
     1488                add_term_meta( $terms[2], 'foo', 'jjj' );
     1489                add_term_meta( $terms[2], 'fee', 'zzz' );
     1490
     1491                $found = get_terms( 'wptests_tax', array(
     1492                        'hide_empty' => false,
     1493                        'meta_query' => array(
     1494                                'relation' => 'AND',
     1495                                'foo_key' => array(
     1496                                        'key' => 'foo',
     1497                                        'compare' => 'EXISTS',
     1498                                ),
     1499                                'fee_key' => array(
     1500                                        'key' => 'fee',
     1501                                        'compare' => 'EXISTS',
     1502                                ),
     1503                        ),
     1504                        'orderby' => 'foo_key',
     1505                        'order' => 'ASC',
     1506                        'fields' => 'ids',
     1507                ) );
     1508
     1509                $this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
     1510
     1511                $found = get_terms( 'wptests_tax', array(
     1512                        'hide_empty' => false,
     1513                        'meta_query' => array(
     1514                                'relation' => 'AND',
     1515                                'foo_key' => array(
     1516                                        'key' => 'foo',
     1517                                        'compare' => 'EXISTS',
     1518                                ),
     1519                                'fee_key' => array(
     1520                                        'key' => 'fee',
     1521                                        'compare' => 'EXISTS',
     1522                                ),
     1523                        ),
     1524                        'orderby' => 'fee_key',
     1525                        'order' => 'ASC',
     1526                        'fields' => 'ids',
     1527                ) );
     1528
     1529                $this->assertEqualSets( array( $terms[1], $terms[0], $terms[2] ), $found );
     1530
     1531                $expected = get_terms( 'wptests_tax', array(
     1532                        'hide_empty' => false,
     1533                        'meta_query' => array(
     1534                                'relation' => 'AND',
     1535                                'foo_key' => array(
     1536                                        'key' => 'foo',
     1537                                        'compare' => 'EXISTS',
     1538                                ),
     1539                                'fee_key' => array(
     1540                                        'key' => 'fee',
     1541                                        'compare' => 'EXISTS',
     1542                                ),
     1543                        ),
     1544                        'fields' => 'ids',
     1545                ) );
     1546
     1547                $found = get_terms( 'wptests_tax', array(
     1548                        'hide_empty' => false,
     1549                        'meta_query' => array(
     1550                                'relation' => 'AND',
     1551                                'foo_key' => array(
     1552                                        'key' => 'foo',
     1553                                        'compare' => 'EXISTS',
     1554                                ),
     1555                                'fee_key' => array(
     1556                                        'key' => 'fee',
     1557                                        'compare' => 'EXISTS',
     1558                                ),
     1559                        ),
     1560                        'orderby' => 'faa_key',
     1561                        'fields' => 'ids',
     1562                ) );
     1563
     1564                $this->assertEqualSets( $expected, $found );
     1565        }
     1566
    12361567        public function test_hierarchical_false_with_parent() {
    12371568                $initial_terms = $this->create_hierarchical_terms();
Note: See TracChangeset for help on using the changeset viewer.