WordPress.org

Make WordPress Core

Ticket #34996: 34996-2.patch

File 34996-2.patch, 10.7 KB (added by jadpm, 5 years ago)

Add sorting by termmeta to get_terms() - with unit tests

  • src/wp-includes/taxonomy.php

     
    14141414        // Meta query support.
    14151415        $join = '';
    14161416        $distinct = '';
    1417         if ( ! empty( $args['meta_query'] ) ) {
    1418                 $mquery = new WP_Meta_Query( $args['meta_query'] );
     1417       
     1418        $mquery = new WP_Meta_Query();
     1419        $mquery->parse_query_vars( $args );
     1420        $meta_clauses = $mquery->get_clauses();
     1421       
     1422        if ( ! empty( $meta_clauses ) ) {
     1423               
    14191424                $mq_sql = $mquery->get_sql( 'term', 't', 'term_id' );
    14201425
    14211426                $join  .= $mq_sql['join'];
    14221427                $where .= $mq_sql['where'];
    14231428                $distinct .= "DISTINCT";
     1429               
     1430                // orderby support
     1431               
     1432                $allowed_keys = array();
     1433                $primary_meta_query = reset( $meta_clauses );
     1434                if ( ! empty( $primary_meta_query['key'] ) ) {
     1435                        $primary_meta_key = $primary_meta_query['key'];
     1436                        $allowed_keys[] = $primary_meta_key;
     1437                }
     1438                $allowed_keys[] = 'meta_value';
     1439                $allowed_keys[] = 'meta_value_num';
     1440                $allowed_keys = array_merge( $allowed_keys, array_keys( $meta_clauses ) );
     1441                if (
     1442                        isset( $args['orderby'] )
     1443                        && ! empty( $args['orderby'] )
     1444                        && in_array( $args['orderby'], $allowed_keys )
     1445                ) {
     1446                        switch( $args['orderby'] ) {
     1447                                case $primary_meta_key:
     1448                                case 'meta_value':
     1449                                        if ( ! empty( $primary_meta_query['type'] ) ) {
     1450                                                $orderby = "ORDER BY CAST({$primary_meta_query['alias']}.meta_value AS {$primary_meta_query['cast']})";
     1451                                        } else {
     1452                                                $orderby = "ORDER BY {$primary_meta_query['alias']}.meta_value";
     1453                                        }
     1454                                        break;
     1455                                case 'meta_value_num':
     1456                                        $orderby = "ORDER BY {$primary_meta_query['alias']}.meta_value+0";
     1457                                        break;
     1458                                default:
     1459                                        if ( array_key_exists( $args['orderby'], $meta_clauses ) ) {
     1460                                                // $orderby corresponds to a meta_query clause.
     1461                                                $meta_clause = $meta_clauses[ $args['orderby'] ];
     1462                                                $orderby = "ORDER BY CAST({$meta_clause['alias']}.meta_value AS {$meta_clause['cast']})";
     1463                                        }
     1464                                        break;
     1465                        }
     1466                }
    14241467        }
    14251468
    14261469        $selects = array();
  • tests/phpunit/tests/term/getTerms.php

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