true, self::CONFIG_SERIALIZATION => array( 'subprojectPHIDs' => self::SERIALIZATION_JSON, ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorPHIDConstants::PHID_TYPE_PROJ); } public function loadProfile() { $profile = id(new PhabricatorProjectProfile())->loadOneWhere( 'projectPHID = %s', $this->getPHID()); return $profile; } public function getMemberPHIDs() { return mpull($this->getAffiliations(), 'getUserPHID'); } public function loadMemberPHIDs() { return mpull($this->loadAffiliations(), 'getUserPHID'); } public function getAffiliations() { if ($this->affiliations === null) { throw new Exception('Attach affiliations first!'); } return $this->affiliations; } public function attachAffiliations(array $affiliations) { assert_instances_of($affiliations, 'PhabricatorProjectAffiliation'); $this->affiliations = $affiliations; return $this; } public function loadAffiliations() { $affils = PhabricatorProjectAffiliation::loadAllForProjectPHIDs( array($this->getPHID())); return $affils[$this->getPHID()]; } public function setPhrictionSlug($slug) { // NOTE: We're doing a little magic here and stripping out '/' so that // project pages always appear at top level under projects/ even if the // display name is "Hack / Slash" or similar (it will become // 'hack_slash' instead of 'hack/slash'). $slug = str_replace('/', ' ', $slug); $slug = PhabricatorSlug::normalize($slug); $this->phrictionSlug = $slug; return $this; } }