Example #1
0
 public function search()
 {
     $this->view = null;
     $user = User::find(Session::uid());
     $isRunner = $user->is_runner;
     $publicOnly = !$user->isInternal();
     $query = isset($_REQUEST['query']) ? $_REQUEST['query'] : null;
     if ($query != null) {
         if (preg_match("/^\\#?\\d+\$/", $query)) {
             $id = ltrim($query, '#');
             if (Project::isJobId($id)) {
                 echo json_encode(array('redirect' => $id));
                 return;
             }
         }
     }
     $conds = array();
     $invertedStatusConds = array();
     $subConds = array();
     $projectFilter = isset($_REQUEST['project_id']) ? $_REQUEST['project_id'] : '';
     if (!empty($projectFilter) && $projectFilter != 'All') {
         $projectId = (int) $projectFilter;
         $conds[] = "`w`.`project_id` = '{$projectId}'";
         $invertedStatusConds[] = "`w`.`project_id` = '{$projectId}'";
     }
     $statusFilter = isset($_REQUEST['status']) && !empty($_REQUEST['status']) ? preg_split('/,/', $_REQUEST['status']) : (empty($query) ? array('Active') : array());
     if ($statusFilter) {
         $statusCond = '';
         foreach ($statusFilter as $status) {
             if (empty($status)) {
                 continue;
             }
             switch ($status) {
                 case 'Draft':
                     $statusCond .= (empty($statusCond) ? '' : ' OR ') . "`w`.`status` = '{$status}' AND `w`.`creator_id` = '{$user->getId()}'";
                     break;
                 case 'Suggestion':
                 case 'Bidding':
                 case 'In Progress':
                 case 'QA Ready':
                 case 'Review':
                 case 'Merged':
                 case 'Done':
                 case 'Pass':
                     $statusCond .= (empty($statusCond) ? '' : ' OR ') . "`w`.`status` = '{$status}'";
                     break;
                     // Pseudo status filters
                 // Pseudo status filters
                 case 'Code Review':
                     $statusCond .= (empty($statusCond) ? '' : ' OR ') . "`w`.`status` = 'Review'";
                     break;
                 case 'Needs-Review':
                     $statusCond .= (empty($statusCond) ? '' : ' OR ') . "\n                                `w`.`status` = 'Review'\n                            AND `w`.`code_review_started` = 0";
                     break;
                 case 'Active':
                     $statusCond .= (empty($statusCond) ? '' : ' OR ') . "\n                               `w`.`status` = 'Suggestion'\n                            OR `w`.`status` = 'Bidding'\n                            OR `w`.`status` = 'In Progress'\n                            OR `w`.`status` = 'QA Ready'\n                            OR `w`.`status` = 'Review'\n                            OR `w`.`status` = 'Merged'";
                     break;
             }
         }
         if (!empty($statusCond)) {
             $conds[] = "({$statusCond})";
             $invertedStatusConds[] = "(\n                       !({$statusCond})\n                    AND\n                      CASE\n                        WHEN(`w`.`status` = 'Draft')\n                          THEN `w`.`creator_id` = '{$user->getId()}'\n                        ELSE true\n                      END\n                    )";
         } else {
             $invertedStatusConds[] = "false";
         }
     } else {
         $conds[] = "(\n                   `w`.`status` != 'Draft'\n                OR (\n                      `w`.`status` = 'Draft'\n                  AND `w`.`creator_id` = '{$user->getId()}'\n                )\n            )";
         $invertedStatusConds[] = "false";
     }
     $participants = array();
     if (isset($_REQUEST['participated']) && !empty($_REQUEST['participated'])) {
         $participants = preg_split('/,/', $_REQUEST['participated']);
     }
     $mentions = array();
     if (preg_match_all('/@([a-zA-Z][a-zA-Z0-9-]+)/', $query, $mentions, PREG_SET_ORDER)) {
         $mentionUsersFound = array();
         foreach ($mentions as $mention) {
             $mentionUser = User::find($mention[1]);
             if ($mentionId = $mentionUser->getId()) {
                 $mentionUsersFound[] = $mentionUser->getNickname();
                 $participants[] = $mentionId;
                 $query = trim(preg_replace('/@' . $mentionUser->getNickname() . '/', '', $query));
             }
         }
     }
     if ($publicOnly) {
         $conds[] = "`w`.is_internal = 0";
         $invertedStatusConds[] = "`w`.is_internal = 0";
     }
     if (isset($_REQUEST['following']) && !empty($_REQUEST["following"])) {
         $followingCond = "(\n                SELECT COUNT(*)\n                FROM `" . TASK_FOLLOWERS . "` `fol`\n                WHERE `fol`.`workitem_id` = `w`.`id`\n                  AND `fol`.`user_id` = {$user->getId()}\n            ) > 0";
         $conds[] = $followingCond;
         $invertedStatusConds[] = $followingCond;
     }
     /* text search */
     if ($query != null) {
         preg_match_all('/"(?:\\\\.|[^\\\\"])*"|\\S+/', $query, $matches);
         foreach ($matches[0] as $match) {
             $safeQuery = str_replace('\'', '\\\'', rawurldecode($match));
             $subConds[] = "(\n                        MATCH(`sub_w`.`summary`, `sub_w`.`notes`) AGAINST ('{$safeQuery}')\n                     OR MATCH(`sub_f`.`notes`) AGAINST ('{$safeQuery}')\n                     OR MATCH(`sub_com`.`comment`) AGAINST ('{$safeQuery}')\n                )";
         }
     }
     if (count($participants) > 0) {
         foreach ($participants as $participant) {
             $participantUser = User::find($participant);
             if (!($participantId = $participantUser->getId())) {
                 continue;
             }
             $participantNickname = $participantUser->getNickname();
             $participantsCond = "(\n                    `w`.`mechanic_id` = '{$participantId}'\n                    OR `w`.`runner_id` = '{$participantId}'\n                    OR `w`.`creator_id` = '{$participantId}'\n                    OR `w`.`notes` REGEXP '([[:space:]]|^)@?{$participantNickname}([[:space:]]|\$)'\n                    OR EXISTS (\n                      SELECT 1\n                      FROM `" . FEES . "` AS `involved_f`\n                      WHERE `involved_f`.`worklist_id` = `w`.`id`\n                        AND `involved_f`.`withdrawn` = 0\n                        AND (\n                             `involved_f`.`notes` REGEXP '([[:space:]]|^)@?{$participantNickname}([[:space:]]|\$)'\n                          OR `involved_f`.`user_id` = {$participantId}\n                        )\n                      LIMIT 1\n                    )\n                    OR EXISTS (\n                      SELECT 1\n                      FROM `" . COMMENTS . "` AS `involved_com`\n                      WHERE `involved_com`.`worklist_id` = `w`.`id`\n                        AND (\n                             `involved_com`.`user_id` = {$participantId}\n                          OR `involved_com`.`comment` REGEXP '([[:space:]]|^)@?{$participantNickname}([[:space:]]|\$)'\n                        )\n                      LIMIT 1\n                    )" . ($isRunner || $user->getId() == $participantId ? "\n                            OR EXISTS (\n                              SELECT 1\n                              FROM `" . BIDS . "` AS `involved_b`\n                              WHERE `involved_b`.`worklist_id` = `w`.`id`\n                                AND `involved_b`.`bidder_id` = {$participantId}\n                              LIMIT 1\n                            )" : '') . "\n                )";
             $conds[] = $participantsCond;
             $invertedStatusConds[] = $participantsCond;
         }
     }
     /* labels filter */
     if (isset($_REQUEST["labels"]) && !empty($_REQUEST["labels"])) {
         $labels = preg_split('/,/', $_REQUEST["labels"]);
         if ($labels) {
             $labelsCond = '';
             foreach ($labels as $label) {
                 if (!strlen(trim($label))) {
                     continue;
                 }
                 $label = mysql_real_escape_string($label);
                 $labelsCond .= (strlen($labelsCond) ? ' AND ' : '') . "labels LIKE '%:{$label}:%'";
             }
             if ($labelsCond) {
                 $conds[] = "({$labelsCond})";
                 $invertedStatusConds[] = "({$labelsCond})";
             }
         }
     }
     $ret = WorkItem::search($query, $conds, $subConds, $_REQUEST['offset'], $_REQUEST['limit']);
     $invertedStatusRet = WorkItem::searchStats($query, $invertedStatusConds, $subConds);
     echo json_encode(array_merge($ret, $invertedStatusRet));
 }