| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-13 10:15:08 -07:00
										 |  |  | final class PhabricatorProjectQuery | 
					
						
							|  |  |  |   extends PhabricatorCursorPagedPolicyAwareQuery { | 
					
						
							| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-17 16:29:35 -08:00
										 |  |  |   private $ids; | 
					
						
							|  |  |  |   private $phids; | 
					
						
							| 
									
										
										
										
											2012-08-07 11:54:24 -07:00
										 |  |  |   private $memberPHIDs; | 
					
						
							| 
									
										
										
										
											2013-03-08 07:12:24 -08:00
										 |  |  |   private $slugs; | 
					
						
							| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-07 14:59:38 -08:00
										 |  |  |   private $status       = 'status-any'; | 
					
						
							|  |  |  |   const STATUS_ANY      = 'status-any'; | 
					
						
							|  |  |  |   const STATUS_OPEN     = 'status-open'; | 
					
						
							|  |  |  |   const STATUS_CLOSED   = 'status-closed'; | 
					
						
							|  |  |  |   const STATUS_ACTIVE   = 'status-active'; | 
					
						
							|  |  |  |   const STATUS_ARCHIVED = 'status-archived'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-17 16:29:35 -08:00
										 |  |  |   private $needMembers; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   public function withIDs(array $ids) { | 
					
						
							|  |  |  |     $this->ids = $ids; | 
					
						
							|  |  |  |     return $this; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   public function withPHIDs(array $phids) { | 
					
						
							|  |  |  |     $this->phids = $phids; | 
					
						
							|  |  |  |     return $this; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-07 14:59:38 -08:00
										 |  |  |   public function withStatus($status) { | 
					
						
							|  |  |  |     $this->status = $status; | 
					
						
							|  |  |  |     return $this; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 11:54:24 -07:00
										 |  |  |   public function withMemberPHIDs(array $member_phids) { | 
					
						
							|  |  |  |     $this->memberPHIDs = $member_phids; | 
					
						
							| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  |     return $this; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-08 07:12:24 -08:00
										 |  |  |   public function withPhrictionSlugs(array $slugs) { | 
					
						
							|  |  |  |     $this->slugs = $slugs; | 
					
						
							|  |  |  |     return $this; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-17 16:29:35 -08:00
										 |  |  |   public function needMembers($need_members) { | 
					
						
							|  |  |  |     $this->needMembers = $need_members; | 
					
						
							|  |  |  |     return $this; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-08 17:10:10 -07:00
										 |  |  |   protected function getPagingColumn() { | 
					
						
							|  |  |  |     return 'name'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   protected function getPagingValue($result) { | 
					
						
							|  |  |  |     return $result->getName(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-11 07:05:45 -07:00
										 |  |  |   protected function getReversePaging() { | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-01 11:28:02 -08:00
										 |  |  |   protected function loadPage() { | 
					
						
							| 
									
										
										
										
											2012-08-07 11:54:39 -07:00
										 |  |  |     $table = new PhabricatorProject(); | 
					
						
							| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  |     $conn_r = $table->establishConnection('r'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-11 07:05:01 -07:00
										 |  |  |     // NOTE: Because visibility checks for projects depend on whether or not
 | 
					
						
							|  |  |  |     // the user is a project member, we always load their membership. If we're
 | 
					
						
							|  |  |  |     // loading all members anyway we can piggyback on that; otherwise we
 | 
					
						
							|  |  |  |     // do an explicit join.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $select_clause = ''; | 
					
						
							|  |  |  |     if (!$this->needMembers) { | 
					
						
							|  |  |  |       $select_clause = ', vm.dst viewerIsMember'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  |     $data = queryfx_all( | 
					
						
							|  |  |  |       $conn_r, | 
					
						
							| 
									
										
										
										
											2012-08-11 07:05:01 -07:00
										 |  |  |       'SELECT p.* %Q FROM %T p %Q %Q %Q %Q %Q', | 
					
						
							|  |  |  |       $select_clause, | 
					
						
							| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  |       $table->getTableName(), | 
					
						
							| 
									
										
										
										
											2012-08-07 18:02:05 -07:00
										 |  |  |       $this->buildJoinClause($conn_r), | 
					
						
							|  |  |  |       $this->buildWhereClause($conn_r), | 
					
						
							|  |  |  |       $this->buildGroupClause($conn_r), | 
					
						
							| 
									
										
										
										
											2012-08-11 07:05:01 -07:00
										 |  |  |       $this->buildOrderClause($conn_r), | 
					
						
							| 
									
										
										
										
											2012-08-07 11:54:39 -07:00
										 |  |  |       $this->buildLimitClause($conn_r)); | 
					
						
							| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-17 16:29:35 -08:00
										 |  |  |     $projects = $table->loadAllFromArray($data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-11 07:05:01 -07:00
										 |  |  |     if ($projects) { | 
					
						
							|  |  |  |       $viewer_phid = $this->getViewer()->getPHID(); | 
					
						
							|  |  |  |       if ($this->needMembers) { | 
					
						
							|  |  |  |         $etype = PhabricatorEdgeConfig::TYPE_PROJ_MEMBER; | 
					
						
							|  |  |  |         $members = id(new PhabricatorEdgeQuery()) | 
					
						
							|  |  |  |           ->withSourcePHIDs(mpull($projects, 'getPHID')) | 
					
						
							|  |  |  |           ->withEdgeTypes(array($etype)) | 
					
						
							|  |  |  |           ->execute(); | 
					
						
							|  |  |  |         foreach ($projects as $project) { | 
					
						
							|  |  |  |           $phid = $project->getPHID(); | 
					
						
							|  |  |  |           $project->attachMemberPHIDs(array_keys($members[$phid][$etype])); | 
					
						
							|  |  |  |           $project->setIsUserMember( | 
					
						
							|  |  |  |             $viewer_phid, | 
					
						
							|  |  |  |             isset($members[$phid][$etype][$viewer_phid])); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         foreach ($data as $row) { | 
					
						
							|  |  |  |           $projects[$row['id']]->setIsUserMember( | 
					
						
							|  |  |  |             $viewer_phid, | 
					
						
							|  |  |  |             ($row['viewerIsMember'] !== null)); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-01-17 16:29:35 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return $projects; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private function buildWhereClause($conn_r) { | 
					
						
							|  |  |  |     $where = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-07 14:59:38 -08:00
										 |  |  |     if ($this->status != self::STATUS_ANY) { | 
					
						
							|  |  |  |       switch ($this->status) { | 
					
						
							|  |  |  |         case self::STATUS_OPEN: | 
					
						
							|  |  |  |         case self::STATUS_ACTIVE: | 
					
						
							| 
									
										
										
										
											2012-08-07 18:02:05 -07:00
										 |  |  |           $filter = array( | 
					
						
							|  |  |  |             PhabricatorProjectStatus::STATUS_ACTIVE, | 
					
						
							|  |  |  |           ); | 
					
						
							| 
									
										
										
										
											2012-02-07 14:59:38 -08:00
										 |  |  |           break; | 
					
						
							| 
									
										
										
										
											2012-08-07 18:02:05 -07:00
										 |  |  |         case self::STATUS_CLOSED: | 
					
						
							| 
									
										
										
										
											2012-02-07 14:59:38 -08:00
										 |  |  |         case self::STATUS_ARCHIVED: | 
					
						
							| 
									
										
										
										
											2012-08-07 18:02:05 -07:00
										 |  |  |           $filter = array( | 
					
						
							|  |  |  |             PhabricatorProjectStatus::STATUS_ARCHIVED, | 
					
						
							|  |  |  |           ); | 
					
						
							| 
									
										
										
										
											2012-02-07 14:59:38 -08:00
										 |  |  |           break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |           throw new Exception( | 
					
						
							|  |  |  |             "Unknown project status '{$this->status}'!"); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2012-08-07 18:02:05 -07:00
										 |  |  |       $where[] = qsprintf( | 
					
						
							|  |  |  |         $conn_r, | 
					
						
							|  |  |  |         'status IN (%Ld)', | 
					
						
							|  |  |  |         $filter); | 
					
						
							| 
									
										
										
										
											2012-02-07 14:59:38 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-17 16:29:35 -08:00
										 |  |  |     if ($this->ids) { | 
					
						
							|  |  |  |       $where[] = qsprintf( | 
					
						
							|  |  |  |         $conn_r, | 
					
						
							|  |  |  |         'id IN (%Ld)', | 
					
						
							|  |  |  |         $this->ids); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ($this->phids) { | 
					
						
							|  |  |  |       $where[] = qsprintf( | 
					
						
							|  |  |  |         $conn_r, | 
					
						
							|  |  |  |         'phid IN (%Ls)', | 
					
						
							|  |  |  |         $this->phids); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 18:02:05 -07:00
										 |  |  |     if ($this->memberPHIDs) { | 
					
						
							|  |  |  |       $where[] = qsprintf( | 
					
						
							|  |  |  |         $conn_r, | 
					
						
							| 
									
										
										
										
											2012-08-11 07:05:01 -07:00
										 |  |  |         'e.dst IN (%Ls)', | 
					
						
							| 
									
										
										
										
											2012-08-07 18:02:05 -07:00
										 |  |  |         $this->memberPHIDs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-08 07:12:24 -08:00
										 |  |  |     if ($this->slugs) { | 
					
						
							|  |  |  |       $where[] = qsprintf( | 
					
						
							|  |  |  |         $conn_r, | 
					
						
							|  |  |  |         'phrictionSlug IN (%Ls)', | 
					
						
							|  |  |  |         $this->slugs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-08 17:10:10 -07:00
										 |  |  |     $where[] = $this->buildPagingClause($conn_r); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 11:54:39 -07:00
										 |  |  |     return $this->formatWhereClause($where); | 
					
						
							| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 18:02:05 -07:00
										 |  |  |   private function buildGroupClause($conn_r) { | 
					
						
							|  |  |  |     if ($this->memberPHIDs) { | 
					
						
							|  |  |  |       return 'GROUP BY p.id'; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return ''; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 18:02:05 -07:00
										 |  |  |   private function buildJoinClause($conn_r) { | 
					
						
							| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  |     $joins = array(); | 
					
						
							| 
									
										
										
										
											2012-08-07 18:02:05 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-11 07:05:01 -07:00
										 |  |  |     if (!$this->needMembers) { | 
					
						
							|  |  |  |       $joins[] = qsprintf( | 
					
						
							|  |  |  |         $conn_r, | 
					
						
							|  |  |  |         'LEFT JOIN %T vm ON vm.src = p.phid AND vm.type = %d AND vm.dst = %s', | 
					
						
							|  |  |  |         PhabricatorEdgeConfig::TABLE_NAME_EDGE, | 
					
						
							|  |  |  |         PhabricatorEdgeConfig::TYPE_PROJ_MEMBER, | 
					
						
							|  |  |  |         $this->getViewer()->getPHID()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 11:54:24 -07:00
										 |  |  |     if ($this->memberPHIDs) { | 
					
						
							| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  |       $joins[] = qsprintf( | 
					
						
							|  |  |  |         $conn_r, | 
					
						
							| 
									
										
										
										
											2012-08-11 07:05:01 -07:00
										 |  |  |         'JOIN %T e ON e.src = p.phid AND e.type = %d', | 
					
						
							|  |  |  |         PhabricatorEdgeConfig::TABLE_NAME_EDGE, | 
					
						
							|  |  |  |         PhabricatorEdgeConfig::TYPE_PROJ_MEMBER); | 
					
						
							| 
									
										
										
										
											2011-12-16 17:08:18 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return implode(' ', $joins); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |