Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve internal page model structure #122

Merged
merged 58 commits into from
Jul 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
f2059f4
Add AbstractPage::$outputDirectory property
caendesilva Jul 1, 2022
c9c78ea
Add PHPDocs
caendesilva Jul 1, 2022
1043f28
Add explicit property getters to contract for page models
caendesilva Jul 1, 2022
80dfc88
Implement the property getters
caendesilva Jul 1, 2022
968f324
Try marking the getters as final
caendesilva Jul 1, 2022
aef1023
Move PHPDocs to contract
caendesilva Jul 1, 2022
49e23b0
Format the file extension return value to ensure it is prefixed with …
caendesilva Jul 1, 2022
3ce9957
Replace type annotated return value PageContract to static
caendesilva Jul 1, 2022
0d47ffc
Replace type annotated return value AbstractPage to static
caendesilva Jul 1, 2022
e8549be
Refactor to use the new source directory getter methods
caendesilva Jul 1, 2022
2b6e4db
Refactor to use the new file extension getter methods
caendesilva Jul 1, 2022
3035048
Refactor to use the new parser class getter method
caendesilva Jul 1, 2022
0a2ea44
Add new method to get an instantiated parser class
caendesilva Jul 1, 2022
707195c
Fix recursion whoopsie
caendesilva Jul 1, 2022
33ee9e3
Remove redundant basename function call
caendesilva Jul 1, 2022
ed465f1
Refactor to use the new page parser getter
caendesilva Jul 1, 2022
d0a83f2
Update BladePage to implement the PageParserContract
caendesilva Jul 1, 2022
99e016b
Reorder helper methods
caendesilva Jul 1, 2022
2191345
Refactor to use sibling helpers to reduce duplicate code
caendesilva Jul 1, 2022
8f3c318
Trim trailing path separators to ensure consistent and predictable state
caendesilva Jul 1, 2022
926d6dd
Create helper to qualify a page basename into a referenceable path
caendesilva Jul 1, 2022
0fc6e1e
Replace string concatenation with model qualifier helper
caendesilva Jul 1, 2022
0570c84
Add getOutputLocation helper to qualify the output path
caendesilva Jul 1, 2022
f422101
Specify default output directories
caendesilva Jul 1, 2022
e82b378
Fix bug, output path should obviously not include source file extension
caendesilva Jul 1, 2022
d89f250
Deprecate DocumentationPage::getDocumentationOutputPath()
caendesilva Jul 1, 2022
ac87d8b
A temporary compat helper until the service provider bootstraps the o…
caendesilva Jul 1, 2022
9db020d
Use the new output location helper to get the output path
caendesilva Jul 1, 2022
b99598e
Dynamically create the needed directories
caendesilva Jul 1, 2022
911c289
Remove unused location parameter
caendesilva Jul 1, 2022
363195f
Rename registerDefaultDirectories to registerSourceDirectories
caendesilva Jul 1, 2022
b02f7d7
Deprecate RegistersDefaultDirectories.php pending rename
caendesilva Jul 1, 2022
d8fcc86
Improve documentation
caendesilva Jul 1, 2022
a3413b7
Create registerOutputDirectories helper
caendesilva Jul 1, 2022
46e5627
Trim the registered location path
caendesilva Jul 1, 2022
e76a1f0
Bind the documentation site output path in the service provider
caendesilva Jul 1, 2022
7d72668
Remove unneeded temporary compatibility helpers
caendesilva Jul 1, 2022
6a015ef
Reregister the service provider to pick up the new config during testing
caendesilva Jul 1, 2022
2fa7ee0
Add getCurrentPagePath to contract
caendesilva Jul 1, 2022
e9b80f2
Update getCurrentPagePath implementation to be dynamic
caendesilva Jul 1, 2022
b8946f8
Add the output directory property to test classes
caendesilva Jul 1, 2022
578bf7b
Move shared test code into helper
caendesilva Jul 1, 2022
9e4d4ed
Reregister the service provider to pick up the new config during testing
caendesilva Jul 1, 2022
99a99d6
Remove now redundant method overrides
caendesilva Jul 1, 2022
65792e2
Deprecate Hyde::getDocumentationOutputDirectory()
caendesilva Jul 1, 2022
b76d8c7
Deprecate Hyde::docsIndexPath()
caendesilva Jul 1, 2022
aebadc4
Replace configuration call with canonical model property value
caendesilva Jul 1, 2022
a2a2e27
Update PHPDoc formatting, add return value
caendesilva Jul 1, 2022
7515387
Format and add inheritDoc annotations
caendesilva Jul 1, 2022
51d2b8d
Add AbstractPage::getOutputPath() helper
caendesilva Jul 1, 2022
d646d61
Use the getOutputPath helper when saving the file
caendesilva Jul 1, 2022
6e44a83
Apply fixes from StyleCI
StyleCIBot Jul 1, 2022
7aa064e
Replace trim with ltrim
caendesilva Jul 1, 2022
c8f6dfe
Collapse PHPDoc
caendesilva Jul 1, 2022
9e2cb26
Create AbstractPageTest.php
caendesilva Jul 1, 2022
d205175
Add the test stubs
caendesilva Jul 1, 2022
f00dcfc
Write tests to cover the AbstractPage class
caendesilva Jul 1, 2022
7ea44d3
Apply fixes from StyleCI
StyleCIBot Jul 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/advanced-customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use Hyde\Framework\Concerns\RegistersDefaultDirectories;

