Skip to content

Commit

Permalink
Merge pull request #110 from hydephp/create-static-file-collections
Browse files Browse the repository at this point in the history
Create static file collections
  • Loading branch information
caendesilva authored Jun 25, 2022
2 parents 6bc9f66 + a84edbe commit c7ffb61
Show file tree
Hide file tree
Showing 6 changed files with 308 additions and 1 deletion.
12 changes: 12 additions & 0 deletions packages/framework/src/HydeServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ function () {

Commands\HydePackageDiscoverCommand::class,
]);

$this->registerModuleServiceProviders();
}

/**
Expand Down Expand Up @@ -136,4 +138,14 @@ protected function storeCompiledSiteIn(string $directory): void
{
StaticPageBuilder::$outputPath = $directory;
}

/**
* Register module service providers.
*
* @todo Make modules configurable.
*/
protected function registerModuleServiceProviders(): void
{
$this->app->register(Modules\DataCollections\DataCollectionServiceProvider::class);
}
}
68 changes: 68 additions & 0 deletions packages/framework/src/Modules/DataCollections/DataCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace Hyde\Framework\Modules\DataCollections;

use Hyde\Framework\Hyde;
use Hyde\Framework\Models\MarkdownDocument;
use Hyde\Framework\Services\MarkdownFileService;
use Illuminate\Support\Collection;

