Пример #1
0
 public function put($file, $content)
 {
     $dir_name = dirname($file);
     if ($dir_name != "." && !is_dir($this->ze->build_dir . '/' . $dir_name)) {
         mkdir($this->ze->build_dir . '/' . $dir_name, 0755, true);
     }
     FS::put($this->ze->build_dir . '/' . $file, $content);
 }
Пример #2
0
 /**
  * Create project from Composer
  * @param string $path path to project root
  * @return Project
  */
 public static function composer($path)
 {
     $path = realpath($path);
     chdir($path);
     $composer = json_decode(FS::get($path . "/composer.json"), true);
     require_once $path . '/vendor/autoload.php';
     $project = new self($composer["name"]);
     $project->setRootDir($path);
     list($vendor, $name) = explode("/", $project->name);
     if ($vendor == $name) {
         $project->alias = ucfirst($name);
         $project->code = strtolower($name);
     } else {
         $project->alias = ucfirst($vendor) . ucfirst($name);
         $project->code = strtolower($vendor) . "_" . strtolower($name);
     }
     $project->description = $composer["description"];
     if (isset($composer["config"]["koda"]["version"])) {
         $ver = $composer["config"]["koda"]["version"];
         if (is_callable($ver)) {
             $project->version = call_user_func($ver);
         } else {
             $project->version = exec($ver);
         }
     }
     $paths = [];
     foreach ($composer["autoload"] as $loader) {
         $paths = array_merge($paths, array_values($loader));
     }
     foreach ($composer["require"] as $require => $version) {
         if (strpos($require, "ext-") === 0) {
             $project->addDepends(substr($require, 4))->setRequired();
         }
     }
     foreach ($composer["suggest"] as $suggest => $comment) {
         if (strpos($suggest, "ext-") === 0) {
             $project->addDepends(substr($suggest, 4))->setOptional();
         }
     }
     foreach ($paths as $dir) {
         $dir = realpath($dir);
         if (is_file($dir)) {
             $project->files[$dir] = new EntityFile($dir, $project);
         } else {
             $iter = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
             foreach ($iter as $file) {
                 /* @var \splFileInfo $file */
                 if ($file->isFile() && strtolower($file->getExtension()) == "php") {
                     $project->files[$file->getRealPath()] = new EntityFile($file->getRealPath(), $project);
                 }
             }
         }
     }
     return $project;
 }
Пример #3
0
 public function process(Project $project)
 {
     if ($project->classes) {
         if (!file_exists("{$this->dir}/classes")) {
             if (!mkdir("{$this->dir}/classes", 0755, true)) {
                 throw new \RuntimeException("Could not create directory {$this->dir}/classes for mdocs");
             }
         }
         foreach ($project->classes as $class) {
             $doc = [];
             $doc["header"] = Flags::decode($class->flags & Flags::CLASS_TYPES) . " " . $class->name;
             $doc[] = str_pad("", strlen($doc["header"]), "=");
             $doc[] = "";
             if ($class->parent) {
                 $doc[] = "Parent: [" . $class->parent->name . "](#xxx)";
             }
             if ($class->interfaces) {
                 $doc[] = "Interfaces: " . implode(", ", array_keys($class->interfaces));
             }
             if ($class->traits) {
                 $doc[] = "Traits: " . implode(", ", array_keys($class->traits));
             }
             $doc[] = $class->description;
             if ($class->constants) {
                 $doc[] = "";
                 $doc[] = "## Constants";
                 foreach ($class->constants as $constant) {
                     $doc[] = "**{$constant->short}** `{$constant->value}`";
                 }
             }
             if ($class->properties) {
                 $doc[] = "";
                 $doc[] = "## Properties";
                 foreach ($class->properties as $property) {
                     $doc[] = "**{$property->name}** `{$property->value}`";
                 }
             }
             if ($class->methods) {
                 $doc[] = "";
                 $doc[] = "## Methods";
                 foreach ($class->methods as $method) {
                     $doc[] = $method->dump() . " {$method->description}";
                 }
             }
             FS::put("{$this->dir}/classes/" . str_replace('\\', '-', $class->name) . '.md', implode("\n", $doc));
         }
     }
 }
