From 96d601d5138328f67604b427c818252cdabf1e9d Mon Sep 17 00:00:00 2001 From: Simon Dann Date: Thu, 22 Feb 2018 13:04:37 +0000 Subject: [PATCH] (#282) Refactored LoadSourceFileTree --- src/Entities/ProjectFile.php | 30 ++++++- src/Steps/LoadSourceFileTree.php | 131 ++++++++++++++++++++----------- tests/Unit/ContentGraphNTest.php | 24 +++++- 3 files changed, 133 insertions(+), 52 deletions(-) diff --git a/src/Entities/ProjectFile.php b/src/Entities/ProjectFile.php index e0cc565..4b6948e 100644 --- a/src/Entities/ProjectFile.php +++ b/src/Entities/ProjectFile.php @@ -56,6 +56,16 @@ class ProjectFile extends SplFileInfo implements ProjectFileInterface */ private $blocked = false; + /** + * Because all files in the source tree are loaded, this ignore flag + * is set on those that should not be parsed. This allows them to be + * analysed for dependencies (e.g. a not ignored file depends upon a + * ignored file) + * + * @var bool + */ + private $ignored = false; + /** * ProjectFile constructor. * @@ -319,7 +329,7 @@ public function setToCopy($copy) /** * @return bool */ - public function isBlocked() + public function isBlocked() : bool { return $this->blocked; } @@ -327,11 +337,27 @@ public function isBlocked() /** * @param bool $blocked */ - public function setBlocked($blocked = true) + public function setBlocked(bool $blocked = true) { $this->blocked = $blocked; } + /** + * @return bool + */ + public function isIgnored(): bool + { + return $this->ignored; + } + + /** + * @param bool $ignored + */ + public function setIgnored(bool $ignored = true) + { + $this->ignored = $ignored; + } + ///////////////////////////////////////////// // Deprecated Methods ///////////////////////////////////////////// diff --git a/src/Steps/LoadSourceFileTree.php b/src/Steps/LoadSourceFileTree.php index 81ac876..b9ade0c 100644 --- a/src/Steps/LoadSourceFileTree.php +++ b/src/Steps/LoadSourceFileTree.php @@ -5,7 +5,6 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Finder\Finder; use Tapestry\Entities\Cache; -use Tapestry\Entities\Collections\ExcludedFilesCollection; use Tapestry\Entities\Configuration; use Tapestry\Entities\Project; use Tapestry\Entities\ProjectFile; @@ -23,11 +22,6 @@ class LoadSourceFileTree implements Step */ private $tapestry; - /** - * @var ExcludedFilesCollection - */ - private $excluded; - /** * @var bool */ @@ -49,17 +43,24 @@ class LoadSourceFileTree implements Step */ private $now; + /** + * Paths that should be ignored. + * + * @var array + */ + private $ignoredPaths = []; + /** * LoadSourceFiles constructor. * - * @param Tapestry $tapestry + * @param Tapestry $tapestry * @param Configuration $configuration */ public function __construct(Tapestry $tapestry, Configuration $configuration) { $this->tapestry = $tapestry; $this->now = new \DateTime(); - $this->excluded = new ExcludedFilesCollection(array_merge($configuration->get('ignore'), ['_views', '_templates'])); + $this->ignoredPaths = array_merge($configuration->get('ignore'), ['_views', '_templates']); $this->prettyPermalink = boolval($configuration->get('pretty_permalink', true)); $this->publishDrafts = boolval($configuration->get('publish_drafts', false)); $this->autoPublish = (isset($tapestry['cmd_options']['auto-publish']) ? boolval($tapestry['cmd_options']['auto-publish']) : false); @@ -76,8 +77,8 @@ public function __construct(Tapestry $tapestry, Configuration $configuration) */ public function __invoke(Project $project, OutputInterface $output) { - if (! file_exists($project->sourceDirectory)) { - $output->writeln('[!] The project source path could not be opened at ['.$project->sourceDirectory.']'); + if (!file_exists($project->sourceDirectory)) { + $output->writeln('[!] The project source path could not be opened at [' . $project->sourceDirectory . ']'); return false; } @@ -86,17 +87,20 @@ public function __invoke(Project $project, OutputInterface $output) $cache = $project->get('cache'); // Table containing all files found and their last update time. - if (! $hashTable = $cache->getItem('fileHashTable')) { + if (!$hashTable = $cache->getItem('fileHashTable')) { $hashTable = []; } /** @var ContentTypeFactory $contentTypes */ $contentTypes = $project->get('content_types'); - // foreach ($contentTypes->all() as $contentType) { - // $this->excluded->addUnderscoreException($contentType->getPath()); - // } - // unset($contentType); + foreach ($contentTypes->all() as $contentType) { + $path = $contentType->getPath(); + if ($path !== '*' && ! isset($this->ignoredPaths[$contentType->getPath()])) { + $this->ignoredPaths[] = $contentType->getPath(); + } + } + unset($contentType); /** @var ContentRendererFactory $contentRenderers */ $contentRenderers = $project->get('content_renderers'); @@ -107,56 +111,61 @@ public function __invoke(Project $project, OutputInterface $output) ->in($project->sourceDirectory) ->ignoreDotFiles(true); - //$this->excluded->excludeFromFinder($finder); - foreach ($finder->files() as $file) { $file = new ProjectFile($file, ['pretty_permalink' => $this->prettyPermalink]); - if (isset($hashTable[$file->getUid()]) && $hashTable[$file->getUid()] == $file->getMTime()){ + if (isset($hashTable[$file->getUid()]) && $hashTable[$file->getUid()] == $file->getMTime()) { $file->isBlocked(); } else { $hashTable[$file->getUid()] = $file->getMTime(); } - $renderer = $contentRenderers->get($file->getFileInfo()->getExtension()); + if ($this->shouldIgnore($file)) { + $file->setIgnored(); + } else { - if ($renderer->supportsFrontMatter()) { - $frontMatter = new FrontMatter($file->getFileContent()); - $file->setData($frontMatter->getData()); - $file->loadContent($frontMatter->getContent()); - } + $renderer = $contentRenderers->get($file->getFileInfo()->getExtension()); - // Publish Drafts / Scheduled Posts - if ($this->publishDrafts === false) { - // If file is a draft and cant auto publish then it remains a draft - if ( - boolval($file->getData('draft', false)) === true && - $this->canAutoPublish($file) === false - ) { - continue; + if ($renderer->supportsFrontMatter()) { + $frontMatter = new FrontMatter($file->getFileContent()); + $file->setData($frontMatter->getData()); + $file->loadContent($frontMatter->getContent()); } - // If file is not a draft, but the date is in the future then it is scheduled - if ($file->getData('date', new \DateTime()) > $this->now) { - continue; + // Publish Drafts / Scheduled Posts + if ($this->publishDrafts === false) { + // If file is a draft and cant auto publish then it remains a draft + if ( + boolval($file->getData('draft', false)) === true && + $this->canAutoPublish($file) === false + ) { + continue; + } + + // If file is not a draft, but the date is in the future then it is scheduled + if ($file->getData('date', new \DateTime()) > $this->now) { + continue; + } } - } - if (! $contentType = $contentTypes->find($file->getRelativePath())) { - $contentType = $contentTypes->get('*'); - } else { - $contentType = $contentTypes->get($contentType); - } + if (!$contentType = $contentTypes->find($file->getRelativePath())) { + $contentType = $contentTypes->get('*'); + } else { + $contentType = $contentTypes->get($contentType); + } + + // Identify if $file belongs to default renderer and therefore should be copied (for issue #255) + if ($renderer->getName() === 'DefaultRenderer') { + $renderer->mutateFile($file); + } - // Identify if $file belongs to default renderer and therefore should be copied (for issue #255) - if ($renderer->getName() === 'DefaultRenderer') { - $renderer->mutateFile($file); + $contentType->addFile($file); } - $contentType->addFile($file); $project->addFile($file); - $output->writeln('[+] File ['.$file->getRelativePathname().'] bucketed into content type ['.$contentType->getName().']'); - + if (! $file->isIgnored()) { + $output->writeln('[+] File [' . $file->getRelativePathname() . '] bucketed into content type [' . $contentType->getName() . ']'); + } } $cache->setItem('fileHashTable', $hashTable); @@ -183,4 +192,32 @@ private function canAutoPublish(ProjectFile $file) return false; } + + /** + * Files found in '_views', '_templates' should have their ignored flag set true. + * This is so they are available for SyntaxAnalysis but not parsed and output to dist + * because that would make no sense... + * + * @param ProjectFile $file + * @return bool + */ + private function shouldIgnore(ProjectFile $file): bool + { + $relativePath = $file->getRelativePath(); + + foreach ($this->ignoredPaths as $ignoredPath) { + if (str_contains($relativePath, $ignoredPath)){ + return true; + } + } + + // Paths containing underscores are ignored by default. + foreach (explode('/', str_replace('\\', '/', $relativePath)) as $pathItem) { + if (substr($pathItem, 0, 1) === '_') { + return true; + } + } + + return false; + } } \ No newline at end of file diff --git a/tests/Unit/ContentGraphNTest.php b/tests/Unit/ContentGraphNTest.php index 4d04f89..c23e02b 100644 --- a/tests/Unit/ContentGraphNTest.php +++ b/tests/Unit/ContentGraphNTest.php @@ -26,7 +26,8 @@ class ContentGraphNTest extends TestCase */ public function testAnalysis() { - $this->loadToTmp($this->assetPath('build_test_7/src')); + //$this->loadToTmp($this->assetPath('build_test_7/src')); + $this->loadToTmp($this->assetPath('build_test_4/src')); $tapestry = $this->mockTapestry($this->tmpDirectory); /** @var Project $project */ @@ -44,9 +45,26 @@ public function testAnalysis() ], $tapestry); $generator->generate($project, new NullOutput()); - touch($this->tmpDirectory . '/source/something.html'); + //touch($this->tmpDirectory . '/source/something.html'); - $generator->generate($project, new NullOutput()); + //$generator->generate($project, new NullOutput()); + + // + // For refactoring issues #300, #297, #284, #282, #270: + // + // Tapestry now parses all files in the source folder and builds an hash table containing them all + // and their last change date. + // + // Test that the following happens: + // + // [ ] All files in source folder are loaded + // [ ] All files in source folder are bucketed correctly + // + // Because ignored files are still "parsed" during the LoadSourceFileTree step it also needs to be checked that + // they have an ignored flag set. This ensures that template files don't then get copied from source to dist. + // + // [ ] Ignored files are ignored + // $f = 0; }