vendor/zircote/swagger-php/src/Analysis.php line 269

Open in your IDE?
  1. <?php
  2. /**
  3.  * @license Apache 2.0
  4.  */
  5. namespace Swagger;
  6. use Closure;
  7. use Exception;
  8. use SplObjectStorage;
  9. use stdClass;
  10. use Swagger\Annotations\AbstractAnnotation;
  11. use Swagger\Annotations\Swagger;
  12. use Swagger\Processors\AugmentDefinitions;
  13. use Swagger\Processors\AugmentOperations;
  14. use Swagger\Processors\AugmentParameters;
  15. use Swagger\Processors\AugmentProperties;
  16. use Swagger\Processors\BuildPaths;
  17. use Swagger\Processors\CleanUnmerged;
  18. use Swagger\Processors\HandleReferences;
  19. use Swagger\Processors\InheritProperties;
  20. use Swagger\Processors\MergeIntoSwagger;
  21. /**
  22.  * Result of the analyser which pretends to be an array of annotations, but also contains detected classes and helper functions for the processors.
  23.  */
  24. class Analysis
  25. {
  26.     /**
  27.      * @var SplObjectStorage
  28.      */
  29.     public $annotations;
  30.     /**
  31.      * Class definitions
  32.      * @var array
  33.      */
  34.     public $classes = [];
  35.     /**
  36.      * The target Swagger annotation.
  37.      * @var Swagger
  38.      */
  39.     public $swagger;
  40.     /**
  41.      * Registry for the post-processing operations.
  42.      * @var Closure[]
  43.      */
  44.     private static $processors;
  45.     /**
  46.      * @param array $annotations
  47.      * @param null  $context
  48.      */
  49.     public function __construct($annotations = [], $context null)
  50.     {
  51.         $this->annotations = new SplObjectStorage();
  52.         if (count($annotations) !== 0) {
  53.             if ($context === null) {
  54.                 $context Context::detect(1);
  55.             }
  56.             $this->addAnnotations($annotations$context);
  57.         }
  58.     }
  59.     /**
  60.      * @param AbstractAnnotation $annotation
  61.      * @param Context $context
  62.      */
  63.     public function addAnnotation($annotation$context)
  64.     {
  65.         if ($this->annotations->contains($annotation)) {
  66.             return;
  67.         }
  68.         if ($annotation instanceof AbstractAnnotation) {
  69.             $context $annotation->_context;
  70.         } else {
  71.             if ($context->is('annotations') === false) {
  72.                 $context->annotations = [];
  73.             }
  74.             if (in_array($annotation$context->annotationstrue) === false) {
  75.                 $context->annotations[] = $annotation;
  76.             }
  77.         }
  78.         $this->annotations->attach($annotation$context);
  79.         $blacklist property_exists($annotation'_blacklist') ? $annotation::$_blacklist : [];
  80.         foreach ($annotation as $property => $value) {
  81.             if (in_array($property$blacklist)) {
  82.                 if ($property === '_unmerged') {
  83.                     foreach ($value as $item) {
  84.                         $this->addAnnotation($item$context);
  85.                     }
  86.                 }
  87.                 continue;
  88.             } elseif (is_array($value)) {
  89.                 foreach ($value as $item) {
  90.                     if ($item instanceof AbstractAnnotation) {
  91.                         $this->addAnnotation($item$context);
  92.                     }
  93.                 }
  94.             } elseif ($value instanceof AbstractAnnotation) {
  95.                 $this->addAnnotation($value$context);
  96.             }
  97.         }
  98.     }
  99.     /**
  100.      * @param array $annotations
  101.      * @param Context $context
  102.      */
  103.     public function addAnnotations($annotations$context)
  104.     {
  105.         foreach ($annotations as $annotation) {
  106.             $this->addAnnotation($annotation$context);
  107.         }
  108.     }
  109.     /**
  110.      * @param array $definition
  111.      */
  112.     public function addClassDefinition($definition)
  113.     {
  114.         $class $definition['context']->fullyQualifiedName($definition['class']);
  115.         $this->classes[$class] = $definition;
  116.     }
  117.     /**
  118.      * @param Analysis $analysis
  119.      */
  120.     public function addAnalysis($analysis)
  121.     {
  122.         foreach ($analysis->annotations as $annotation) {
  123.             $this->addAnnotation($annotation$analysis->annotations[$annotation]);
  124.         }
  125.         $this->classes array_merge($this->classes$analysis->classes);
  126.         if ($this->swagger === null && $analysis->swagger) {
  127.             $this->swagger $analysis->swagger;
  128.             $analysis->target->_context->analysis $this;
  129.         }
  130.     }
  131.     public function getSubClasses($class)
  132.     {
  133.         $definitions = [];
  134.         foreach ($this->classes as $subclass => $definition) {
  135.             if ($definition['extends'] === $class) {
  136.                 $definitions[$subclass] = $definition;
  137.                 $definitions array_merge($definitions$this->getSubClasses($subclass));
  138.             }
  139.         }
  140.         return $definitions;
  141.     }
  142.     public function getSuperClasses($class)
  143.     {
  144.         $classDefinition = isset($this->classes[$class]) ? $this->classes[$class] : null;
  145.         if (!$classDefinition || empty($classDefinition['extends'])) { // unknown class, or no inheritance?
  146.             return [];
  147.         }
  148.         $extends $classDefinition['extends'];
  149.         $extendsDefinition = isset($this->classes[$extends]) ? $this->classes[$extends] : null;
  150.         if (!$extendsDefinition) {
  151.             return [];
  152.         }
  153.         $definitions array_merge([$extends => $extendsDefinition], $this->getSuperClasses($extends));
  154.         return $definitions;
  155.     }
  156.     /**
  157.      *
  158.      * @param string $class
  159.      * @param boolean $strict Innon-strict mode childclasses are also detected.
  160.      * @return array
  161.      */
  162.     public function getAnnotationsOfType($class$strict false)
  163.     {
  164.         $annotations = [];
  165.         if ($strict) {
  166.             foreach ($this->annotations as $annotation) {
  167.                 if (get_class($annotation) === $class) {
  168.                     $annotations[] = $annotation;
  169.                 }
  170.             }
  171.         } else {
  172.             foreach ($this->annotations as $annotation) {
  173.                 if ($annotation instanceof $class) {
  174.                     $annotations[] = $annotation;
  175.                 }
  176.             }
  177.         }
  178.         return $annotations;
  179.     }
  180.     /**
  181.      *
  182.      * @param object $annotation
  183.      * @return \Swagger\Context
  184.      */
  185.     public function getContext($annotation)
  186.     {
  187.         if ($annotation instanceof AbstractAnnotation) {
  188.             return $annotation->_context;
  189.         }
  190.         if ($this->annotations->contains($annotation) === false) {
  191.             throw new Exception('Annotation not found');
  192.         }
  193.         $context $this->annotations[$annotation];
  194.         if ($context instanceof Context) {
  195.             return $context;
  196.         }
  197.         var_dump($context);
  198.         ob_flush();
  199.         die;
  200.         throw new Exception('Annotation has no context'); // Weird, did you use the addAnnotation/addAnnotations methods?
  201.     }
  202.     /**
  203.      * Build an analysis with only the annotations that are merged into the swagger annotation.
  204.      *
  205.      * @return Analysis
  206.      */
  207.     public function merged()
  208.     {
  209.         if (!$this->swagger) {
  210.             throw new Exception('No swagger target set. Run the MergeIntoSwagger processor');
  211.         }
  212.         $unmerged $this->swagger->_unmerged;
  213.         $this->swagger->_unmerged = [];
  214.         $analysis = new Analysis([$this->swagger]);
  215.         $this->swagger->_unmerged $unmerged;
  216.         return $analysis;
  217.     }
  218.     /**
  219.      * Analysis with only the annotations that not merged.
  220.      *
  221.      * @return Analysis
  222.      */
  223.     public function unmerged()
  224.     {
  225.         return $this->split()->unmerged;
  226.     }
  227.     /**
  228.      * Split the annotation into two analysis.
  229.      * One with annotations that are merged and one with annotations that are not merged.
  230.      *
  231.      * @return object {merged: Analysis, unmerged: Analysis}
  232.      */
  233.     public function split()
  234.     {
  235.         $result = new stdClass();
  236.         $result->merged $this->merged();
  237.         $result->unmerged = new Analysis();
  238.         foreach ($this->annotations as $annotation) {
  239.             if ($result->merged->annotations->contains($annotation) === false) {
  240.                 $result->unmerged->annotations->attach($annotation$this->annotations[$annotation]);
  241.             }
  242.         }
  243.         return $result;
  244.     }
  245.     /**
  246.      * Apply the processor(s)
  247.      * @param Closure|Closure[] $processors One or more processors
  248.      */
  249.     public function process($processors null)
  250.     {
  251.         if ($processors === null) { // Use the default and registered processors.
  252.             $processors self::processors();
  253.         }
  254.         if (is_array($processors) === false && is_callable($processors)) {
  255.             $processors = [$processors];
  256.         }
  257.         foreach ($processors as $processor) {
  258.             $processor($this);
  259.         }
  260.     }
  261.     /**
  262.      * Get direct access to the processors array.
  263.      * @return array reference
  264.      */
  265.     public static function &processors()
  266.     {
  267.         if (!self::$processors) {
  268.             // Add default processors.
  269.             self::$processors = [
  270.                 new MergeIntoSwagger(),
  271.                 new BuildPaths(),
  272.                 new HandleReferences(),
  273.                 new AugmentDefinitions(),
  274.                 new AugmentProperties(),
  275.                 new InheritProperties(),
  276.                 new AugmentOperations(),
  277.                 new AugmentParameters(),
  278.                 new CleanUnmerged(),
  279.             ];
  280.         }
  281.         return self::$processors;
  282.     }
  283.     /**
  284.      * Register a processor
  285.      * @param Closure $processor
  286.      */
  287.     public static function registerProcessor($processor)
  288.     {
  289.         array_push(self::processors(), $processor);
  290.     }
  291.     /**
  292.      * Unregister a processor
  293.      * @param Closure $processor
  294.      */
  295.     public static function unregisterProcessor($processor)
  296.     {
  297.         $processors = &self::processors();
  298.         $key array_search($processor$processorstrue);
  299.         if ($key === false) {
  300.             throw new Exception('Given processor was not registered');
  301.         }
  302.         unset($processors[$key]);
  303.     }
  304.     public function validate()
  305.     {
  306.         if ($this->swagger) {
  307.             return $this->swagger->validate();
  308.         }
  309.         Logger::notice('No swagger target set. Run the MergeIntoSwagger processor before validate()');
  310.         return false;
  311.     }
  312. }