Path: blob/master/src/applications/diviner/atom/DivinerAtom.php
12256 views
<?php12final class DivinerAtom extends Phobject {34const TYPE_ARTICLE = 'article';5const TYPE_CLASS = 'class';6const TYPE_FILE = 'file';7const TYPE_FUNCTION = 'function';8const TYPE_INTERFACE = 'interface';9const TYPE_METHOD = 'method';1011private $type;12private $name;13private $file;14private $line;15private $hash;16private $contentRaw;17private $length;18private $language;19private $docblockRaw;20private $docblockText;21private $docblockMeta;22private $warnings = array();23private $parent;24private $parentHash;25private $children = array();26private $childHashes = array();27private $context;28private $extends = array();29private $links = array();30private $book;31private $properties = array();3233/**34* Returns a sorting key which imposes an unambiguous, stable order on atoms.35*/36public function getSortKey() {37return implode(38"\0",39array(40$this->getBook(),41$this->getType(),42$this->getContext(),43$this->getName(),44$this->getFile(),45sprintf('%08d', $this->getLine()),46));47}4849public function setBook($book) {50$this->book = $book;51return $this;52}5354public function getBook() {55return $this->book;56}5758public function setContext($context) {59$this->context = $context;60return $this;61}6263public function getContext() {64return $this->context;65}6667public static function getAtomSerializationVersion() {68return 2;69}7071public function addWarning($warning) {72$this->warnings[] = $warning;73return $this;74}7576public function getWarnings() {77return $this->warnings;78}7980public function setDocblockRaw($docblock_raw) {81$this->docblockRaw = $docblock_raw;8283if ($docblock_raw !== null) {84$parser = new PhutilDocblockParser();85list($text, $meta) = $parser->parse($docblock_raw);86$this->docblockText = $text;87$this->docblockMeta = $meta;88} else {89$this->docblockText = null;90$this->docblockMeta = null;91}9293return $this;94}9596public function getDocblockRaw() {97return $this->docblockRaw;98}99100public function getDocblockText() {101if ($this->docblockText === null) {102throw new PhutilInvalidStateException('setDocblockRaw');103}104return $this->docblockText;105}106107public function getDocblockMeta() {108if ($this->docblockMeta === null) {109throw new PhutilInvalidStateException('setDocblockRaw');110}111return $this->docblockMeta;112}113114public function getDocblockMetaValue($key, $default = null) {115$meta = $this->getDocblockMeta();116return idx($meta, $key, $default);117}118119public function setDocblockMetaValue($key, $value) {120$meta = $this->getDocblockMeta();121$meta[$key] = $value;122$this->docblockMeta = $meta;123return $this;124}125126public function setType($type) {127$this->type = $type;128return $this;129}130131public function getType() {132return $this->type;133}134135public function setName($name) {136$this->name = $name;137return $this;138}139140public function getName() {141return $this->name;142}143144public function setFile($file) {145$this->file = $file;146return $this;147}148149public function getFile() {150return $this->file;151}152153public function setLine($line) {154$this->line = $line;155return $this;156}157158public function getLine() {159return $this->line;160}161162public function setContentRaw($content_raw) {163$this->contentRaw = $content_raw;164return $this;165}166167public function getContentRaw() {168return $this->contentRaw;169}170171public function setHash($hash) {172$this->hash = $hash;173return $this;174}175176public function addLink(DivinerAtomRef $ref) {177$this->links[] = $ref;178return $this;179}180181public function addExtends(DivinerAtomRef $ref) {182$this->extends[] = $ref;183return $this;184}185186public function getLinkDictionaries() {187return mpull($this->links, 'toDictionary');188}189190public function getExtendsDictionaries() {191return mpull($this->extends, 'toDictionary');192}193194public function getExtends() {195return $this->extends;196}197198public function getHash() {199if ($this->hash) {200return $this->hash;201}202203$parts = array(204$this->getBook(),205$this->getType(),206$this->getName(),207$this->getFile(),208$this->getLine(),209$this->getLength(),210$this->getLanguage(),211$this->getContentRaw(),212$this->getDocblockRaw(),213$this->getProperties(),214$this->getChildHashes(),215mpull($this->extends, 'toHash'),216mpull($this->links, 'toHash'),217);218219$this->hash = md5(serialize($parts)).'N';220return $this->hash;221}222223public function setLength($length) {224$this->length = $length;225return $this;226}227228public function getLength() {229return $this->length;230}231232public function setLanguage($language) {233$this->language = $language;234return $this;235}236237public function getLanguage() {238return $this->language;239}240241public function addChildHash($child_hash) {242$this->childHashes[] = $child_hash;243return $this;244}245246public function getChildHashes() {247if (!$this->childHashes && $this->children) {248$this->childHashes = mpull($this->children, 'getHash');249}250return $this->childHashes;251}252253public function setParentHash($parent_hash) {254if ($this->parentHash) {255throw new Exception(pht('Atom already has a parent!'));256}257$this->parentHash = $parent_hash;258return $this;259}260261public function hasParent() {262return $this->parent || $this->parentHash;263}264265public function setParent(DivinerAtom $atom) {266if ($this->parentHash) {267throw new Exception(pht('Parent hash has already been computed!'));268}269$this->parent = $atom;270return $this;271}272273public function getParentHash() {274if ($this->parent && !$this->parentHash) {275$this->parentHash = $this->parent->getHash();276}277return $this->parentHash;278}279280public function addChild(DivinerAtom $atom) {281if ($this->childHashes) {282throw new Exception(pht('Child hashes have already been computed!'));283}284285$atom->setParent($this);286$this->children[] = $atom;287return $this;288}289290public function getURI() {291$parts = array();292$parts[] = phutil_escape_uri_path_component($this->getType());293if ($this->getContext()) {294$parts[] = phutil_escape_uri_path_component($this->getContext());295}296$parts[] = phutil_escape_uri_path_component($this->getName());297$parts[] = null;298return implode('/', $parts);299}300301public function toDictionary() {302// NOTE: If you change this format, bump the format version in303// @{method:getAtomSerializationVersion}.304return array(305'book' => $this->getBook(),306'type' => $this->getType(),307'name' => $this->getName(),308'file' => $this->getFile(),309'line' => $this->getLine(),310'hash' => $this->getHash(),311'uri' => $this->getURI(),312'length' => $this->getLength(),313'context' => $this->getContext(),314'language' => $this->getLanguage(),315'docblockRaw' => $this->getDocblockRaw(),316'warnings' => $this->getWarnings(),317'parentHash' => $this->getParentHash(),318'childHashes' => $this->getChildHashes(),319'extends' => $this->getExtendsDictionaries(),320'links' => $this->getLinkDictionaries(),321'ref' => $this->getRef()->toDictionary(),322'properties' => $this->getProperties(),323);324}325326public function getRef() {327$title = null;328if ($this->docblockMeta) {329$title = $this->getDocblockMetaValue('title');330}331332return id(new DivinerAtomRef())333->setBook($this->getBook())334->setContext($this->getContext())335->setType($this->getType())336->setName($this->getName())337->setTitle($title)338->setGroup($this->getProperty('group'));339}340341public static function newFromDictionary(array $dictionary) {342$atom = id(new DivinerAtom())343->setBook(idx($dictionary, 'book'))344->setType(idx($dictionary, 'type'))345->setName(idx($dictionary, 'name'))346->setFile(idx($dictionary, 'file'))347->setLine(idx($dictionary, 'line'))348->setHash(idx($dictionary, 'hash'))349->setLength(idx($dictionary, 'length'))350->setContext(idx($dictionary, 'context'))351->setLanguage(idx($dictionary, 'language'))352->setParentHash(idx($dictionary, 'parentHash'))353->setDocblockRaw(idx($dictionary, 'docblockRaw'))354->setProperties(idx($dictionary, 'properties'));355356foreach (idx($dictionary, 'warnings', array()) as $warning) {357$atom->addWarning($warning);358}359360foreach (idx($dictionary, 'childHashes', array()) as $child) {361$atom->addChildHash($child);362}363364foreach (idx($dictionary, 'extends', array()) as $extends) {365$atom->addExtends(DivinerAtomRef::newFromDictionary($extends));366}367368return $atom;369}370371public function getProperty($key, $default = null) {372return idx($this->properties, $key, $default);373}374375public function setProperty($key, $value) {376$this->properties[$key] = $value;377return $this;378}379380public function getProperties() {381return $this->properties;382}383384public function setProperties(array $properties) {385$this->properties = $properties;386return $this;387}388389public static function getThisAtomIsNotDocumentedString($type) {390switch ($type) {391case self::TYPE_ARTICLE:392return pht('This article is not documented.');393case self::TYPE_CLASS:394return pht('This class is not documented.');395case self::TYPE_FILE:396return pht('This file is not documented.');397case self::TYPE_FUNCTION:398return pht('This function is not documented.');399case self::TYPE_INTERFACE:400return pht('This interface is not documented.');401case self::TYPE_METHOD:402return pht('This method is not documented.');403default:404phlog(pht("Need translation for '%s'.", $type));405return pht('This %s is not documented.', $type);406}407}408409public static function getAllTypes() {410return array(411self::TYPE_ARTICLE,412self::TYPE_CLASS,413self::TYPE_FILE,414self::TYPE_FUNCTION,415self::TYPE_INTERFACE,416self::TYPE_METHOD,417);418}419420public static function getAtomTypeNameString($type) {421switch ($type) {422case self::TYPE_ARTICLE:423return pht('Article');424case self::TYPE_CLASS:425return pht('Class');426case self::TYPE_FILE:427return pht('File');428case self::TYPE_FUNCTION:429return pht('Function');430case self::TYPE_INTERFACE:431return pht('Interface');432case self::TYPE_METHOD:433return pht('Method');434default:435phlog(pht("Need translation for '%s'.", $type));436return ucwords($type);437}438}439440}441442443