@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Modernize ManiphestTask paging and ordering

Summary:
Ref T7803. The ApplicationSearch integration is still a little rough here, but it seems to have the correct behavior.

The rest of this is now at least relatively sane, cohesive, and properly behaved.

Test Plan:
- Used all grouping and ordering queries in Maniphest. Pagingated results.
- Used custom field ordering in Maniphest. Paginated results.
- Paginated through the `null` section of "Assigned" and "Projects" group-by queries. Pagingation now works correctly (it does not work at HEAD).
- Ran unit tests covering priority changes.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T7803

Differential Revision: https://secure.phabricator.com/D12372

+218 -332
+13 -7
src/applications/maniphest/editor/ManiphestTransactionEditor.php
··· 612 612 613 613 $query = id(new ManiphestTaskQuery()) 614 614 ->setViewer(PhabricatorUser::getOmnipotentUser()) 615 - ->setOrderBy(ManiphestTaskQuery::ORDER_PRIORITY) 616 615 ->withPriorities(array($priority)) 617 616 ->setLimit(1); 618 617 619 618 if ($is_end) { 620 - $query->setReversePaging(true); 619 + $query->setOrderVector(array('-priority', '-subpriority', '-id')); 620 + } else { 621 + $query->setOrderVector(array('priority', 'subpriority', 'id')); 621 622 } 622 623 623 624 $result = $query->executeOne(); ··· 675 676 // Get all of the tasks with the same subpriority as the adjacent 676 677 // task, including the adjacent task itself. 677 678 $shift_base = $adjacent->getSubpriority(); 678 - $shift_all = id(new ManiphestTaskQuery()) 679 + $query = id(new ManiphestTaskQuery()) 679 680 ->setViewer(PhabricatorUser::getOmnipotentUser()) 680 - ->setOrderBy(ManiphestTaskQuery::ORDER_PRIORITY) 681 681 ->withPriorities(array($adjacent->getPriority())) 682 - ->withSubpriorities(array($shift_base)) 683 - ->setReversePaging(!$is_after) 684 - ->execute(); 682 + ->withSubpriorities(array($shift_base)); 683 + 684 + if (!$is_after) { 685 + $query->setOrderVector(array('-priority', '-subpriority', '-id')); 686 + } else { 687 + $query->setOrderVector(array('priority', 'subpriority', 'id')); 688 + } 689 + 690 + $shift_all = $query->execute(); 685 691 $shift_last = last($shift_all); 686 692 687 693 // Find the subpriority before or after the task at the end of the
+159 -285
src/applications/maniphest/query/ManiphestTaskQuery.php
··· 21 21 private $dateCreatedBefore; 22 22 private $dateModifiedAfter; 23 23 private $dateModifiedBefore; 24 - private $reversePaging; 25 24 26 25 private $fullTextSearch = ''; 27 26 ··· 54 53 55 54 private $needSubscriberPHIDs; 56 55 private $needProjectPHIDs; 57 - 58 56 private $blockingTasks; 59 57 private $blockedTasks; 60 - 61 58 private $projectPolicyCheckFailed = false; 62 - 63 - const DEFAULT_PAGE_SIZE = 1000; 64 59 65 60 public function withAuthors(array $authors) { 66 61 $this->authorPHIDs = $authors; ··· 231 226 return $this; 232 227 } 233 228 229 + protected function newResultObject() { 230 + return new ManiphestTask(); 231 + } 232 + 234 233 protected function willExecute() { 235 234 // Make sure the user can see any projects specified in this 236 235 // query FIRST. ··· 252 251 } 253 252 $this->projectPHIDs = array_values($this->projectPHIDs); 254 253 } 254 + 255 + // If we already have an order vector, use it as provided. 256 + // TODO: This is a messy hack to make setOrderVector() stronger than 257 + // setPriority(). 258 + $vector = $this->getOrderVector(); 259 + $keys = mpull(iterator_to_array($vector), 'getOrderKey'); 260 + if (array_values($keys) !== array('id')) { 261 + return; 262 + } 263 + 264 + $parts = array(); 265 + switch ($this->groupBy) { 266 + case self::GROUP_NONE: 267 + break; 268 + case self::GROUP_PRIORITY: 269 + $parts[] = array('priority'); 270 + break; 271 + case self::GROUP_OWNER: 272 + $parts[] = array('owner'); 273 + break; 274 + case self::GROUP_STATUS: 275 + $parts[] = array('status'); 276 + break; 277 + case self::GROUP_PROJECT: 278 + $parts[] = array('project'); 279 + break; 280 + } 281 + 282 + if ($this->applicationSearchOrders) { 283 + $columns = array(); 284 + foreach ($this->applicationSearchOrders as $order) { 285 + $part = 'custom:'.$order['key']; 286 + if ($order['ascending']) { 287 + $part = '-'.$part; 288 + } 289 + $columns[] = $part; 290 + } 291 + $columns[] = 'id'; 292 + $parts[] = $columns; 293 + } else { 294 + switch ($this->orderBy) { 295 + case self::ORDER_PRIORITY: 296 + $parts[] = array('priority', 'subpriority', 'id'); 297 + break; 298 + case self::ORDER_CREATED: 299 + $parts[] = array('id'); 300 + break; 301 + case self::ORDER_MODIFIED: 302 + $parts[] = array('updated', 'id'); 303 + break; 304 + case self::ORDER_TITLE: 305 + $parts[] = array('title', 'id'); 306 + break; 307 + } 308 + } 309 + 310 + $parts = array_mergev($parts); 311 + // We may have a duplicate column if we are both ordering and grouping 312 + // by priority. 313 + $parts = array_unique($parts); 314 + $this->setOrderVector($parts); 255 315 } 256 316 257 317 protected function loadPage() { ··· 268 328 $where[] = $this->buildTaskPHIDsWhereClause($conn); 269 329 $where[] = $this->buildStatusWhereClause($conn); 270 330 $where[] = $this->buildStatusesWhereClause($conn); 271 - $where[] = $this->buildPrioritiesWhereClause($conn); 272 331 $where[] = $this->buildDependenciesWhereClause($conn); 273 332 $where[] = $this->buildAuthorWhereClause($conn); 274 333 $where[] = $this->buildOwnerWhereClause($conn); ··· 306 365 $this->dateModifiedBefore); 307 366 } 308 367 368 + if ($this->priorities) { 369 + $where[] = qsprintf( 370 + $conn, 371 + 'task.priority IN (%Ld)', 372 + $this->priorities); 373 + } 374 + 375 + if ($this->subpriorities) { 376 + $where[] = qsprintf( 377 + $conn, 378 + 'task.subpriority IN (%Lf)', 379 + $this->subpriorities); 380 + } 381 + 309 382 $where[] = $this->buildPagingClause($conn); 310 383 311 384 $where = $this->formatWhereClause($where); ··· 325 398 count($this->projectPHIDs)); 326 399 } 327 400 328 - $order = $this->buildCustomOrderClause($conn); 329 - 330 - // TODO: Clean up this nonstandardness. 331 - if (!$this->getLimit()) { 332 - $this->setLimit(self::DEFAULT_PAGE_SIZE); 333 - } 334 - 335 401 $group_column = ''; 336 402 switch ($this->groupBy) { 337 403 case self::GROUP_PROJECT: ··· 351 417 $where, 352 418 $this->buildGroupClause($conn), 353 419 $having, 354 - $order, 420 + $this->buildOrderClause($conn), 355 421 $this->buildLimitClause($conn)); 356 422 357 423 switch ($this->groupBy) { ··· 504 570 return null; 505 571 } 506 572 507 - private function buildPrioritiesWhereClause(AphrontDatabaseConnection $conn) { 508 - if ($this->priorities) { 509 - return qsprintf( 510 - $conn, 511 - 'task.priority IN (%Ld)', 512 - $this->priorities); 513 - } 514 - 515 - if ($this->subpriorities) { 516 - return qsprintf( 517 - $conn, 518 - 'task.subpriority IN (%Lf)', 519 - $this->subpriorities); 520 - } 521 - 522 - return null; 523 - } 524 - 525 573 private function buildAuthorWhereClause(AphrontDatabaseConnection $conn) { 526 574 if (!$this->authorPHIDs) { 527 575 return null; ··· 689 737 'xproject.dst IS NULL'); 690 738 } 691 739 692 - private function buildCustomOrderClause(AphrontDatabaseConnection $conn) { 693 - $reverse = ($this->getBeforeID() xor $this->getReversePaging()); 694 - 695 - $order = array(); 696 - 697 - switch ($this->groupBy) { 698 - case self::GROUP_NONE: 699 - break; 700 - case self::GROUP_PRIORITY: 701 - $order[] = 'task.priority'; 702 - break; 703 - case self::GROUP_OWNER: 704 - $order[] = 'task.ownerOrdering'; 705 - break; 706 - case self::GROUP_STATUS: 707 - $order[] = 'task.status'; 708 - break; 709 - case self::GROUP_PROJECT: 710 - $order[] = '<group.project>'; 711 - break; 712 - default: 713 - throw new Exception("Unknown group query '{$this->groupBy}'!"); 714 - } 715 - 716 - $app_order = $this->buildApplicationSearchOrders($conn, $reverse); 717 - 718 - if (!$app_order) { 719 - switch ($this->orderBy) { 720 - case self::ORDER_PRIORITY: 721 - $order[] = 'task.priority'; 722 - $order[] = 'task.subpriority'; 723 - $order[] = 'task.dateModified'; 724 - break; 725 - case self::ORDER_CREATED: 726 - $order[] = 'task.id'; 727 - break; 728 - case self::ORDER_MODIFIED: 729 - $order[] = 'task.dateModified'; 730 - break; 731 - case self::ORDER_TITLE: 732 - $order[] = 'task.title'; 733 - break; 734 - default: 735 - throw new Exception("Unknown order query '{$this->orderBy}'!"); 736 - } 737 - } 738 - 739 - $order = array_unique($order); 740 - 741 - if (empty($order) && empty($app_order)) { 742 - return null; 743 - } 744 - 745 - foreach ($order as $k => $column) { 746 - switch ($column) { 747 - case 'subpriority': 748 - case 'ownerOrdering': 749 - case 'title': 750 - if ($reverse) { 751 - $order[$k] = "{$column} DESC"; 752 - } else { 753 - $order[$k] = "{$column} ASC"; 754 - } 755 - break; 756 - case '<group.project>': 757 - // Put "No Project" at the end of the list. 758 - if ($reverse) { 759 - $order[$k] = 760 - 'projectGroupName.indexedObjectName IS NULL DESC, '. 761 - 'projectGroupName.indexedObjectName DESC'; 762 - } else { 763 - $order[$k] = 764 - 'projectGroupName.indexedObjectName IS NULL ASC, '. 765 - 'projectGroupName.indexedObjectName ASC'; 766 - } 767 - break; 768 - default: 769 - if ($reverse) { 770 - $order[$k] = "{$column} ASC"; 771 - } else { 772 - $order[$k] = "{$column} DESC"; 773 - } 774 - break; 775 - } 776 - } 777 - 778 - if ($app_order) { 779 - foreach ($app_order as $order_by) { 780 - $order[] = $order_by; 781 - } 782 - } 783 - 784 - if ($reverse) { 785 - $order[] = 'task.id ASC'; 786 - } else { 787 - $order[] = 'task.id DESC'; 788 - } 789 - 790 - return 'ORDER BY '.implode(', ', $order); 791 - } 792 - 793 740 private function buildJoinsClause(AphrontDatabaseConnection $conn_r) { 794 741 $edge_table = PhabricatorEdgeConfig::TABLE_NAME_EDGE; 795 742 ··· 954 901 955 902 switch ($this->groupBy) { 956 903 case self::GROUP_NONE: 957 - return $id; 904 + case self::GROUP_STATUS: 958 905 case self::GROUP_PRIORITY: 959 - return $id.'.'.$result->getPriority(); 960 906 case self::GROUP_OWNER: 961 - return rtrim($id.'.'.$result->getOwnerPHID(), '.'); 962 - case self::GROUP_STATUS: 963 - return $id.'.'.$result->getStatus(); 907 + return $id; 964 908 case self::GROUP_PROJECT: 965 909 return rtrim($id.'.'.$result->getGroupByProjectPHID(), '.'); 966 910 default: ··· 968 912 } 969 913 } 970 914 971 - protected function buildPagingClause(AphrontDatabaseConnection $conn_r) { 972 - $before_id = $this->getBeforeID(); 973 - $after_id = $this->getAfterID(); 974 - 975 - if (!$before_id && !$after_id) { 976 - return ''; 977 - } 915 + public function getOrderableColumns() { 916 + return parent::getOrderableColumns() + array( 917 + 'priority' => array( 918 + 'table' => 'task', 919 + 'column' => 'priority', 920 + 'type' => 'int', 921 + ), 922 + 'owner' => array( 923 + 'table' => 'task', 924 + 'column' => 'ownerOrdering', 925 + 'null' => 'head', 926 + 'reverse' => true, 927 + 'type' => 'string', 928 + ), 929 + 'status' => array( 930 + 'table' => 'task', 931 + 'column' => 'status', 932 + 'type' => 'string', 933 + 'reverse' => true, 934 + ), 935 + 'project' => array( 936 + 'table' => 'projectGroupName', 937 + 'column' => 'indexedObjectName', 938 + 'type' => 'string', 939 + 'null' => 'head', 940 + 'reverse' => true, 941 + ), 942 + 'title' => array( 943 + 'table' => 'task', 944 + 'column' => 'title', 945 + 'type' => 'string', 946 + 'reverse' => true, 947 + ), 948 + 'subpriority' => array( 949 + 'table' => 'task', 950 + 'column' => 'subpriority', 951 + 'type' => 'float', 952 + ), 953 + 'updated' => array( 954 + 'table' => 'task', 955 + 'column' => 'dateModified', 956 + 'type' => 'int', 957 + ), 958 + ); 959 + } 978 960 979 - $cursor_id = nonempty($before_id, $after_id); 980 - $cursor_parts = explode('.', $cursor_id, 2); 961 + protected function getPagingValueMap($cursor, array $keys) { 962 + $cursor_parts = explode('.', $cursor, 2); 981 963 $task_id = $cursor_parts[0]; 982 964 $group_id = idx($cursor_parts, 1); 983 965 984 - $cursor = $this->loadCursorObject($task_id); 985 - if (!$cursor) { 986 - // We may loop if we have a cursor and don't build a paging clause; fail 987 - // instead. 988 - throw new PhabricatorEmptyQueryException(); 989 - } 990 - 991 - $columns = array(); 992 - 993 - switch ($this->groupBy) { 994 - case self::GROUP_NONE: 995 - break; 996 - case self::GROUP_PRIORITY: 997 - $columns[] = array( 998 - 'table' => 'task', 999 - 'column' => 'priority', 1000 - 'value' => (int)$group_id, 1001 - 'type' => 'int', 1002 - ); 1003 - break; 1004 - case self::GROUP_OWNER: 1005 - $value = null; 1006 - if ($group_id) { 1007 - $paging_users = id(new PhabricatorPeopleQuery()) 1008 - ->setViewer($this->getViewer()) 1009 - ->withPHIDs(array($group_id)) 1010 - ->execute(); 1011 - if ($paging_users) { 1012 - $value = head($paging_users)->getUsername(); 1013 - } 1014 - } 1015 - $columns[] = array( 1016 - 'table' => 'task', 1017 - 'column' => 'ownerOrdering', 1018 - 'value' => $value, 1019 - 'type' => 'string', 1020 - 'null' => 'head', 1021 - 'reverse' => true, 1022 - ); 1023 - break; 1024 - case self::GROUP_STATUS: 1025 - $columns[] = array( 1026 - 'table' => 'task', 1027 - 'column' => 'status', 1028 - 'value' => $group_id, 1029 - 'type' => 'string', 1030 - ); 1031 - break; 1032 - case self::GROUP_PROJECT: 1033 - $value = null; 1034 - if ($group_id) { 1035 - $paging_projects = id(new PhabricatorProjectQuery()) 1036 - ->setViewer($this->getViewer()) 1037 - ->withPHIDs(array($group_id)) 1038 - ->execute(); 1039 - if ($paging_projects) { 1040 - $value = head($paging_projects)->getName(); 1041 - } 1042 - } 966 + $task = $this->loadCursorObject($task_id); 1043 967 1044 - $columns[] = array( 1045 - 'table' => 'projectGroupName', 1046 - 'column' => 'indexedObjectName', 1047 - 'value' => $value, 1048 - 'type' => 'string', 1049 - 'null' => 'head', 1050 - 'reverse' => true, 1051 - ); 1052 - break; 1053 - default: 1054 - throw new Exception("Unknown group query '{$this->groupBy}'!"); 1055 - } 968 + $map = array( 969 + 'id' => $task->getID(), 970 + 'priority' => $task->getPriority(), 971 + 'subpriority' => $task->getSubpriority(), 972 + 'owner' => $task->getOwnerOrdering(), 973 + 'status' => $task->getStatus(), 974 + 'title' => $task->getTitle(), 975 + 'updated' => $task->getDateModified(), 976 + ); 1056 977 1057 - $app_columns = $this->buildApplicationSearchPagination($conn_r, $cursor); 1058 - if ($app_columns) { 1059 - $columns = array_merge($columns, $app_columns); 1060 - } else { 1061 - switch ($this->orderBy) { 1062 - case self::ORDER_PRIORITY: 1063 - if ($this->groupBy != self::GROUP_PRIORITY) { 1064 - $columns[] = array( 1065 - 'table' => 'task', 1066 - 'column' => 'priority', 1067 - 'value' => (int)$cursor->getPriority(), 1068 - 'type' => 'int', 1069 - ); 978 + foreach ($keys as $key) { 979 + switch ($key) { 980 + case 'project': 981 + $value = null; 982 + if ($group_id) { 983 + $paging_projects = id(new PhabricatorProjectQuery()) 984 + ->setViewer($this->getViewer()) 985 + ->withPHIDs(array($group_id)) 986 + ->execute(); 987 + if ($paging_projects) { 988 + $value = head($paging_projects)->getName(); 989 + } 1070 990 } 1071 - $columns[] = array( 1072 - 'table' => 'task', 1073 - 'column' => 'subpriority', 1074 - 'value' => $cursor->getSubpriority(), 1075 - 'type' => 'float', 1076 - ); 1077 - $columns[] = array( 1078 - 'table' => 'task', 1079 - 'column' => 'dateModified', 1080 - 'value' => (int)$cursor->getDateModified(), 1081 - 'type' => 'int', 1082 - ); 991 + $map[$key] = $value; 1083 992 break; 1084 - case self::ORDER_CREATED: 1085 - // This just uses the ID column, below. 1086 - break; 1087 - case self::ORDER_MODIFIED: 1088 - $columns[] = array( 1089 - 'table' => 'task', 1090 - 'column' => 'dateModified', 1091 - 'value' => (int)$cursor->getDateModified(), 1092 - 'type' => 'int', 1093 - ); 1094 - break; 1095 - case self::ORDER_TITLE: 1096 - $columns[] = array( 1097 - 'table' => 'task', 1098 - 'column' => 'title', 1099 - 'value' => $cursor->getTitle(), 1100 - 'type' => 'string', 1101 - ); 1102 - break; 1103 - default: 1104 - throw new Exception("Unknown order query '{$this->orderBy}'!"); 1105 993 } 1106 994 } 1107 995 1108 - $columns[] = array( 1109 - 'table' => 'task', 1110 - 'column' => 'id', 1111 - 'value' => $cursor->getID(), 1112 - 'type' => 'int', 1113 - ); 996 + foreach ($keys as $key) { 997 + if ($this->isCustomFieldOrderKey($key)) { 998 + $map += $this->getPagingValueMapForCustomFields($task); 999 + break; 1000 + } 1001 + } 1114 1002 1115 - return $this->buildPagingClauseFromMultipleColumns( 1116 - $conn_r, 1117 - $columns, 1118 - array( 1119 - 'reversed' => (bool)($before_id xor $this->getReversePaging()), 1120 - )); 1003 + return $map; 1121 1004 } 1122 1005 1123 1006 protected function getPrimaryTableAlias() { ··· 1126 1009 1127 1010 public function getQueryApplicationClass() { 1128 1011 return 'PhabricatorManiphestApplication'; 1129 - } 1130 - 1131 - public function setReversePaging($reverse_paging) { 1132 - $this->reversePaging = $reverse_paging; 1133 - return $this; 1134 - } 1135 - 1136 - protected function getReversePaging() { 1137 - return $this->reversePaging; 1138 1012 } 1139 1013 1140 1014 }
+46 -40
src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
··· 14 14 private $afterID; 15 15 private $beforeID; 16 16 private $applicationSearchConstraints = array(); 17 - private $applicationSearchOrders = array(); 17 + protected $applicationSearchOrders = array(); 18 18 private $internalPaging; 19 19 private $orderVector; 20 20 ··· 158 158 * @return string Alias for the primary table. 159 159 */ 160 160 protected function getPrimaryTableAlias() { 161 + return null; 162 + } 163 + 164 + protected function newResultObject() { 161 165 return null; 162 166 } 163 167 ··· 546 550 return array(); 547 551 } 548 552 549 - return array( 553 + $columns = array( 550 554 'id' => array( 551 555 'table' => $this->getPrimaryTableAlias(), 552 556 'column' => 'id', ··· 555 559 'unique' => true, 556 560 ), 557 561 ); 562 + 563 + $object = $this->newResultObject(); 564 + if ($object instanceof PhabricatorCustomFieldInterface) { 565 + $list = PhabricatorCustomField::getObjectFields( 566 + $object, 567 + PhabricatorCustomField::ROLE_APPLICATIONSEARCH); 568 + foreach ($list->getFields() as $field) { 569 + $index = $field->buildOrderIndex(); 570 + if (!$index) { 571 + continue; 572 + } 573 + 574 + $key = $field->getFieldKey(); 575 + $digest = $field->getFieldIndex(); 576 + 577 + $full_key = 'custom:'.$key; 578 + $columns[$full_key] = array( 579 + 'table' => 'appsearch_order_'.$digest, 580 + 'column' => 'indexValue', 581 + 'type' => $index->getIndexValueType(), 582 + 'null' => 'tail', 583 + ); 584 + } 585 + } 586 + 587 + return $columns; 558 588 } 559 589 560 590 ··· 961 991 962 992 foreach ($this->applicationSearchOrders as $key => $order) { 963 993 $table = $order['table']; 964 - $alias = 'appsearch_order_'.$key; 965 994 $index = $order['index']; 995 + $alias = 'appsearch_order_'.$index; 966 996 $phid_column = $this->getApplicationSearchObjectPHIDColumn(); 967 997 968 998 $joins[] = qsprintf( ··· 980 1010 return implode(' ', $joins); 981 1011 } 982 1012 983 - protected function buildApplicationSearchOrders( 984 - AphrontDatabaseConnection $conn_r, 985 - $reverse) { 986 - 987 - $orders = array(); 988 - foreach ($this->applicationSearchOrders as $key => $order) { 989 - $alias = 'appsearch_order_'.$key; 990 - 991 - if ($order['ascending'] xor $reverse) { 992 - $orders[] = qsprintf($conn_r, '%T.indexValue ASC', $alias); 993 - } else { 994 - $orders[] = qsprintf($conn_r, '%T.indexValue DESC', $alias); 995 - } 996 - } 997 - 998 - return $orders; 999 - } 1000 - 1001 - protected function buildApplicationSearchPagination( 1002 - AphrontDatabaseConnection $conn_r, 1003 - $cursor) { 1013 + protected function getPagingValueMapForCustomFields( 1014 + PhabricatorCustomFieldInterface $object) { 1004 1015 1005 1016 // We have to get the current field values on the cursor object. 1006 1017 $fields = PhabricatorCustomField::getObjectFields( 1007 - $cursor, 1018 + $object, 1008 1019 PhabricatorCustomField::ROLE_APPLICATIONSEARCH); 1009 1020 $fields->setViewer($this->getViewer()); 1010 - $fields->readFieldsFromStorage($cursor); 1021 + $fields->readFieldsFromStorage($object); 1011 1022 1012 - $fields = mpull($fields->getFields(), null, 'getFieldKey'); 1023 + $map = array(); 1024 + foreach ($fields->getFields() as $field) { 1025 + $map['custom:'.$field->getFieldKey()] = $field->getValueForStorage(); 1026 + } 1013 1027 1014 - $columns = array(); 1015 - foreach ($this->applicationSearchOrders as $key => $order) { 1016 - $alias = 'appsearch_order_'.$key; 1028 + return $map; 1029 + } 1017 1030 1018 - $field = idx($fields, $order['key']); 1019 - 1020 - $columns[] = array( 1021 - 'name' => $alias.'.indexValue', 1022 - 'value' => $field->getValueForStorage(), 1023 - 'type' => $order['type'], 1024 - ); 1025 - } 1026 - 1027 - return $columns; 1031 + protected function isCustomFieldOrderKey($key) { 1032 + $prefix = 'custom:'; 1033 + return !strncmp($key, $prefix, strlen($prefix)); 1028 1034 } 1029 1035 1030 1036 }