/** * Build classmap configuration * * @return bool|mixed */ public function buildClassmapConfig($relativePath) { // get needed options to shorten code $directory = $this->requestOptions->getDirectory(); $destination = $this->requestOptions->getDestination(); // Get the ClassFileLocator, and pass it the library path $fileLocator = new ClassFileLocator($directory); // load existing map if (file_exists($destination)) { $classMap = (require $destination); } else { $classMap = array(); } // Iterate over each element in the path, and create a map of // classname => filename, where the filename is relative to // the library path foreach ($fileLocator as $file) { $filename = str_replace($directory . '/', '', str_replace(DIRECTORY_SEPARATOR, '/', $file->getPath()) . '/' . $file->getFilename()); // Add in relative path to library $filename = $relativePath . $filename; foreach ($file->getClasses() as $class) { $classMap[$class] = $filename; } } // check for application config updates if (count($classMap) == 0) { return false; } // loop through class map foreach ($classMap as $class => $file) { $classMap[$class] = '__DIR__ . \'/' . $file . '\''; } return $classMap; }
/** * Update module class with class map autoloading * * @return bool * @throws \Zend\Code\Generator\Exception */ public function updateModuleWithClassmapAutoloader() { // get needed options to shorten code $path = realpath($this->requestOptions->getPath()); $directory = $this->requestOptions->getDirectory(); $destination = $this->requestOptions->getDestination(); $moduleFile = $directory . '/Module.php'; $moduleClass = str_replace($path . '/module/', '', $directory) . '\\Module'; $moduleName = str_replace($path . '/module/', '', $directory); // check for module file if (!file_exists($moduleFile)) { return false; } // get file and class reflection $fileReflection = new FileReflection($moduleFile, true); $classReflection = $fileReflection->getClass($moduleClass); // setup class generator with reflected class $code = ClassGenerator::fromReflection($classReflection); // check for action method if ($code->hasMethod('getAutoloaderConfig')) { $code->removeMethod('getAutoloaderConfig'); } // add getAutoloaderConfig method with class map $code->addMethodFromGenerator($this->generateGetAutoloaderConfigMethod($destination, $moduleName)); // create file with file generator $file = new FileGenerator(); $file->setClass($code); // add optional doc block if ($this->flagCreateApiDocs) { $file->setDocBlock(new DocBlockGenerator('This file was generated by FrilleZFTool.', null, array($this->generatePackageTag($moduleName), $this->generateSeeTag()))); } // create file with file generator $file = new FileGenerator(); $file->setClass($code); // add optional doc block if ($this->flagCreateApiDocs) { $file->setDocBlock(new DocBlockGenerator('This file was generated by FrilleZFTool.', null, array($this->generatePackageTag($moduleName), $this->generateSeeTag()))); } // write module class if (!file_put_contents($moduleFile, $file->generate())) { return false; } return true; }
/** * Generate classmap * * @return ConsoleModel */ public function classmapAction() { // check for help mode if ($this->requestOptions->getFlagHelp()) { return $this->classmapHelp(); } // output header $this->consoleHeader('Generating classmap'); // get needed options to shorten code $directory = $this->requestOptions->getDirectory(); $destination = $this->requestOptions->getDestination(); $relativePath = ''; $usingStdout = false; // check if directory provided if (is_null($directory)) { return $this->sendError(array(array(Color::NORMAL => 'Please provide the directory to create the classmap in'))); } // Validate directory if (!is_dir($directory)) { return $this->sendError(array(array(Color::NORMAL => 'Invalid library directory provided '), array(Color::RED => $directory), array(Color::NORMAL => '.'))); } // check that destination file is not a directory if (is_dir($destination)) { return $this->sendError(array(array(Color::RED => $destination), array(Color::NORMAL => ' is not a valid output file.'))); } // check that destination file is writable if (!is_writeable(dirname($destination))) { return $this->sendError(array(array(Color::NORMAL => 'Cannot write to '), array(Color::RED => $destination), array(Color::NORMAL => '.'))); } // Determine output if ('-' == $destination) { $destination = STDOUT; $usingStdout = true; } else { // We need to add the $libraryPath into the relative path that is created in the classmap file. $classmapPath = str_replace(DIRECTORY_SEPARATOR, '/', realpath(dirname($destination))); // Simple case: $libraryPathCompare is in $classmapPathCompare if (strpos($directory, $classmapPath) === 0) { if ($directory !== $classmapPath) { // prevent double dash in filepaths when using "." as directory $relativePath = substr($directory, strlen($classmapPath) + 1) . '/'; } } else { $libraryPathParts = explode('/', $directory); $classmapPathParts = explode('/', $classmapPath); // Find the common part $count = count($classmapPathParts); for ($i = 0; $i < $count; $i++) { if (!isset($libraryPathParts[$i]) || $libraryPathParts[$i] != $classmapPathParts[$i]) { // Common part end break; } } // Add parent dirs for the subdirs of classmap $relativePath = str_repeat('../', $count - $i); // Add library subdirs $count = count($libraryPathParts); for (; $i < $count; $i++) { $relativePath .= $libraryPathParts[$i] . '/'; } } } // start output if (!$usingStdout) { $this->console->writeLine(' => Scanning for files containing PHP classes '); } // generate new classmap $classMap = $this->moduleConfigurator->buildClassmapConfig($relativePath); // Check if we have found any PHP classes. if (!$classMap) { return $this->sendError(array(array(Color::NORMAL => 'Cannot find any PHP classes in '), array(Color::RED => $directory), array(Color::NORMAL => '.'))); } // continue output if (!$usingStdout) { $this->console->write(' => Found '); $this->console->write(count($classMap), Color::GREEN); $this->console->writeLine(' PHP classes'); $this->console->writeLine(' => Writing classmap'); } // update module configuration $this->moduleGenerator->updateConfiguration($classMap, $destination, true); // update module class with classmap autoloading $updateFlag = $this->moduleGenerator->updateModuleWithClassmapAutoloader(); // continue output if (!$usingStdout) { if ($updateFlag) { $this->console->writeLine(' => Update module class to use classmap for autoloading'); } else { $this->console->writeLine(); $this->console->write(' Warn ', Color::NORMAL, Color::RED); $this->console->write(' '); $this->console->writeLine('=> Could not find a module class in directory to update the autoloading for the new classmap', Color::RED); } } // end output if (!$usingStdout) { $this->console->writeLine(); $this->console->write(' Done ', Color::NORMAL, Color::CYAN); $this->console->write(' '); $this->console->write('Wrote classmap to '); $this->console->writeLine($destination, Color::GREEN); } // output footer $this->consoleFooter('classmap was successfully generated'); }