Decouple Site from pages

This commit is contained in:
Giuseppe Criscione 2024-10-05 12:41:35 +02:00
parent e58503d955
commit b6d6d7601d
21 changed files with 86 additions and 63 deletions

View File

@ -1,7 +1,9 @@
canonicalRoute: null author: ''
defaultTemplate: page defaultTemplate: page
description: ''
maintenance: maintenance:
enabled: false enabled: false
page: null page: null

View File

@ -2,8 +2,8 @@
use Formwork\Fields\Exceptions\ValidationException; use Formwork\Fields\Exceptions\ValidationException;
use Formwork\Fields\Field; use Formwork\Fields\Field;
use Formwork\Pages\Site;
use Formwork\Parsers\Markdown; use Formwork\Parsers\Markdown;
use Formwork\Site;
use Formwork\Utils\Constraint; use Formwork\Utils\Constraint;
use Formwork\Utils\Str; use Formwork\Utils\Str;

View File

@ -4,7 +4,7 @@ use Formwork\Fields\Exceptions\ValidationException;
use Formwork\Fields\Field; use Formwork\Fields\Field;
use Formwork\Pages\Page; use Formwork\Pages\Page;
use Formwork\Pages\PageCollection; use Formwork\Pages\PageCollection;
use Formwork\Pages\Site; use Formwork\Site;
return function (Site $site) { return function (Site $site) {
return [ return [

View File

@ -1,7 +1,7 @@
<?php <?php
use Formwork\Fields\Field; use Formwork\Fields\Field;
use Formwork\Pages\Site; use Formwork\Site;
return function (Site $site) { return function (Site $site) {
return [ return [

View File

@ -16,5 +16,5 @@ parameters:
- '#^Call to an undefined method Formwork\\Data\\CollectionDataProxy\:\:#' - '#^Call to an undefined method Formwork\\Data\\CollectionDataProxy\:\:#'
- '#^Call to an undefined method Formwork\\Fields\\Field\:\:#' - '#^Call to an undefined method Formwork\\Fields\\Field\:\:#'
- '#^Call to an undefined method Formwork\\Pages\\Page\:\:#' - '#^Call to an undefined method Formwork\\Pages\\Page\:\:#'
- '#^Call to an undefined method Formwork\\Pages\\Site\:\:#' - '#^Call to an undefined method Formwork\\Site\:\:#'
- '#^Call to an undefined method Formwork\\Panel\\Users\\User\:\:#' - '#^Call to an undefined method Formwork\\Panel\\Users\\User\:\:#'

View File

@ -13,7 +13,6 @@ use Formwork\Http\Request;
use Formwork\Http\Response; use Formwork\Http\Response;
use Formwork\Images\ImageFactory; use Formwork\Images\ImageFactory;
use Formwork\Languages\Languages; use Formwork\Languages\Languages;
use Formwork\Pages\Site;
use Formwork\Pages\Templates\TemplateFactory; use Formwork\Pages\Templates\TemplateFactory;
use Formwork\Panel\Panel; use Formwork\Panel\Panel;
use Formwork\Panel\Users\UserFactory; use Formwork\Panel\Users\UserFactory;

View File

@ -10,9 +10,9 @@ use Formwork\Http\RedirectResponse;
use Formwork\Http\Response; use Formwork\Http\Response;
use Formwork\Http\ResponseStatus; use Formwork\Http\ResponseStatus;
use Formwork\Pages\Page; use Formwork\Pages\Page;
use Formwork\Pages\Site;
use Formwork\Router\RouteParams; use Formwork\Router\RouteParams;
use Formwork\Router\Router; use Formwork\Router\Router;
use Formwork\Site;
use Formwork\Statistics\Statistics; use Formwork\Statistics\Statistics;
use Formwork\Utils\FileSystem; use Formwork\Utils\FileSystem;
use Formwork\View\ViewFactory; use Formwork\View\ViewFactory;
@ -64,8 +64,8 @@ class PageController extends AbstractController
)) { )) {
// Clear cache if the site was not modified since the page has been published or unpublished // Clear cache if the site was not modified since the page has been published or unpublished
$this->filesCache->clear(); $this->filesCache->clear();
if ($this->site->path() !== null) { if ($this->site->contentPath() !== null) {
FileSystem::touch($this->site->path()); FileSystem::touch($this->site->contentPath());
} }
} }

View File

@ -4,8 +4,8 @@ namespace Formwork\Files;
use Formwork\Config\Config; use Formwork\Config\Config;
use Formwork\Files\Exceptions\FileUriGenerationException; use Formwork\Files\Exceptions\FileUriGenerationException;
use Formwork\Pages\Site;
use Formwork\Router\Router; use Formwork\Router\Router;
use Formwork\Site;
use Formwork\Utils\FileSystem; use Formwork\Utils\FileSystem;
use Formwork\Utils\Str; use Formwork\Utils\Str;
use RuntimeException; use RuntimeException;

View File

@ -16,6 +16,7 @@ use Formwork\Pages\Traits\PageStatus;
use Formwork\Pages\Traits\PageTraversal; use Formwork\Pages\Traits\PageTraversal;
use Formwork\Pages\Traits\PageUid; use Formwork\Pages\Traits\PageUid;
use Formwork\Pages\Traits\PageUri; use Formwork\Pages\Traits\PageUri;
use Formwork\Site;
use Formwork\Utils\Arr; use Formwork\Utils\Arr;
use Formwork\Utils\FileSystem; use Formwork\Utils\FileSystem;
use Formwork\Utils\Path; use Formwork\Utils\Path;
@ -493,6 +494,16 @@ class Page extends Model implements Stringable
$this->__construct($data); $this->__construct($data);
} }
public function contentPath(): ?string
{
return $this->path;
}
public function contentRelativePath(): ?string
{
return $this->relativePath;
}
/** /**
* Load files related to page * Load files related to page
*/ */
@ -602,11 +613,11 @@ class Page extends Model implements Stringable
{ {
$this->path = FileSystem::normalizePath($path . '/'); $this->path = FileSystem::normalizePath($path . '/');
if ($this->site()->path() === null) { if ($this->site()->contentPath() === null) {
throw new UnexpectedValueException('Unexpected missing site path'); throw new UnexpectedValueException('Unexpected missing site path');
} }
$this->relativePath = Str::prepend(Path::makeRelative($this->path, $this->site()->path(), DS), DS); $this->relativePath = Str::prepend(Path::makeRelative($this->path, $this->site()->contentPath(), DS), DS);
$routePath = preg_replace('~[/\\\](\d+-)~', '/', $this->relativePath) $routePath = preg_replace('~[/\\\](\d+-)~', '/', $this->relativePath)
?? throw new RuntimeException(sprintf('Replacement failed with error: %s', preg_last_error_msg())); ?? throw new RuntimeException(sprintf('Replacement failed with error: %s', preg_last_error_msg()));

View File

@ -4,6 +4,7 @@ namespace Formwork\Pages;
use Formwork\Data\AbstractCollection; use Formwork\Data\AbstractCollection;
use Formwork\Data\Contracts\Paginable; use Formwork\Data\Contracts\Paginable;
use Formwork\Site;
use Formwork\Utils\Str; use Formwork\Utils\Str;
use RuntimeException; use RuntimeException;

View File

@ -5,7 +5,7 @@ namespace Formwork\Pages\Templates;
use Closure; use Closure;
use Formwork\App; use Formwork\App;
use Formwork\Assets; use Formwork\Assets;
use Formwork\Pages\Site; use Formwork\Site;
use Formwork\Utils\Constraint; use Formwork\Utils\Constraint;
use Formwork\Utils\FileSystem; use Formwork\Utils\FileSystem;
use Formwork\View\Exceptions\RenderingException; use Formwork\View\Exceptions\RenderingException;

View File

@ -4,7 +4,7 @@ namespace Formwork\Pages\Traits;
use Formwork\Pages\Page; use Formwork\Pages\Page;
use Formwork\Pages\PageCollection; use Formwork\Pages\PageCollection;
use Formwork\Pages\Site; use Formwork\Site;
use Formwork\Utils\FileSystem; use Formwork\Utils\FileSystem;
use RuntimeException; use RuntimeException;
@ -43,7 +43,7 @@ trait PageTraversal
/** /**
* Get page or site path * Get page or site path
*/ */
abstract public function path(): ?string; abstract public function contentPath(): ?string;
/** /**
* Get page or site route * Get page or site route
@ -66,13 +66,13 @@ trait PageTraversal
return $this->parent; return $this->parent;
} }
if ($this->path() === null) { if ($this->contentPath() === null) {
return null; return null;
} }
$parentPath = FileSystem::joinPaths(dirname($this->path()), '/'); $parentPath = FileSystem::joinPaths(dirname($this->contentPath()), '/');
if ($parentPath === $this->site()->path()) { if ($parentPath === $this->site()->contentPath()) {
return $this->parent = $this->site(); return $this->parent = $this->site();
} }
@ -104,11 +104,11 @@ trait PageTraversal
return $this->children; return $this->children;
} }
if ($this->path() === null) { if ($this->contentPath() === null) {
return $this->children = new PageCollection(); return $this->children = new PageCollection();
} }
return $this->children = $this->site()->retrievePages($this->path()); return $this->children = $this->site()->retrievePages($this->contentPath());
} }
/** /**
@ -136,11 +136,11 @@ trait PageTraversal
return $this->descendants; return $this->descendants;
} }
if ($this->path() === null) { if ($this->contentPath() === null) {
return $this->descendants = new PageCollection(); return $this->descendants = new PageCollection();
} }
return $this->descendants = $this->site()->retrievePages($this->path(), recursive: true); return $this->descendants = $this->site()->retrievePages($this->contentPath(), recursive: true);
} }
/** /**
@ -213,7 +213,7 @@ trait PageTraversal
return $this->inclusiveSiblings; return $this->inclusiveSiblings;
} }
if ($this->path() === null || $this->parent() === null) { if ($this->contentPath() === null || $this->parent() === null) {
return $this->inclusiveSiblings = new PageCollection([$this->route() => $this]); return $this->inclusiveSiblings = new PageCollection([$this->route() => $this]);
} }

View File

@ -14,7 +14,7 @@ trait PageUid
/** /**
* Get page or site relative path * Get page or site relative path
*/ */
abstract public function relativePath(): ?string; abstract public function contentRelativePath(): ?string;
/** /**
* Get the page unique identifier * Get the page unique identifier
@ -25,7 +25,7 @@ trait PageUid
return $this->uid; return $this->uid;
} }
$id = $this->relativePath() ?: spl_object_hash($this); $id = $this->contentRelativePath() ?: spl_object_hash($this);
return $this->uid = Str::chunk(substr(hash('sha256', (string) $id), 0, 32), 8, '-'); return $this->uid = Str::chunk(substr(hash('sha256', (string) $id), 0, 32), 8, '-');
} }

View File

@ -3,7 +3,7 @@
namespace Formwork\Pages\Traits; namespace Formwork\Pages\Traits;
use Formwork\App; use Formwork\App;
use Formwork\Pages\Site; use Formwork\Site;
use Formwork\Utils\Path; use Formwork\Utils\Path;
use Formwork\Utils\Uri; use Formwork\Utils\Uri;

View File

@ -8,7 +8,6 @@ use Formwork\Controllers\AbstractController as BaseAbstractController;
use Formwork\Http\RedirectResponse; use Formwork\Http\RedirectResponse;
use Formwork\Http\Request; use Formwork\Http\Request;
use Formwork\Http\ResponseStatus; use Formwork\Http\ResponseStatus;
use Formwork\Pages\Site;
use Formwork\Panel\Modals\Modal; use Formwork\Panel\Modals\Modal;
use Formwork\Panel\Modals\ModalCollection; use Formwork\Panel\Modals\ModalCollection;
use Formwork\Panel\Modals\ModalFactory; use Formwork\Panel\Modals\ModalFactory;
@ -18,6 +17,7 @@ use Formwork\Parsers\Json;
use Formwork\Router\Router; use Formwork\Router\Router;
use Formwork\Security\CsrfToken; use Formwork\Security\CsrfToken;
use Formwork\Services\Container; use Formwork\Services\Container;
use Formwork\Site;
use Formwork\Translations\Translations; use Formwork\Translations\Translations;
use Formwork\Utils\Date; use Formwork\Utils\Date;
use Formwork\Utils\Uri; use Formwork\Utils\Uri;

View File

@ -50,10 +50,10 @@ class OptionsController extends AbstractController
// Touch content folder to invalidate cache // Touch content folder to invalidate cache
if ($differ) { if ($differ) {
if ($this->site()->path() === null) { if ($this->site()->contentPath() === null) {
throw new UnexpectedValueException('Unexpected missing site path'); throw new UnexpectedValueException('Unexpected missing site path');
} }
FileSystem::touch($this->site()->path()); FileSystem::touch($this->site()->contentPath());
} }
$this->panel()->notify($this->translate('panel.options.updated'), 'success'); $this->panel()->notify($this->translate('panel.options.updated'), 'success');
@ -93,10 +93,10 @@ class OptionsController extends AbstractController
// Touch content folder to invalidate cache // Touch content folder to invalidate cache
if ($differ) { if ($differ) {
if ($this->site()->path() === null) { if ($this->site()->contentPath() === null) {
throw new UnexpectedValueException('Unexpected missing site path'); throw new UnexpectedValueException('Unexpected missing site path');
} }
FileSystem::touch($this->site()->path()); FileSystem::touch($this->site()->contentPath());
} }
$this->panel()->notify($this->translate('panel.options.updated'), 'success'); $this->panel()->notify($this->translate('panel.options.updated'), 'success');

View File

@ -15,12 +15,12 @@ use Formwork\Http\RequestMethod;
use Formwork\Http\Response; use Formwork\Http\Response;
use Formwork\Images\Image; use Formwork\Images\Image;
use Formwork\Pages\Page; use Formwork\Pages\Page;
use Formwork\Pages\Site;
use Formwork\Panel\ContentHistory\ContentHistory; use Formwork\Panel\ContentHistory\ContentHistory;
use Formwork\Panel\ContentHistory\ContentHistoryEvent; use Formwork\Panel\ContentHistory\ContentHistoryEvent;
use Formwork\Parsers\Yaml; use Formwork\Parsers\Yaml;
use Formwork\Router\RouteParams; use Formwork\Router\RouteParams;
use Formwork\Schemes\Schemes; use Formwork\Schemes\Schemes;
use Formwork\Site;
use Formwork\Utils\Arr; use Formwork\Utils\Arr;
use Formwork\Utils\Constraint; use Formwork\Utils\Constraint;
use Formwork\Utils\Date; use Formwork\Utils\Date;
@ -655,12 +655,12 @@ class PagesController extends AbstractController
throw new UnexpectedValueException('Unexpected missing page path'); throw new UnexpectedValueException('Unexpected missing page path');
} }
if ($this->site()->path() === null) { if ($this->site()->contentPath() === null) {
throw new UnexpectedValueException('Unexpected missing site path'); throw new UnexpectedValueException('Unexpected missing site path');
} }
FileSystem::write($page->path() . $filename, $fileContent); FileSystem::write($page->path() . $filename, $fileContent);
FileSystem::touch($this->site()->path()); FileSystem::touch($this->site()->contentPath());
$contentHistory = new ContentHistory($page->path()); $contentHistory = new ContentHistory($page->path());

View File

@ -4,11 +4,10 @@ namespace Formwork\Services\Loaders;
use Formwork\Config\Config; use Formwork\Config\Config;
use Formwork\Languages\Languages; use Formwork\Languages\Languages;
use Formwork\Pages\Site;
use Formwork\Parsers\Yaml;
use Formwork\Schemes\Schemes; use Formwork\Schemes\Schemes;
use Formwork\Services\Container; use Formwork\Services\Container;
use Formwork\Services\ResolutionAwareServiceLoaderInterface; use Formwork\Services\ResolutionAwareServiceLoaderInterface;
use Formwork\Site;
class SiteServiceLoader implements ResolutionAwareServiceLoaderInterface class SiteServiceLoader implements ResolutionAwareServiceLoaderInterface
{ {
@ -19,12 +18,13 @@ class SiteServiceLoader implements ResolutionAwareServiceLoaderInterface
public function load(Container $container): Site public function load(Container $container): Site
{ {
$this->schemes->loadFromPath($this->config->get('system.schemes.paths.site')); $this->schemes->loadFromPath($this->config->get('system.schemes.paths.site'));
$config = Yaml::parseFile(ROOT_PATH . '/site/config/site.yaml'); $config = $this->config->get('site');
return $container->build(Site::class, ['data' => [ return $container->build(Site::class, ['data' => [
'path' => $this->config->get('system.pages.path'), ...$config,
'languages' => $this->languages, 'contentPath' => $this->config->get('system.pages.path'),
] + $config]); 'languages' => $this->languages,
]]);
} }
/** /**

View File

@ -1,19 +1,20 @@
<?php <?php
namespace Formwork\Pages; namespace Formwork;
use Formwork\App;
use Formwork\Config\Config; use Formwork\Config\Config;
use Formwork\Languages\Languages; use Formwork\Languages\Languages;
use Formwork\Metadata\MetadataCollection; use Formwork\Metadata\MetadataCollection;
use Formwork\Model\Model; use Formwork\Model\Model;
use Formwork\Pages\ContentFile;
use Formwork\Pages\Exceptions\PageNotFoundException; use Formwork\Pages\Exceptions\PageNotFoundException;
use Formwork\Pages\Page;
use Formwork\Pages\PageCollection;
use Formwork\Pages\Templates\TemplateCollection; use Formwork\Pages\Templates\TemplateCollection;
use Formwork\Pages\Templates\TemplateFactory; use Formwork\Pages\Templates\TemplateFactory;
use Formwork\Pages\Traits\PageTraversal; use Formwork\Pages\Traits\PageTraversal;
use Formwork\Pages\Traits\PageUid; use Formwork\Pages\Traits\PageUid;
use Formwork\Pages\Traits\PageUri; use Formwork\Pages\Traits\PageUri;
use Formwork\Parsers\Yaml;
use Formwork\Schemes\Schemes; use Formwork\Schemes\Schemes;
use Formwork\Utils\Arr; use Formwork\Utils\Arr;
use Formwork\Utils\FileSystem; use Formwork\Utils\FileSystem;
@ -32,10 +33,7 @@ class Site extends Model implements Stringable
*/ */
protected ?string $path = null; protected ?string $path = null;
/** protected ?string $contentPath = null;
* Site relative path
*/
protected ?string $relativePath = null;
/** /**
* Site content file * Site content file
@ -122,7 +120,7 @@ class Site extends Model implements Stringable
*/ */
public function defaults(): array public function defaults(): array
{ {
$defaults = Yaml::parseFile(SYSTEM_PATH . '/config/site.yaml'); $defaults = $this->config->getDefaults('site');
return [...$defaults, ...Arr::reject($this->fields()->pluck('default'), fn ($value) => $value === null)]; return [...$defaults, ...Arr::reject($this->fields()->pluck('default'), fn ($value) => $value === null)];
} }
@ -150,14 +148,6 @@ class Site extends Model implements Stringable
return $this->path; return $this->path;
} }
/**
* Get site relative path
*/
public function relativePath(): ?string
{
return $this->relativePath;
}
/** /**
* Get site filename * Get site filename
*/ */
@ -166,6 +156,16 @@ class Site extends Model implements Stringable
return $this->contentFile; return $this->contentFile;
} }
public function contentPath(): ?string
{
return $this->contentPath;
}
public function contentRelativePath(): ?string
{
return '/';
}
/** /**
* Get site route * Get site route
*/ */
@ -254,10 +254,10 @@ class Site extends Model implements Stringable
*/ */
public function modifiedSince(int $time): bool public function modifiedSince(int $time): bool
{ {
if ($this->path === null) { if ($this->contentPath === null) {
return false; return false;
} }
return FileSystem::directoryModifiedSince($this->path, $time); return FileSystem::directoryModifiedSince($this->contentPath, $time);
} }
/** /**
@ -322,7 +322,7 @@ class Site extends Model implements Stringable
} }
$components = explode('/', trim($route, '/')); $components = explode('/', trim($route, '/'));
$path = $this->path; $path = $this->contentPath;
if ($path === null) { if ($path === null) {
return null; return null;
@ -432,6 +432,14 @@ class Site extends Model implements Stringable
$this->fields->setValues($this->data); $this->fields->setValues($this->data);
} }
/**
* @param array<string, mixed> $metadata
*/
protected function setMetadata(array $metadata): void
{
$this->data['metadata'] = $metadata;
}
protected function loadTemplates(): void protected function loadTemplates(): void
{ {
$path = $this->config->get('system.templates.path'); $path = $this->config->get('system.templates.path');
@ -460,9 +468,12 @@ class Site extends Model implements Stringable
protected function setPath(string $path): void protected function setPath(string $path): void
{ {
$this->path = FileSystem::normalizePath($path . '/'); $this->path = $this->data['path'] = FileSystem::normalizePath($path . '/');
}
$this->relativePath = DS; protected function setContentPath(string $path): void
{
$this->contentPath = FileSystem::normalizePath($path . '/');
$this->route = '/'; $this->route = '/';

View File

@ -4,9 +4,9 @@ use Formwork\Http\JsonResponse;
use Formwork\Http\RedirectResponse; use Formwork\Http\RedirectResponse;
use Formwork\Http\Request; use Formwork\Http\Request;
use Formwork\Http\ResponseStatus; use Formwork\Http\ResponseStatus;
use Formwork\Pages\Site;
use Formwork\Panel\Panel; use Formwork\Panel\Panel;
use Formwork\Security\CsrfToken; use Formwork\Security\CsrfToken;
use Formwork\Site;
use Formwork\Translations\Translations; use Formwork\Translations\Translations;
use Formwork\Utils\FileSystem; use Formwork\Utils\FileSystem;

View File

@ -1,2 +1 @@
title: Formwork title: Formwork
description: ''