Esempio n. 1
0
 /**
 * Extends PHP glob with recursion and base path (files only)
 * 
 * @param  string|array $paths           Paths to find files (base paths). 
 *                                       Default = system current directory.
 * @param  string|array $filePatterns    RegExp patterns to filter files (to find files). 
 *                                       Default = "" - all files.
 * @param  string|array $excludePatterns RegExp patterns to filter files (to ignore files). 
 *                                       Default = NULL - no files to exclusion.
 * @param  boolean      $recursive       =TRUE - find files in sub directories. 
 *                                       Default = TRUE.
 * @return array                         A hash array of found files. Hash structure:
 * @code
 *  array( 
 *      "/absolute/file/name1" => "/base/path" 
 *      "/absolute/file/name2" => "/base/path" 
 *      ...
 * )
 * @endcode
 * 
 * Exapmle:
 * @code
  
   print_r( Files::globFiles('/base/path/', '\.php$') );
 
   //-------- 
   // Return:
  
   Array (
        '/base/path/file1.php'                                  => '/base/path',
        '/base/path/file2.php'                                  => '/base/path',
        '/base/path/folder1/file1_in_folder1.php'               => '/base/path',
        '/base/path/folder1/file2_in_folder1.php'               => '/base/path',
        '/base/path/folder1/subfolder1/file1_in_subfolder1.php' => '/base/path',
   )
 
 * @endcode
 */
 public static function globFiles($paths = array(''), $filePatterns = array(''), $excludePatterns = NULL, $recursive = true)
 {
     //--- Convert $paths to array:
     if (!is_array($paths)) {
         $paths = array($paths);
     }
     //--- Convert $filePatterns to array:
     if (!is_array($filePatterns)) {
         $filePatterns = array($filePatterns);
     }
     //--- Convert $excludePatterns to array:
     if ($excludePatterns && !is_array($excludePatterns)) {
         $excludePatterns = array($excludePatterns);
     }
     //--- Get all source paths:
     $sourcePaths = array();
     foreach ($paths as $sourcePath) {
         $sourcePath = realpath($sourcePath);
         $sourcePaths[$sourcePath] = $sourcePath;
         if ($sourcePath && is_array($out = self::glob($sourcePath, "*", GLOB_ONLYDIR, $recursive))) {
             foreach ($out as $path) {
                 $sourcePaths[$path] = $sourcePath;
             }
         }
     }
     //--- Get all source files and filter it:
     foreach ($sourcePaths as $path => $base) {
         if (is_array($files = self::glob($path))) {
             foreach ($files as $file) {
                 if (!is_file($file)) {
                     continue;
                 }
                 $name = basename($file);
                 if (Basic::inPatterns($name, $filePatterns) && !Basic::inPatterns($name, $excludePatterns)) {
                     $outSources[$file] = $base;
                 }
             }
         }
     }
     return $outSources;
 }
Esempio n. 2
0
 /**
  * To find all methods of class into a source code of a given class
  * 
  * @param  string $data Text data contains a class source code.
  * @return <i>array</i> Array structure: 
  * ~~~
  * array( 
  *      "method1" => array(
  *                      "type"   => static | abstract | "", 
  *                      "scope"  => private | protected | private , 
  *                      "params" => "parameters of methods"
  *                         )
  *      "method2" => array( ... ), 
  *      ...
  *  )
  * ~~~
  */
 public static function getClassMethods($data)
 {
     if (preg_match_all('/^\\s*([\\w\\s]*)\\s*function\\s+([\\w_]+)\\s*\\(([^\\{]*)\\)[^\\{\\)]*\\{/ms', $data, $m)) {
         foreach ($m[1] as $i => $value) {
             $methodProp = $m[1][$i];
             $methodScop = Basic::inPatterns($methodProp, array("public", "protected", "private"), true);
             if (!$methodScop) {
                 $methodScop = "public";
             }
             $methodType = Basic::inPatterns($methodProp, array("abstract"), true);
             if (!$methodType) {
                 $methodType = Basic::inPatterns($methodProp, array("static"), true);
             }
             $methodName = $m[2][$i];
             $methodPara = $m[3][$i];
             $methods[$methodName] = array("scope" => $methodScop, "type" => $methodType, "params" => $methodPara);
         }
     }
     return $methods;
 }
