Skip to content

Commit

Permalink
Merge pull request #122 from hydephp/ModelImprovements
Browse files Browse the repository at this point in the history
Improve internal page model structure
  • Loading branch information
caendesilva authored Jul 1, 2022
2 parents 93b0e9d + 7ea44d3 commit 82f1c89
Show file tree
Hide file tree
Showing 20 changed files with 436 additions and 107 deletions.
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

0 comments on commit 82f1c89

Please sign in to comment.