public function register(): void
{
$this->registerDefaultDirectories([
$this->registerSourceDirectories([
BladePage::class => '_pages',
MarkdownPage::class => '_pages',
MarkdownPost::class => '_posts',
Expand Down
6 changes: 3 additions & 3 deletions packages/framework/src/Actions/CreatesNewPageSourceFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,18 @@ public function canSaveFile(string $path): void
public function createPage(string $type): int|false
{
if ($type === MarkdownPage::class) {
$this->needsDirectory(MarkdownPage::$sourceDirectory);
$this->needsDirectory(MarkdownPage::getSourceDirectory());

return $this->createMarkdownFile();
}
if ($type === BladePage::class) {
$this->needsDirectory(BladePage::$sourceDirectory);
$this->needsDirectory(BladePage::getSourceDirectory());

return $this->createBladeFile();
}

if ($type === DocumentationPage::class) {
$this->needsDirectory(DocumentationPage::$sourceDirectory);
$this->needsDirectory(DocumentationPage::getSourceDirectory());

return $this->createDocumentationFile();
}
Expand Down
9 changes: 6 additions & 3 deletions packages/framework/src/Concerns/Internal/FileHelpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,29 @@ trait FileHelpers
* Get the subdirectory compiled documentation files are stored in.
*
* @since v0.39.x (replaces `Hyde::docsDirectory()`)
* @deprecated v0.44.x (handled in the page model property `outputDirectory`)
*
* @return string
*/
public static function getDocumentationOutputDirectory(): string
{
return trim(config('docs.output_directory', 'docs'), '/\\');
return DocumentationPage::getOutputDirectory();
}

/**
* Get the path to the frontpage for the documentation.
*
* @deprecated v0.44.x should be moved to the documentation page model.
*
* @return string|false returns false if no frontpage is found
*/
public static function docsIndexPath(): string|false
{
if (file_exists(static::path(DocumentationPage::$sourceDirectory.'/index.md'))) {
if (file_exists(static::path(DocumentationPage::getSourceDirectory().'/index.md'))) {
return trim(static::pageLink(static::getDocumentationOutputDirectory().'/index.html'), '/');
}

if (file_exists(static::path(DocumentationPage::$sourceDirectory.'/readme.md'))) {
if (file_exists(static::path(DocumentationPage::getSourceDirectory().'/readme.md'))) {
return trim(static::pageLink(static::getDocumentationOutputDirectory().'/readme.html'), '/');
}

Expand Down
33 changes: 29 additions & 4 deletions packages/framework/src/Concerns/RegistersDefaultDirectories.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,44 @@

use Hyde\Framework\Contracts\AbstractPage;

/**
* @deprecated will be renamed to RegistersFileLocations or similar
*/
trait RegistersDefaultDirectories
{
/**
* Register the default directories.
* Register the default source directories for the given page classes.
* Location string should be relative to the root of the application.
*
* @param array $directoryMapping
* @example registerSourceDirectories([AbstractPage::class => '_pages'])
*
* @param array $directoryMapping{class: string<AbstractPage>, location: string}
* @return void
*/
protected function registerSourceDirectories(array $directoryMapping): void
{
foreach ($directoryMapping as $class => $location) {
/** @var AbstractPage $class */
$class::$sourceDirectory = trim($location, '/\\');
}
}

/*
* Register the optional output directories.
* Some HTML pages, like Blade and Markdown pages are stored right in the _site/ directory.
* However, some pages, like docs and posts are in subdirectories of the _site/ directory.
* Location string should be relative to the root of the application.
*
* @example registerOutputDirectories([AbstractPage::class => 'docs'])
*
* @param array $directoryMapping{class: string<AbstractPage>, location: string}
* @return void
*/
protected function registerDefaultDirectories(array $directoryMapping): void
protected function registerOutputDirectories(array $directoryMapping): void
{
foreach ($directoryMapping as $class => $location) {
/** @var AbstractPage $class */
$class::$sourceDirectory = $location;
$class::$outputDirectory = trim($location, '/\\');
}
}
}
4 changes: 2 additions & 2 deletions packages/framework/src/Concerns/ValidatesExistence.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ trait ValidatesExistence
public function validateExistence(string $model, string $slug): void
{
/** @var \Hyde\Framework\Contracts\AbstractPage $model */
$filepath = $model::$sourceDirectory.'/'.
$slug.$model::$fileExtension;
$filepath = $model::getSourceDirectory().'/'.
$slug.$model::getFileExtension();

if (! file_exists(Hyde::path($filepath))) {
throw new FileNotFoundException($filepath);
Expand Down
84 changes: 72 additions & 12 deletions packages/framework/src/Contracts/AbstractPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,104 @@
use Illuminate\Support\Collection;

/**
* To ensure compatability with the Hyde Framework,
* all Page Models must extend this class.
* To ensure compatibility with the Hyde Framework, all Page Models should extend this class.
*
* Markdown-based Pages should extend MarkdownDocument.
* Markdown-based Pages can extend the MarkdownDocument class to get relevant helpers.
*
* To learn about what the methods do, see the PHPDocs in the PageContract.
*
* @see \Hyde\Framework\Contracts\PageContract
* @test \Hyde\Framework\Testing\Feature\AbstractPageTest
*/
abstract class AbstractPage implements PageContract
{
use HasPageMetadata;

public static string $sourceDirectory;
public static string $outputDirectory;
public static string $fileExtension;
public static string $parserClass;

public string $slug;
/** @inheritDoc */
final public static function getSourceDirectory(): string
{
return trim(static::$sourceDirectory, '\\/');
}

public function getCurrentPagePath(): string
/** @inheritDoc */
final public static function getOutputDirectory(): string
{
return trim(static::$outputDirectory, '\\/');
}

/** @inheritDoc */
final public static function getFileExtension(): string
{
return '.'.ltrim(static::$fileExtension, '.');
}

/** @inheritDoc */
final public static function getParserClass(): string
{
return static::$parserClass;
}

/** @inheritDoc */
public static function getParser(string $slug): PageParserContract
{
return new static::$parserClass($slug);
}

/** @inheritDoc */
public static function parse(string $slug): static
{
return $this->slug;
return (new static::$parserClass($slug))->get();
}

/** @inheritDoc */
public static function files(): array
{
return CollectionService::getSourceFileListForModel(static::class);
}

/** @inheritDoc */
public static function all(): Collection
{
$collection = new Collection();

foreach (CollectionService::getSourceFileListForModel(static::class) as $filepath) {
$collection->push((new static::$parserClass(basename($filepath, static::$fileExtension)))->get());
foreach (static::files() as $basename) {
$collection->push(static::parse($basename));
}

return $collection;
}

public static function files(): array
/** @inheritDoc */
public static function qualifyBasename(string $basename): string
{
return CollectionService::getSourceFileListForModel(static::class);
return static::getSourceDirectory().'/'.trim($basename, '\\/').static::getFileExtension();
}

public static function parse(string $slug): AbstractPage
/** @inheritDoc */
public static function getOutputLocation(string $basename): string
{
return (new static::$parserClass($slug))->get();
// Using the trim function we ensure we don't have a leading slash when the output directory is the root directory.
return trim(
static::getOutputDirectory().'/'.trim($basename, '\\/'), '/'
).'.html';
}

public string $slug;

/** @inheritDoc */
public function getCurrentPagePath(): string
{
return trim(static::getOutputDirectory().'/'.$this->slug, '/');
}

/** @inheritDoc */
public function getOutputPath(): string
{
return static::getCurrentPagePath().'.html';
}
}
87 changes: 78 additions & 9 deletions packages/framework/src/Contracts/PageContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,48 @@
interface PageContract
{
/**
* Get a collection of all pages, parsed into page models.
* Get the directory in where source files are stored.
*
* @return \Illuminate\Support\Collection<\Hyde\Framework\Contracts\PageContract>
* @return string Path relative to the root of the project
*/
public static function getSourceDirectory(): string;

/**
* Get the output subdirectory to store compiled HTML.
*
* @see \Hyde\Framework\Testing\Unit\PageModelGetHelperTest
* @return string Relative to the site output directory.
*/
public static function all(): Collection;
public static function getOutputDirectory(): string;

/**
* Get the file extension of the source files.
*
* @return string (e.g. ".md")
*/
public static function getFileExtension(): string;

/**
* Get the class that parses source files into page models.
*
* @return string<\Hyde\Framework\Contracts\PageParserContract>
*/
public static function getParserClass(): string;

/**
* Create and return a new PageParser instance for this model,
* with the given slug passed to the constructor.
*/
public static function getParser(string $slug): PageParserContract;

/**
* Parse a source file slug into a page model.
*
* @param string $slug
* @return static New page model instance for the parsed source file.
*
* @see \Hyde\Framework\Testing\Unit\PageModelParseHelperTest
*/
public static function parse(string $slug): static;

/**
* Get an array of all the source file slugs for the model.
Expand All @@ -26,12 +61,46 @@ public static function all(): Collection;
public static function files(): array;

/**
* Parse a source file slug into a page model.
* Get a collection of all pages, parsed into page models.
*
* @param string $slug
* @return \Hyde\Framework\Contracts\AbstractPage
* @return \Illuminate\Support\Collection<static>
*
* @see \Hyde\Framework\Testing\Unit\PageModelParseHelperTest
* @see \Hyde\Framework\Testing\Unit\PageModelGetHelperTest
*/
public static function all(): Collection;

/**
* Qualify a page basename into a referenceable file path.
*
* @param string $basename for the page model source file.
* @return string path to the file relative to project root
*/
public static function qualifyBasename(string $basename): string;

/**
* Get the proper site output path for a page model.
*
* @param string $basename for the page model source file.
* @return string of the output file relative to the site output directory.
*
* @example DocumentationPage::getOutputPath('index') => 'docs/index.html'
*/
public static function getOutputLocation(string $basename): string;

/**
* Get the URI path relative to the site root.
*
* @example if the compiled page will be saved to _site/docs/index.html,
* then this method will return 'docs/index'
*
* @return string URI path relative to the site root.
*/
public function getCurrentPagePath(): string;

/**
* Get the path where the compiled page will be saved.
*
* @return string Relative to the site output directory.
*/
public static function parse(string $slug): AbstractPage;
public function getOutputPath(): string;
}
9 changes: 8 additions & 1 deletion packages/framework/src/HydeServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,20 @@ function () {

$this->app->singleton(AssetServiceContract::class, AssetService::class);

$this->registerDefaultDirectories([
$this->registerSourceDirectories([
BladePage::class => '_pages',
MarkdownPage::class => '_pages',
MarkdownPost::class => '_posts',
DocumentationPage::class => '_docs',
]);

$this->registerOutputDirectories([
BladePage::class => '',
MarkdownPage::class => '',
MarkdownPost::class => 'posts',
DocumentationPage::class => config('docs.output_directory', 'docs'),
]);

$this->discoverBladeViewsIn('_pages');

/** @deprecated v0.43.0-beta and is used here as a fallback for compatibility */
Expand Down
Loading