Esempio n. 3
0
 /**
  * Generate code with PHPUnit tests for classes and functions of source code
  * 
  * @param  string $sourceCode     PHP-file source code.
  * @param  string $sourceFileName (Option) needed to create "require" directive.
  * @param  string $resultFileName (Option) needed to create class name for stanalong functions and to create "require" directive with relative path.
  * @param  string $currentContent (Option) needed to insert result code inside an existing content.
  * @return string                 Result code of PHP-file contains tests.
  */
 public function generateCode($sourceCode, $sourceFileName = "", $resultFileName = "NonameClass", $currentContent = NULL)
 {
     //--- Prepare excludeNames Array:
     if ($this->excludeNames && !is_array($this->excludeNames)) {
         $this->excludeNames = array($this->excludeNames);
     }
     //--- Create class name for functions:
     $baseClassName = preg_replace("/\\..*\$/", "", basename($resultFileName));
     //--- Create source code structure:
     $codeStructure = SimpleCodeParser::parseCode($sourceCode);
     //--- Create out structure for tests:
     foreach ($codeStructure as $nameSpace => $body) {
         //--- Create Namespaces:
         if ($nameSpace) {
             $useNameSpaces[] = $nameSpace;
             $nameSpacePrefix = basename(str_replace("\\", "/", $nameSpace)) . "\\";
             $nameSpaceFull = $nameSpace . "\\";
         } else {
             $nameSpacePrefix = "";
             $nameSpaceFull = "";
         }
         //--- Create Tests for Classes:
         if (is_array($body["classes"])) {
             foreach ($body["classes"] as $className => $methods) {
                 $sourceClassList[] = "   class: " . $nameSpaceFull . $className;
                 $testClassName = Basic::replace($this->testClassName, array("NAME" => $className));
                 $testClassMap[$testClassName] = $nameSpaceFull . $className;
                 if (is_array($methods)) {
                     foreach ($methods as $methodName => $params) {
                         if (($params["scope"] == "" || $params["scope"] == "public") && !Basic::inPatterns($methodName, $this->excludeNames)) {
                             $add = false;
                             if ($params["type"] == "static") {
                                 $name = "static method: " . $nameSpaceFull . "{$className}::{$methodName}";
                                 $create = "";
                                 $instance = $nameSpacePrefix . "{$className}::{$methodName}(" . $this->stripFunctionParams($params["params"]) . ")";
                                 $add = true;
                             } elseif ($params["type"] == "") {
                                 $name = "method: " . $nameSpaceFull . "{$className}->{$methodName}";
                                 $create = "\$c = new " . $nameSpacePrefix . "{$className}();";
                                 $instance = "\$c->{$methodName}(" . $this->stripFunctionParams($params["params"]) . ")";
                                 $add = true;
                             }
                             if (!$add) {
                                 continue;
                             }
                             //--- Add Tests to outStructure:
                             $testName = Basic::replace($this->testName, array("NAME" => $methodName));
                             $outStructure[$testClassName][$testName] = Basic::replace($this->templateTest, array("NAME" => $name, "TEST_NAME" => $testName, "CREATE" => $create, "INSTANCE" => $instance));
                         }
                     }
                 }
             }
         }
         //--- Create Tests for functions:
         if (is_array($body["functions"])) {
             foreach ($body["functions"] as $functionName => $params) {
                 if (Basic::inPatterns($functionName, $this->excludeNames)) {
                     continue;
                 }
                 $name = "function: " . $nameSpaceFull . $functionName;
                 $sourceClassList[] = $name;
                 //--- Add Tests to outStructure:
                 $testClassName = $baseClassName;
                 $testName = Basic::replace($this->testName, array("NAME" => $functionName));
                 $outStructure[$testClassName][$testName] = Basic::replace($this->templateTest, array("NAME" => $name, "TEST_NAME" => $testName, "CREATE" => "", "INSTANCE" => $nameSpacePrefix . "{$functionName}(" . $this->stripFunctionParams($params) . ")"));
             }
         }
     }
     //--- If outStructure is empty - break:
     if (!$outStructure) {
         return false;
     }
     //--- Get existing result code structure (if it was saved earlier):
     $existingStructure = SimpleCodeParser::parseCode($currentContent);
     //--- Generate new result code:
     $resultCode = $currentContent;
     //--- Add Header:
     if ($resultCode == "") {
         $resultCode = Basic::replace($this->templateHeader, array("DATE" => date("Y.m.d H:i"), "GENERATOR_NAME" => get_class()));
     }
     //--- Add some comments:
     if (is_array($sourceClassList)) {
         sort($sourceClassList);
         $sourceClassList = implode("\n *      ", $sourceClassList);
     }
     $comments = Basic::replace($this->templateComments, array("SOURCE_FILE" => basename($sourceFileName), "CLASS_LIST" => $sourceClassList));
     $resultCode = preg_replace('/( \\*=+\\n)([^=]*?)( \\*\\/)/ms', '\\1' . $comments . '\\3', $resultCode);
     //--- Add testNameSpace:
     if ($this->testNameSpace) {
         $testNameSpace = "\n\n" . "namespace " . $this->testNameSpace . ";\n";
         $regExpPattern = '^\\s*namespace\\s+' . preg_quote($this->testNameSpace, "/") . '\\s*;';
         $resultCode = self::placeAfter($resultCode, $testNameSpace, $regExpPattern);
     }
     //--- Add "USE" directive:
     if (is_array($useNameSpaces)) {
         foreach ($useNameSpaces as $nameSpace) {
             $useNameSpaceString = "\n\n" . "use {$nameSpace};";
             $regExpPattern = '^\\s*use\\s+' . preg_quote($nameSpace, "/") . '\\s*;';
             $resultCode = self::placeAfter($resultCode, $useNameSpaceString, $regExpPattern, array('^\\s*(require|require_once)\\s+[^;]+;', '^\\s*namespace\\s+[^;]+;', '^\\s*<\\?php'));
         }
     }
     //--- Add "REQUIRE" directive:
     if ($sourceFileName) {
         $includeSourceFileName = $sourceFileName;
         if ($this->includeRelativePath) {
             $relativeSourcePath = Files::getRelativePath(dirname($includeSourceFileName), dirname($resultFileName));
             $includeSourceFileName = $relativeSourcePath["relative"] . "/" . basename($includeSourceFileName);
             $require = "\n\n" . "require_once __DIR__ . '{$includeSourceFileName}';";
         } else {
             $require = "\n\n" . "require_once '{$includeSourceFileName}';";
         }
         $regExpPattern = "^\\s*(require|require_once)\\s+[^;]*\\(?\\s*['\"]+" . preg_quote($includeSourceFileName, "/") . "['\"]+\\s*\\)?\\s*;";
         $resultCode = self::placeAfter($resultCode, $require, $regExpPattern, array('^\\s*namespace\\s+[^;]+;', '^\\s*<\\?php'));
     }
     //--- Add "REQUIRE AUTOLOADER" directive:
     if ($this->includeAutoloaderFileName) {
         $includeAutoloaderFileName = realpath($this->includeAutoloaderFileName);
         if (!$includeAutoloaderFileName) {
             throw new Exception('Autoloader not found : [' . $this->includeAutoloaderFileName . ']');
         }
         $relativeSourcePath = Files::getRelativePath(dirname($includeAutoloaderFileName), dirname($resultFileName));
         $includeAutoloaderFileName = $relativeSourcePath["relative"] . "/" . basename($includeAutoloaderFileName);
         $require = "\n\n" . "require_once __DIR__ . '{$includeAutoloaderFileName}';";
         $regExpPattern = "^\\s*(require|require_once)\\s+[^;]*\\(?\\s*['\"]+" . preg_quote($includeAutoloaderFileName, "/") . "['\"]+\\s*\\)?\\s*;";
         $resultCode = self::placeAfter($resultCode, $require, $regExpPattern, array('^\\s*namespace\\s+[^;]+;', '^\\s*<\\?php'));
     }
     //--- Add file body:
     if (is_array($outStructure)) {
         //--- Add classes
         foreach ($outStructure as $className => $methods) {
             if (is_array($existingStructure[$this->testNameSpace]["classes"]) && array_key_exists($className, $existingStructure[$this->testNameSpace]["classes"])) {
                 continue;
             }
             $resultCode .= Basic::replace($this->templateClass, array("CLASS_NAME" => $testClassMap[$className], "TEST_CLASS_NAME" => $className));
         }
         //--- Add methods
         foreach ($outStructure as $className => $methods) {
             $classBody = "";
             foreach ($methods as $methodName => $methodBody) {
                 if (is_array($existingStructure[$this->testNameSpace]["classes"][$className]) && array_key_exists($methodName, $existingStructure[$this->testNameSpace]["classes"][$className])) {
                     continue;
                 }
                 $classBody .= $methodBody;
             }
             if (preg_match('/^\\s*class\\s+' . preg_quote($className, "/") . '\\s+([^\\{]*)/ms', $resultCode, $m, PREG_OFFSET_CAPTURE)) {
                 list($startPosition, $endPosition) = SimpleCodeParser::getFirstBraceBlockPos(substr($resultCode, $m[0][1]));
                 $endPosition += $m[0][1];
                 $resultCode = substr($resultCode, 0, $endPosition) . $classBody . substr($resultCode, $endPosition);
             }
         }
     }
     //--- Change Update time in header ---
     $resultCode = preg_replace("/Updated on : \\d\\d\\d\\d\\.\\d\\d\\.\\d\\d \\d\\d:\\d\\d/", 'Updated on : ' . date("Y.m.d H:i"), $resultCode);
     //------------------------------------
     //print_r($resultCode); exit;
     return $resultCode;
 }