/**
* Generates Laravel Collections from static data files,
* such as Markdown components and YAML files.
*
* @see \Hyde\Framework\Testing\Modules\DataCollections\DataCollectionTest\DataCollectionTest
*/
class DataCollection extends Collection
{
public string $key;

protected float $timeStart;
public float $parseTimeInMs;

public static string $sourceDirectory = '_data';

public function __construct(string $key)
{
$this->timeStart = microtime(true);
$this->key = $key;

parent::__construct();
}

public function getCollection(): DataCollection
{
$this->parseTimeInMs = round((microtime(true) - $this->timeStart) * 1000, 2);
unset($this->timeStart);

return $this;
}

public function getMarkdownFiles(): array
{
return glob(Hyde::path(
static::$sourceDirectory.'/'.$this->key.'/*'.MarkdownDocument::$fileExtension
));
}

/**
* Get a collection of Markdown documents in the _data/<$key> directory.
* Each Markdown file will be parsed into a MarkdownDocument with front matter.
*
* @param string $key for a subdirectory of the _data directory
* @return DataCollection<\Hyde\Framework\Models\MarkdownDocument>
*/
public static function markdown(string $key): DataCollection
{
$collection = new DataCollection($key);
foreach ($collection->getMarkdownFiles() as $file) {
if (! str_starts_with(basename($file), '_')) {
$collection->push(
(new MarkdownFileService($file))->get()
);
}
}

return $collection->getCollection();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Hyde\Framework\Modules\DataCollections;

use Hyde\Framework\Hyde;
use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\ServiceProvider;

/**
* @see \Hyde\Framework\Testing\Modules\DataCollections\DataCollectionTest\DataCollectionTest
*/
class DataCollectionServiceProvider extends ServiceProvider
{
public function register()
{
// Register the class alias
AliasLoader::getInstance()->alias(
'MarkdownCollection', Facades\MarkdownCollection::class
);
}

public function boot()
{
// Create the _data directory if it doesn't exist
if (! is_dir(Hyde::path('_data'))) {
mkdir(Hyde::path('_data'));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Hyde\Framework\Modules\DataCollections\Facades;

use Hyde\Framework\Modules\DataCollections\DataCollection;

/**
* @see \Hyde\Framework\Testing\Modules\DataCollections\DataCollectionTest\DataCollectionTest
*/
class MarkdownCollection
{
public static function get(string $collectionKey): DataCollection
{
return DataCollection::markdown($collectionKey);
}
}
8 changes: 7 additions & 1 deletion packages/framework/src/Modules/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# Hyde Modules

This directory contains self-contained code modules,
that may eventually be extracted into packages.
that may eventually be extracted into packages.

They may also be merged into the Hyde core.

As these modules may be experimental,
the namespaces used may be changed without notice
as per the current 0.x semantic versioning range.
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
<?php

namespace Hyde\Framework\Testing\Modules\DataCollections\DataCollectionTest;

use Hyde\Framework\Hyde;
use Hyde\Framework\Models\MarkdownDocument;
use Hyde\Framework\Modules\DataCollections\DataCollection;
use Hyde\Framework\Modules\DataCollections\DataCollectionServiceProvider;
use Hyde\Framework\Modules\DataCollections\Facades\MarkdownCollection;
use Hyde\Testing\TestCase;
use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\File;

/**
* @covers \Hyde\Framework\Modules\DataCollections\DataCollection
* @covers \Hyde\Framework\Modules\DataCollections\DataCollectionServiceProvider
* @covers \Hyde\Framework\Modules\DataCollections\Facades\MarkdownCollection
*/
class DataCollectionTest extends TestCase
{
// constructor creates new data collection instance
public function test_constructor_creates_new_data_collection_instance()
{
$class = new DataCollection('foo');
$this->assertInstanceOf(DataCollection::class, $class);
$this->assertInstanceOf(Collection::class, $class);
}

public function test_constructor_sets_key()
{
$class = new DataCollection('foo');
$this->assertEquals('foo', $class->key);
}

public function test_key_is_required()
{
$this->expectException(\ArgumentCountError::class);
new DataCollection();
}

public function test_get_collection_method_returns_the_collection_instance()
{
$class = new DataCollection('foo');
$this->assertSame($class, $class->getCollection());
}

public function test_get_collection_method_sets_parse_time_in_ms()
{
$class = new DataCollection('foo');
$class->getCollection();
$this->assertIsFloat($class->parseTimeInMs);
}

public function test_get_markdown_files_method_returns_empty_array_if_the_specified_directory_does_not_exist()
{
$class = new DataCollection('foo');
$this->assertIsArray($class->getMarkdownFiles());
$this->assertEmpty($class->getMarkdownFiles());
}

public function test_get_markdown_files_method_returns_empty_array_if_no_files_are_found_in_specified_directory()
{
mkdir(Hyde::path('_data/foo'));
$class = new DataCollection('foo');
$this->assertIsArray($class->getMarkdownFiles());
$this->assertEmpty($class->getMarkdownFiles());
rmdir(Hyde::path('_data/foo'));
}

public function test_get_markdown_files_method_returns_an_array_of_markdown_files_in_the_specified_directory()
{
mkdir(Hyde::path('_data/foo'));
touch(Hyde::path('_data/foo/foo.md'));
touch(Hyde::path('_data/foo/bar.md'));

$this->assertEquals([
Hyde::path('_data/foo/bar.md'),
Hyde::path('_data/foo/foo.md'),
], (new DataCollection('foo'))->getMarkdownFiles());

File::deleteDirectory(Hyde::path('_data/foo'));
}

public function test_get_markdown_files_method_does_not_include_files_in_subdirectories()
{
mkdir(Hyde::path('_data/foo'));
mkdir(Hyde::path('_data/foo/bar'));
touch(Hyde::path('_data/foo/foo.md'));
touch(Hyde::path('_data/foo/bar/bar.md'));
$this->assertEquals([
Hyde::path('_data/foo/foo.md'),
], (new DataCollection('foo'))->getMarkdownFiles());
File::deleteDirectory(Hyde::path('_data/foo'));
}

public function test_get_markdown_files_method_does_not_include_files_with_extensions_other_than_md()
{
mkdir(Hyde::path('_data/foo'));
touch(Hyde::path('_data/foo/foo.md'));
touch(Hyde::path('_data/foo/bar.txt'));
$this->assertEquals([
Hyde::path('_data/foo/foo.md'),
], (new DataCollection('foo'))->getMarkdownFiles());
File::deleteDirectory(Hyde::path('_data/foo'));
}

public function test_static_markdown_helper_returns_new_data_collection_instance()
{
$this->assertInstanceOf(DataCollection::class, DataCollection::markdown('foo'));
}

public function test_static_markdown_helper_discovers_and_parses_markdown_files_in_the_specified_directory()
{
mkdir(Hyde::path('_data/foo'));
touch(Hyde::path('_data/foo/foo.md'));
touch(Hyde::path('_data/foo/bar.md'));

$collection = DataCollection::markdown('foo');

$this->assertContainsOnlyInstancesOf(MarkdownDocument::class, $collection);

File::deleteDirectory(Hyde::path('_data/foo'));
}

public function test_static_markdown_helper_ignores_files_starting_with_an_underscore()
{
mkdir(Hyde::path('_data/foo'));
touch(Hyde::path('_data/foo/foo.md'));
touch(Hyde::path('_data/foo/_bar.md'));
$this->assertCount(1, DataCollection::markdown('foo'));
File::deleteDirectory(Hyde::path('_data/foo'));
}

public function test_markdown_facade_returns_same_result_as_static_markdown_helper()
{
$expected = DataCollection::markdown('foo');
$actual = MarkdownCollection::get('foo');
unset($expected->parseTimeInMs);
unset($actual->parseTimeInMs);
$this->assertEquals($expected, $actual);
}

// Test DataCollectionServiceProvider registers the facade as an alias
public function test_data_collection_service_provider_registers_the_facade_as_an_alias()
{
$this->assertArrayHasKey('MarkdownCollection', AliasLoader::getInstance()->getAliases());
$this->assertContains(MarkdownCollection::class, AliasLoader::getInstance()->getAliases());
}

public function test_data_collection_service_provider_creates_the__data_directory_if_it_does_not_exist()
{
File::deleteDirectory(Hyde::path('_data'));
$this->assertFileDoesNotExist(Hyde::path('_data'));

(new DataCollectionServiceProvider($this->app))->boot();

$this->assertFileExists(Hyde::path('_data'));
}

public function test_class_has_static_source_directory_property()
{
$this->assertEquals('_data', DataCollection::$sourceDirectory);
}

public function test_source_directory_can_be_changed()
{
DataCollection::$sourceDirectory = 'foo';
mkdir(Hyde::path('foo/bar'), recursive: true);
touch(Hyde::path('foo/bar/foo.md'));
$this->assertEquals([
Hyde::path('foo/bar/foo.md'),
], (new DataCollection('bar'))->getMarkdownFiles());
File::deleteDirectory(Hyde::path('foo'));
}
}

0 comments on commit c7ffb61

Please sign in to comment.