Пример #4
0
 public function scan()
 {
     require_once $this->path;
     $ns = "";
     $_ns = "";
     $ns_bracket = false;
     $aliases = [];
     $tokens = new Tokenizer(FS::get($this->path));
     while ($tokens->valid()) {
         if ($tokens->is(T_NAMESPACE)) {
             $ns = "";
             $_ns = "";
             $tokens->next();
             if ($tokens->is(T_STRING)) {
                 $ns = $this->_parseName($tokens);
                 if ($tokens->is('{')) {
                     $tokens->skip();
                     $ns_bracket = true;
                 } else {
                     $tokens->skipIf(';');
                 }
                 $_ns = $ns . '\\';
             } elseif ($tokens->is('{')) {
                 $ns_bracket = true;
                 $tokens->next();
             }
         } elseif ($tokens->is(T_USE)) {
             do {
                 $tokens->next();
                 $name = $this->_parseName($tokens);
                 if ($tokens->is(T_AS)) {
                     $aliases[$tokens->next()->get(T_STRING)] = $name;
                     $tokens->next();
                 } else {
                     if (strpos($name, '\\') === false) {
                         $aliases[$name] = $name;
                     } else {
                         $aliases[ltrim('\\', strrchr($name, '\\'))] = $name;
                     }
                 }
             } while ($tokens->is(','));
             $tokens->need(';')->next();
         } elseif ($tokens->is(T_CONST)) {
             $name = $tokens->next()->get(T_STRING);
             $constant = new EntityConstant($_ns . $name);
             $constant->setValue(constant($_ns . $name));
             $constant->setLine($this->line($tokens->getLine()));
             $this->constants[$_ns . $name] = $constant;
             $tokens->forwardTo(';')->next();
         } elseif ($tokens->is(T_FUNCTION)) {
             $name = $tokens->next()->get(T_STRING);
             $function = new EntityFunction($_ns . $name);
             $function->setLine($this->line($tokens->getLine()));
             $function->setAliases($aliases);
             $this->parseCallable($function, new \ReflectionFunction($function->name));
             $function->setBody($tokens->forwardTo('{')->getScope());
             $tokens->next();
             $this->functions[$function->name] = $function;
         } elseif ($tokens->is(T_FINAL, T_ABSTRACT, T_INTERFACE, T_TRAIT, T_CLASS)) {
             $tokens->forwardTo(T_STRING);
             $name = $tokens->current();
             $class = new EntityClass($_ns . $name);
             $ref = new \ReflectionClass($class->name);
             $doc = $ref->getDocComment();
             //                if($name == "NamesInterface") {
             //                    drop($ref);
             //                }
             if ($ref->isInterface()) {
                 $class->addFlag(Flags::IS_INTERFACE);
             } elseif ($ref->isTrait()) {
                 $class->addFlag(Flags::IS_TRAIT);
             } else {
                 $class->addFlag(Flags::IS_CLASS);
             }
             if ($ref->isAbstract()) {
                 $class->addFlag(Flags::IS_ABSTRACT);
             } elseif ($ref->isFinal()) {
                 $class->addFlag(Flags::IS_FINAL);
             }
             if ($doc) {
                 $info = ToolKit::parseDoc($doc);
                 $class->setDescription($info['desc']);
                 $class->addOptions($info['options']);
             }
             $class->setAliases($aliases);
             $class->setLine($this->line($tokens->getLine()));
             $tokens->next();
             if ($tokens->is(T_EXTENDS)) {
                 // process 'extends' keyword
                 do {
                     $tokens->next();
                     $root = $tokens->is(T_NS_SEPARATOR);
                     $parent = $this->_parseName($tokens);
                     if ($root) {
                         // extends from root namespace
                         $class->setParent($parent, $class->isInterface());
                     } elseif (isset($aliases[$parent])) {
                         $class->setParent($aliases[$parent], $class->isInterface());
                     } else {
                         $class->setParent($_ns . $parent, $class->isInterface());
                     }
                 } while ($tokens->is(','));
             }
             if ($tokens->is(T_IMPLEMENTS)) {
                 // process 'implements' keyword
                 do {
                     $tokens->next();
                     $root = $tokens->is(T_NS_SEPARATOR);
                     $parent = $this->_parseName($tokens);
                     if ($root) {
                         // extends from root namespace
                         $class->addInterface($parent);
                     } elseif (isset($aliases[$parent])) {
                         $class->addInterface($aliases[$parent]);
                     } else {
                         $class->addInterface($_ns . $parent);
                     }
                 } while ($tokens->is(','));
             }
             $tokens->forwardTo('{')->next();
             while ($tokens->forwardTo(T_CONST, T_FUNCTION, '{', '}', T_VARIABLE) && $tokens->valid()) {
                 switch ($tokens->key()) {
                     case T_CONST:
                         $constant = new EntityConstant($class->name . '::' . $tokens->next()->get(T_STRING));
                         $constant->setValue(constant($constant->name));
                         $constant->setLine(new Line($this, $tokens->getLine()));
                         $class->addConstant($constant);
                         break;
                     case T_VARIABLE:
                         $property = new EntityProperty(ltrim($tokens->getAndNext(), '$'));
                         $ref = new \ReflectionProperty($class->name, $property->name);
                         $doc = $ref->getDocComment();
                         if ($doc) {
                             $property->setDescription(ToolKit::parseDoc($doc)['desc']);
                         }
                         if ($ref->isPrivate()) {
                             $property->addFlag(Flags::IS_PRIVATE);
                         } elseif ($ref->isProtected()) {
                             $property->addFlag(Flags::IS_PROTECTED);
                         } else {
                             $property->addFlag(Flags::IS_PUBLIC);
                         }
                         if ($ref->isStatic()) {
                             $property->addFlag(Flags::IS_STATIC);
                         }
                         if ($ref->isDefault()) {
                             $property->setValue($ref->getDeclaringClass()->getDefaultProperties()[$property->name]);
                         }
                         $class->addProperty($property);
                         break;
                     case T_FUNCTION:
                         $method = new EntityMethod($name . '::' . $tokens->next()->get(T_STRING));
                         $method->setLine($this->line($tokens->getLine()));
                         $this->parseCallable($method, $ref = new \ReflectionMethod($class->name, $method->short));
                         if ($ref->isPrivate()) {
                             $method->addFlag(Flags::IS_PRIVATE);
                         } elseif ($ref->isProtected()) {
                             $method->addFlag(Flags::IS_PROTECTED);
                         } else {
                             $method->addFlag(Flags::IS_PUBLIC);
                         }
                         if ($ref->isStatic()) {
                             $method->addFlag(Flags::IS_STATIC);
                         }
                         if ($ref->isAbstract()) {
                             $method->addFlag(Flags::IS_ABSTRACT);
                             $method->addFlag(Flags::IS_ABSTRACT_IMPLICIT);
                         } elseif ($ref->isFinal()) {
                             $method->addFlag(Flags::IS_FINAL);
                         }
                         if (isset($method->options['deprecated'])) {
                             $method->addFlag(Flags::IS_DEPRECATED);
                         }
                         $tokens->forwardTo(')')->next();
                         if ($tokens->is('{')) {
                             $method_body = $tokens->getScope();
                             $method->setBody($method_body);
                         }
                         $tokens->next();
                         $class->addMethod($method);
                         break;
                     case '{':
                         // use traits scope
                         $tokens->forwardTo('}')->next();
                         break;
                     case '}':
                         // end of class
                         $tokens->next();
                         $this->classes[$class->name] = $class;
                         break 2;
                 }
             }
         } elseif ($tokens->is('}') && $ns_bracket) {
             $tokens->next();
             $ns_bracket = false;
         } else {
             drop($tokens->curr);
             if ($tokens->valid()) {
                 throw new UnexpectedTokenException($tokens);
             }
             break;
         }
     }
 }