PageRenderTime 54ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/dev/build/publication/license/Routine.php

https://bitbucket.org/sunil_nextbits/magento2
PHP | 364 lines | 193 code | 40 blank | 131 comment | 25 complexity | a47cdc6d35030bde409036de92c05013 MD5 | raw file
  1. <?php
  2. /**
  3. * {license_notice}
  4. *
  5. * @category build
  6. * @package license
  7. * @copyright {copyright}
  8. * @license {license_link}
  9. */
  10. /**
  11. * Service routines for license-tool command line script
  12. * Routine run time functions
  13. *
  14. */
  15. class Routine
  16. {
  17. /**
  18. * List skipped directories
  19. *
  20. * @var null|array
  21. */
  22. public static $skipDirectories = null;
  23. /**
  24. * List skipped files
  25. *
  26. * @var null|array
  27. */
  28. public static $skipFiles = null;
  29. /**
  30. * Verbose output flag
  31. *
  32. * @var bool
  33. */
  34. public static $isVerbose = false;
  35. /**
  36. * Dry run flag
  37. *
  38. * @var bool
  39. */
  40. public static $dryRun = false;
  41. /**
  42. * File types
  43. *
  44. * @var array
  45. */
  46. public static $fileTypes = array(
  47. 'xml' => array(
  48. '*.xml', '*.xml.template', '*.xml.additional', '*.xml.dist', '*.xml.sample',
  49. '*.xsd', '*.mxml', '*.jmx', '*.jtl',
  50. ),
  51. 'php' => array('*.php', '*.php.dist', '*.php.sample'),
  52. 'phtml' => array('*.phtml'),
  53. 'html' => array('*.html', '*.htm'),
  54. 'css' => array('*.css'),
  55. 'js' => array('*.js'),
  56. 'flex' => array('*.as'),
  57. 'sql' => array('*.sql'),
  58. );
  59. /**
  60. * Length of working directory
  61. *
  62. * @var int
  63. */
  64. protected static $_workingDirLen = 0;
  65. /**
  66. * @var int
  67. */
  68. protected static $_errorsCount = 0;
  69. /**
  70. * @var int
  71. */
  72. protected static $_updatedCount = 0;
  73. /**
  74. * @var int
  75. */
  76. protected static $_skippedCount = 0;
  77. /**
  78. * Walk through all file inside folder and sub folder. Filter found files by pattern.
  79. *
  80. * @static
  81. * @param string|array $paths
  82. * @param string|array $fileMasks
  83. * @param array $result
  84. * @param bool $allowRecursion
  85. * @return null
  86. */
  87. public static function globSearch($paths, $fileMasks, &$result, $allowRecursion = true)
  88. {
  89. if (empty($paths)) {
  90. return;
  91. }
  92. if (!is_array($paths)) {
  93. $paths = array($paths);
  94. }
  95. if (!is_array($fileMasks)) {
  96. $fileMasks = array($fileMasks);
  97. }
  98. foreach ($paths as $resource) {
  99. if (is_file($resource) && !self::_isFileSkipped($resource)) {
  100. $result[] = $resource;
  101. continue;
  102. }
  103. if (self::_isDirectorySkipped($resource)) {
  104. continue;
  105. }
  106. if ($allowRecursion) {
  107. self::globSearch(glob($resource . '/*', GLOB_ONLYDIR), $fileMasks, $result, true);
  108. }
  109. self::_filterFilesByMask($resource, $fileMasks, $result);
  110. }
  111. }
  112. /**
  113. * Filter directory by passed file mask. Results will be saved in $result variable.
  114. *
  115. * @static
  116. * @param $directory
  117. * @param $fileMasks
  118. * @param $result
  119. * @return null
  120. */
  121. protected static function _filterFilesByMask($directory, $fileMasks, &$result)
  122. {
  123. foreach ($fileMasks as $filesMask) {
  124. foreach (glob($directory . '/' . $filesMask) as $filename) {
  125. if (is_file($filename) && !self::_isFileSkipped($filename)) {
  126. $result[] = $filename;
  127. }
  128. }
  129. }
  130. }
  131. /**
  132. * Filters passed array on skip path items marked by "!" sign
  133. *
  134. * @static
  135. * @param string $workingDir
  136. * @param array $list
  137. */
  138. protected static function _setSkippedPaths($workingDir, $list)
  139. {
  140. $paths = array();
  141. foreach ($list as $globPattern) {
  142. $path = $workingDir . DIRECTORY_SEPARATOR . $globPattern;
  143. $subPaths = glob($path, GLOB_BRACE);
  144. if (false === $subPaths) {
  145. throw new Exception("No real paths found by glob pattern: {$path}");
  146. }
  147. $paths = array_merge($paths, $subPaths);
  148. }
  149. $paths = array_unique($paths);
  150. foreach ($paths as $path) {
  151. $real = realpath($path);
  152. if (is_dir($real)) {
  153. self::$skipDirectories[] = $real;
  154. } elseif (is_file($real)) {
  155. self::$skipFiles[] = $real;
  156. }
  157. }
  158. }
  159. /**
  160. * Analyzes passed directory should it be skipped or not.
  161. *
  162. * @static
  163. * @param string $directory
  164. * @return bool
  165. */
  166. protected static function _isDirectorySkipped($directory)
  167. {
  168. $directory = realpath($directory) . DIRECTORY_SEPARATOR;
  169. foreach (self::$skipDirectories as $skipDir) {
  170. if (false !== strpos($directory, $skipDir . DIRECTORY_SEPARATOR)) {
  171. return true;
  172. }
  173. }
  174. return false;
  175. }
  176. /**
  177. * Analyzes passed file should it be skipped or not.
  178. *
  179. * @static
  180. * @param string $filename
  181. * @return bool
  182. */
  183. protected static function _isFileSkipped($filename)
  184. {
  185. return in_array(realpath($filename), self::$skipFiles);
  186. }
  187. /**
  188. * Updates files in passed directory using license rules.
  189. * Could be run as validation process for files in dry run case.
  190. *
  191. * @static
  192. * @param string|array $directories
  193. * @param string|array $fileMasks
  194. * @param AbstractLicense $license
  195. * @param bool $recursive
  196. * @return null
  197. */
  198. public static function updateLicense($directories, $fileMasks, $license, $recursive = true)
  199. {
  200. $foundFiles = array();
  201. self::globSearch($directories, $fileMasks, $foundFiles, $recursive);
  202. foreach ($foundFiles as $filename) {
  203. $path = substr($filename, self::$_workingDirLen + 1);
  204. $contents = file_get_contents($filename);
  205. preg_match('#/\*\*(.*)\*/.*#Us', $contents, $matches);
  206. if (empty($contents) || !isset($matches[1])) {
  207. self::printLog("E {$path}\n");
  208. self::$_errorsCount += 1;
  209. continue;
  210. }
  211. $placeholders = array(
  212. ' * {license_notice}',
  213. '{copyright}',
  214. '{license_link}'
  215. );
  216. $changeset = array(
  217. $license->getNotice(),
  218. $license->getCopyright(),
  219. $license->getLink()
  220. );
  221. $docBlock = str_replace($placeholders, $changeset, $matches[1]);
  222. $newContents = preg_replace('#(/\*\*).*(\*/.*)#Us', '$1'. $docBlock . '$2', $contents, 1);
  223. if ($contents !== $newContents) {
  224. if (!self::$dryRun) {
  225. file_put_contents($filename, $newContents);
  226. }
  227. self::printLog(". {$path}\n");
  228. self::$_updatedCount += 1;
  229. } else {
  230. self::printLog("S {$path}\n");
  231. self::$_skippedCount += 1;
  232. }
  233. }
  234. }
  235. /**
  236. * Prints logging messaged in case verbose mode enabled during run.
  237. *
  238. * @statict
  239. * @param string $msg
  240. * @return null
  241. */
  242. public static function printLog($msg)
  243. {
  244. if (self::$isVerbose) {
  245. echo $msg;
  246. }
  247. }
  248. /**
  249. * Create instance of license class which contains information about license
  250. *
  251. * @static
  252. * @throws Exception
  253. * @param string $license
  254. * @return AbstractLicense
  255. */
  256. public static function createLicenseInstance($license)
  257. {
  258. $licenseClassName = ucfirst(strtolower($license));
  259. if (!class_exists($licenseClassName)) {
  260. $licenseClassFile = dirname(__FILE__) . DIRECTORY_SEPARATOR . $licenseClassName . '.php';
  261. if (!file_exists($licenseClassFile) || !is_readable($licenseClassFile)) {
  262. throw new Exception("Can't access license file: {$licenseClassFile}.\n");
  263. }
  264. include_once $licenseClassFile;
  265. if (!class_exists($licenseClassName)) {
  266. throw new Exception("Can't find license class: {$licenseClassName}.\n");
  267. }
  268. }
  269. $licenseObject = new $licenseClassName;
  270. if (!$licenseObject instanceof LicenseAbstract) {
  271. throw new Exception("License class does not have correct interface: {$licenseClassName}.\n");
  272. }
  273. return $licenseObject;
  274. }
  275. /**
  276. * Entry point of routine work
  277. *
  278. * @static
  279. * @param string $workingDir
  280. * @param array $config
  281. * @param array $blackList
  282. * @return null
  283. */
  284. public static function run($workingDir, $config, $blackList)
  285. {
  286. // various display parameters
  287. $workingDir = realpath($workingDir);
  288. self::$_workingDirLen = strlen($workingDir);
  289. self::$_errorsCount = 0;
  290. self::$_updatedCount = 0;
  291. self::$_skippedCount = 0;
  292. // set black list
  293. self::$skipFiles = array();
  294. self::$skipDirectories = array();
  295. self::_setSkippedPaths($workingDir, $blackList);
  296. $licenseInstances = array();
  297. foreach ($config as $path => $types) {
  298. // whether to scan directory recursively
  299. $recursive = (isset($types['_recursive']) ? $types['_recursive'] : true);
  300. unset($types['_recursive']);
  301. // update licenses
  302. foreach ($types as $fileType => $licenseType) {
  303. if (!isset($licenseInstances[$licenseType])) {
  304. $licenseInstances[$licenseType] = Routine::createLicenseInstance($licenseType);
  305. }
  306. Routine::updateLicense(
  307. array($workingDir . ($path ? DIRECTORY_SEPARATOR . $path : '')),
  308. Routine::$fileTypes[$fileType],
  309. $licenseInstances[$licenseType],
  310. $recursive
  311. );
  312. }
  313. }
  314. Routine::printLog(sprintf("\n" . 'Updated: %d; Skipped: %d; Errors: %d.' . "\n",
  315. self::$_updatedCount, self::$_skippedCount, self::$_errorsCount
  316. ));
  317. if (self::$_errorsCount || self::$_skippedCount) {
  318. throw new Exception('Failed: check skipped files or errors.' . "\n");
  319. }
  320. Routine::printLog('Success.' . "\n");
  321. }
  322. }