mirror of
https://github.com/archtechx/laravel-pages.git
synced 2025-12-12 01:44:03 +00:00
add source code
This commit is contained in:
commit
e534ddd14c
23 changed files with 798 additions and 0 deletions
12
.gitattributes
vendored
Normal file
12
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/.github export-ignore
|
||||
/.gitattributes export-ignore
|
||||
/.gitignore export-ignore
|
||||
|
||||
/docker-compose.yml export-ignore
|
||||
/tests export-ignore
|
||||
|
||||
/.php_cs.php export-ignore
|
||||
/psalm.xml export-ignore
|
||||
/phpunit.xml export-ignore
|
||||
/check export-ignore
|
||||
/coverage export-ignore
|
||||
39
.github/workflows/ci.yml
vendored
Normal file
39
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
name: CI
|
||||
|
||||
env:
|
||||
COMPOSE_INTERACTIVE_NO_CLI: 1
|
||||
PHP_CS_FIXER_IGNORE_ENV: 1
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
pest:
|
||||
name: Tests (Pest)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install composer dependencies
|
||||
run: composer install
|
||||
- name: Run tests
|
||||
run: vendor/bin/pest
|
||||
|
||||
php-cs-fixer:
|
||||
name: Code style (php-cs-fixer)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install php-cs-fixer
|
||||
run: composer global require friendsofphp/php-cs-fixer
|
||||
- name: Run php-cs-fixer
|
||||
run: $HOME/.composer/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php
|
||||
- name: Commit changes from php-cs-fixer
|
||||
uses: EndBug/add-and-commit@v5
|
||||
with:
|
||||
author_name: "PHP CS Fixer"
|
||||
author_email: "phpcsfixer@example.com"
|
||||
message: Fix code style (php-cs-fixer)
|
||||
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
.phpunit.result.cache
|
||||
package-lock.json
|
||||
composer.lock
|
||||
vendor/
|
||||
.php-cs-fixer.cache
|
||||
.vscode/
|
||||
coverage/
|
||||
node_modules
|
||||
141
.php-cs-fixer.php
Normal file
141
.php-cs-fixer.php
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
|
||||
use PhpCsFixer\Config;
|
||||
use PhpCsFixer\Finder;
|
||||
|
||||
$rules = [
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
'binary_operator_spaces' => [
|
||||
'default' => 'single_space',
|
||||
'operators' => [
|
||||
'=>' => null,
|
||||
'|' => 'no_space',
|
||||
]
|
||||
],
|
||||
'blank_line_after_namespace' => true,
|
||||
'blank_line_after_opening_tag' => true,
|
||||
'no_superfluous_phpdoc_tags' => true,
|
||||
'blank_line_before_statement' => [
|
||||
'statements' => ['return']
|
||||
],
|
||||
'braces' => true,
|
||||
'cast_spaces' => true,
|
||||
'class_definition' => true,
|
||||
'concat_space' => [
|
||||
'spacing' => 'one'
|
||||
],
|
||||
'declare_equal_normalize' => true,
|
||||
'elseif' => true,
|
||||
'encoding' => true,
|
||||
'full_opening_tag' => true,
|
||||
'declare_strict_types' => true,
|
||||
'fully_qualified_strict_types' => true, // added by Shift
|
||||
'function_declaration' => true,
|
||||
'function_typehint_space' => true,
|
||||
'heredoc_to_nowdoc' => true,
|
||||
'include' => true,
|
||||
'increment_style' => ['style' => 'post'],
|
||||
'indentation_type' => true,
|
||||
'linebreak_after_opening_tag' => true,
|
||||
'line_ending' => true,
|
||||
'lowercase_cast' => true,
|
||||
'constant_case' => true,
|
||||
'lowercase_keywords' => true,
|
||||
'lowercase_static_reference' => true, // added from Symfony
|
||||
'magic_method_casing' => true, // added from Symfony
|
||||
'magic_constant_casing' => true,
|
||||
'method_argument_space' => true,
|
||||
'native_function_casing' => true,
|
||||
'no_alias_functions' => true,
|
||||
'no_extra_blank_lines' => [
|
||||
'tokens' => [
|
||||
'extra',
|
||||
'throw',
|
||||
'use',
|
||||
'use_trait',
|
||||
]
|
||||
],
|
||||
'no_blank_lines_after_class_opening' => true,
|
||||
'no_blank_lines_after_phpdoc' => true,
|
||||
'no_closing_tag' => true,
|
||||
'no_empty_phpdoc' => true,
|
||||
'no_empty_statement' => true,
|
||||
'no_leading_import_slash' => true,
|
||||
'no_leading_namespace_whitespace' => true,
|
||||
'no_mixed_echo_print' => [
|
||||
'use' => 'echo'
|
||||
],
|
||||
'no_multiline_whitespace_around_double_arrow' => true,
|
||||
'multiline_whitespace_before_semicolons' => [
|
||||
'strategy' => 'no_multi_line'
|
||||
],
|
||||
'no_short_bool_cast' => true,
|
||||
'no_singleline_whitespace_before_semicolons' => true,
|
||||
'no_spaces_after_function_name' => true,
|
||||
'no_spaces_around_offset' => true,
|
||||
'no_spaces_inside_parenthesis' => true,
|
||||
'no_trailing_comma_in_list_call' => true,
|
||||
'no_trailing_comma_in_singleline_array' => true,
|
||||
'no_trailing_whitespace' => true,
|
||||
'no_trailing_whitespace_in_comment' => true,
|
||||
'no_unneeded_control_parentheses' => true,
|
||||
'no_unreachable_default_argument_value' => true,
|
||||
'no_useless_return' => true,
|
||||
'no_whitespace_before_comma_in_array' => true,
|
||||
'no_whitespace_in_blank_line' => true,
|
||||
'normalize_index_brace' => true,
|
||||
'not_operator_with_successor_space' => true,
|
||||
'object_operator_without_whitespace' => true,
|
||||
'ordered_imports' => ['sort_algorithm' => 'alpha'],
|
||||
'phpdoc_indent' => true,
|
||||
'general_phpdoc_tag_rename' => true,
|
||||
'phpdoc_no_access' => true,
|
||||
'phpdoc_no_package' => true,
|
||||
'phpdoc_no_useless_inheritdoc' => true,
|
||||
'phpdoc_scalar' => true,
|
||||
'phpdoc_single_line_var_spacing' => true,
|
||||
'phpdoc_summary' => true,
|
||||
'phpdoc_to_comment' => false,
|
||||
'phpdoc_trim' => true,
|
||||
'phpdoc_types' => true,
|
||||
'phpdoc_var_without_name' => true,
|
||||
'psr_autoloading' => true,
|
||||
'self_accessor' => true,
|
||||
'short_scalar_cast' => true,
|
||||
'simplified_null_return' => false, // disabled by Shift
|
||||
'single_blank_line_at_eof' => true,
|
||||
'single_blank_line_before_namespace' => true,
|
||||
'single_class_element_per_statement' => true,
|
||||
'single_import_per_statement' => true,
|
||||
'single_line_after_imports' => true,
|
||||
'no_unused_imports' => true,
|
||||
'single_line_comment_style' => [
|
||||
'comment_types' => ['hash']
|
||||
],
|
||||
'single_quote' => true,
|
||||
'space_after_semicolon' => true,
|
||||
'standardize_not_equals' => true,
|
||||
'switch_case_semicolon_to_colon' => true,
|
||||
'switch_case_space' => true,
|
||||
'ternary_operator_spaces' => true,
|
||||
'trailing_comma_in_multiline' => true,
|
||||
'trim_array_spaces' => true,
|
||||
'unary_operator_spaces' => true,
|
||||
'whitespace_after_comma_in_array' => true,
|
||||
];
|
||||
|
||||
$project_path = getcwd();
|
||||
$finder = Finder::create()
|
||||
->in([
|
||||
$project_path . '/src',
|
||||
])
|
||||
->name('*.php')
|
||||
->notName('*.blade.php')
|
||||
->ignoreDotFiles(true)
|
||||
->ignoreVCS(true);
|
||||
|
||||
return (new Config())
|
||||
->setFinder($finder)
|
||||
->setRules($rules)
|
||||
->setRiskyAllowed(true)
|
||||
->setUsingCache(true);
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 ArchTech Development, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
116
README.md
Normal file
116
README.md
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
# Laravel Pages
|
||||
|
||||
This package lets you create pages using Markdown or Blade without having to worry about creating routes or controllers yourself.
|
||||
|
||||
Essentially, you create either `content/pages/foo.md` or `resources/views/pages/foo.blade.php`.
|
||||
|
||||
Markdown files use a pre-defined Blade view to get rendered. Blade files are meant for pages which don't follow the default layout and need more custom styling.
|
||||
|
||||
For instance, you could have the `/pricing` route use a Blade file (`pages/pricing.blade.php`) with a pretty design that accompanies your pricing copy.
|
||||
|
||||
Whereas for `/about`, you could have a simple Markdown file (`content/pages/about.md`) that describes your service using pure text without any special graphical elements.
|
||||
|
||||
We use this on the ArchTech website — the [About](https://archte.ch/about), [Careers](https://archte.ch/careers), and [Open source](https://archte.ch/open-source) pages are simple Markdown files.
|
||||
|
||||
## Installation
|
||||
|
||||
Require the package via composer:
|
||||
|
||||
```
|
||||
composer require archtechx/laravel-pages
|
||||
```
|
||||
|
||||
Publish the config file:
|
||||
|
||||
```
|
||||
php artisan vendor:publish --tag=archtech-pages-config
|
||||
```
|
||||
|
||||
And finally, add this line to the **end** of your `routes/web.php` file:
|
||||
|
||||
```php
|
||||
ArchTech\Pages\Page::routes();
|
||||
```
|
||||
|
||||
This line will register the routes in a way that ensures that your routes take precedence, and the page route is only used as the final option.
|
||||
|
||||
## Usage
|
||||
|
||||
### Markdown pages
|
||||
|
||||
To create a markdown file, create a file in `content/pages/`. The route to the page will match the file name (without `.md`).
|
||||
|
||||
For example, to create the `/about` page, create `content/pages/about.md` with this content:
|
||||
|
||||
```md
|
||||
---
|
||||
slug: about
|
||||
title: 'About us'
|
||||
updated_at: 2021-05-19T19:09:02+00:00
|
||||
created_at: 2021-05-19T19:09:02+00:00
|
||||
---
|
||||
|
||||
We are a web development agency that specializes in ...
|
||||
```
|
||||
|
||||
### Blade pages
|
||||
|
||||
To create a Blade page, create a file in `resources/views/pages/`. Like in the Markdown example, the route to the page will match the file name without the extension.
|
||||
|
||||
Therefore to create the `/about` page, you'd create `resources/views/pages/about.blade.php`:
|
||||
|
||||
```html
|
||||
<x-app-layout>
|
||||
This view can use any layouts or markup.
|
||||
</x-app-layout>
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
You'll likely want to configure a few things, most likely the used layout.
|
||||
|
||||
To do that, simply modify `config/pages.php`.
|
||||
|
||||
The config file lets you change:
|
||||
- the used model
|
||||
- the used controller
|
||||
- the layout used by the markdown views
|
||||
- the view file used to render Markdown pages
|
||||
- routing details
|
||||
|
||||
The layout is used *by* the vendor (package-provided) Markdown view. You'll likely want to set it to something like ``app-layout` or `layouts.app`.`
|
||||
|
||||
If you'd like to change the file that renders the Markdown itself, create `resources/views/pages/_markdown.blade.php` (the `_` prefix is important as it prevents direct visits) and change the `pages.views.markdown` config key to `pages._markdown`.
|
||||
|
||||
And if you'd like to customize the routing logic more ethan the config file allows you, simply register the route yourself (instead of calling `Page::routes()`):
|
||||
|
||||
```php
|
||||
Route::get('/{page}', ArchTech\Pages\PageController::class);
|
||||
```
|
||||
|
||||
## Ecosystem support
|
||||
|
||||
The package perfectly supports other tools in the ecosystem, such as [Laravel Nova](https://nova.laravel.com) or [Lean Admin](https://lean-admin.dev).
|
||||
|
||||
For example, in Laravel Nova you could create a resource for the package-provided `Page` model (`ArchTech\Pages\Page`) and use the following field schema:
|
||||
|
||||
```php
|
||||
public function fields(Request $request)
|
||||
{
|
||||
return [
|
||||
Text::make('slug'),
|
||||
Text::make('title'),
|
||||
Markdown::make('content'),
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
## Git integration & Orbit
|
||||
|
||||
This package uses [Orbit](https://github.com/ryangjchandler/orbit) under the hood — to manage the Markdown files as Eloquent models. If you'd like to customize some things related to that logic, take a look at the Orbit documentation.
|
||||
|
||||
The package also uses another package of ours, [Laravel SEO](https://github.com/archtechx/laravel-seo), to provide meta tag support for Markdown pages. We recommended that you use this package yourself, since it will make handling meta tags as easy as adding the following line to your layout's `<head>` section:
|
||||
|
||||
```html
|
||||
<x-seo::meta />
|
||||
```
|
||||
36
assets/config.php
Normal file
36
assets/config.php
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'model' => ArchTech\Pages\Page::class,
|
||||
|
||||
'views' => [
|
||||
/**
|
||||
* The layout used to render the pages.
|
||||
*
|
||||
* @example app-layout For resources/views/app-layout.blade.php
|
||||
* @example layouts.app For resources/views/layouts.app.blade.php
|
||||
*/
|
||||
'layout' => 'app-layout',
|
||||
|
||||
/**
|
||||
* The path to your views.
|
||||
*
|
||||
* @example 'pages.' The package will look into resources/views/pages
|
||||
* @example 'foo::' The package will look into the 'foo' view namespace
|
||||
*/
|
||||
'path' => 'pages.',
|
||||
|
||||
/**
|
||||
* The name of the view used to render markdown pages.
|
||||
*
|
||||
* @example 'pages._markdown' The package will use resources/views/pages/_markdown.blade.php
|
||||
*/
|
||||
'markdown' => 'pages::_markdown',
|
||||
],
|
||||
|
||||
'routes' => [
|
||||
'name' => 'page',
|
||||
'prefix' => '',
|
||||
'handler' => ArchTech\Pages\PageController::class,
|
||||
],
|
||||
];
|
||||
9
assets/views/_markdown.blade.php
Normal file
9
assets/views/_markdown.blade.php
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<x-dynamic-component :component="config('pages.views.layout')">
|
||||
<div class="w-full flex justify-center my-16 px-4">
|
||||
<div class="prose prose-indigo">
|
||||
<h1>{{ $page->title }}</h1>
|
||||
|
||||
{!! Str::markdown($page->content) !!}
|
||||
</div>
|
||||
</div>
|
||||
</x-dynamic-component>
|
||||
47
check
Executable file
47
check
Executable file
|
|
@ -0,0 +1,47 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
offer_run() {
|
||||
read -p "For more output, run $1. Run it now (Y/n)? " run
|
||||
|
||||
case ${run:0:1} in
|
||||
n|N )
|
||||
exit 1
|
||||
;;
|
||||
* )
|
||||
$1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (php-cs-fixer fix --dry-run --config=.php-cs-fixer.php > /dev/null 2>/dev/null); then
|
||||
echo '✅ php-cs-fixer OK'
|
||||
else
|
||||
read -p "⚠️ php-cs-fixer found issues. Fix (Y/n)? " fix
|
||||
case ${fix:0:1} in
|
||||
n|N )
|
||||
echo '❌ php-cs-fixer FAIL'
|
||||
offer_run 'php-cs-fixer fix --config=.php-cs-fixer.php'
|
||||
;;
|
||||
* )
|
||||
if (php-cs-fixer fix --config=.php-cs-fixer.php > /dev/null 2>/dev/null); then
|
||||
echo '✅ php-cs-fixer OK'
|
||||
else
|
||||
echo '❌ php-cs-fixer FAIL'
|
||||
offer_run 'php-cs-fixer fix --config=.php-cs-fixer.php'
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if (./vendor/bin/pest > /dev/null 2>/dev/null); then
|
||||
echo '✅ PEST OK'
|
||||
else
|
||||
echo '❌ PEST FAIL'
|
||||
offer_run './vendor/bin/pest'
|
||||
fi
|
||||
|
||||
echo '=================='
|
||||
echo '✅ Everything OK'
|
||||
42
composer.json
Normal file
42
composer.json
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"name": "archtechx/laravel-pages",
|
||||
"description": "",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Samuel Štancl",
|
||||
"email": "samuel@archte.ch"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ArchTech\\Pages\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"ArchTech\\Pages\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"illuminate/support": "^8.24",
|
||||
"archtechx/laravel-seo": "^0.2.2",
|
||||
"ryangjchandler/orbit": "^0.9.0",
|
||||
"illuminate/routing": "^8.53",
|
||||
"illuminate/database": "^8.53"
|
||||
},
|
||||
"require-dev": {
|
||||
"orchestra/testbench": "^6.9",
|
||||
"pestphp/pest": "^1.2",
|
||||
"pestphp/pest-plugin-laravel": "^1.0"
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"ArchTech\\Pages\\PackageServiceProvider"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
33
phpunit.xml
Normal file
33
phpunit.xml
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" backupStaticAttributes="false" bootstrap="vendor/autoload.php" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
|
||||
<coverage processUncoveredFiles="true">
|
||||
<include>
|
||||
<directory suffix=".php">./src</directory>
|
||||
</include>
|
||||
<report>
|
||||
<clover outputFile="coverage/phpunit/clover.xml"/>
|
||||
<html outputDirectory="coverage/phpunit/html" lowUpperBound="35" highLowerBound="70"/>
|
||||
</report>
|
||||
</coverage>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory suffix="Test.php">./tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<php>
|
||||
<env name="APP_ENV" value="testing"/>
|
||||
<env name="APP_KEY" value="base64:uYlmYxcuuO7dC34yUn2hQcPu8PnlC98LTyOZg4fNAZU="/>
|
||||
<env name="BCRYPT_ROUNDS" value="4"/>
|
||||
<env name="CACHE_DRIVER" value="redis"/>
|
||||
<env name="MAIL_DRIVER" value="array"/>
|
||||
<env name="QUEUE_CONNECTION" value="sync"/>
|
||||
<env name="SESSION_DRIVER" value="array"/>
|
||||
|
||||
<env name="DB_CONNECTION" value="testbench"/>
|
||||
<env name="DB_DATABASE" value="main"/>
|
||||
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
|
||||
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
|
||||
|
||||
<env name="AWS_DEFAULT_REGION" value="us-west-2"/>
|
||||
</php>
|
||||
</phpunit>
|
||||
41
src/Page.php
Normal file
41
src/Page.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ArchTech\Pages;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Orbit\Concerns\Orbital;
|
||||
|
||||
class Page extends Model
|
||||
{
|
||||
use Orbital;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public static function schema(Blueprint $table)
|
||||
{
|
||||
$table->string('slug');
|
||||
$table->string('title');
|
||||
$table->longText('content');
|
||||
}
|
||||
|
||||
public function getKeyName()
|
||||
{
|
||||
return 'slug';
|
||||
}
|
||||
|
||||
public function getIncrementing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function routes(): void
|
||||
{
|
||||
Route::get('/{page}', config('pages.routes.handler'))
|
||||
->prefix(config('pages.routes.prefix'))
|
||||
->name(config('pages.routes.name'));
|
||||
}
|
||||
}
|
||||
33
src/PageController.php
Normal file
33
src/PageController.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ArchTech\Pages;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class PageController
|
||||
{
|
||||
public function __invoke(string $page)
|
||||
{
|
||||
if (str_starts_with($page, '_')) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$view = config('pages.views.path') . $page;
|
||||
|
||||
if (view()->exists($view)) {
|
||||
return view($view);
|
||||
}
|
||||
|
||||
if ($model = config('pages.model')::find($page)) {
|
||||
seo()
|
||||
->title($model->title)
|
||||
->description(Str::limit($model->content, 100));
|
||||
|
||||
return view(config('pages.views.markdown'), ['page' => $model]);
|
||||
}
|
||||
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
28
src/PagesServiceProvider.php
Normal file
28
src/PagesServiceProvider.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ArchTech\Pages;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class PagesServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadViewsFrom(__DIR__ . '/../assets/views', 'pages');
|
||||
$this->mergeConfigFrom(__DIR__ . '/../assets/config.php', 'pages');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/../assets/views' => resource_path('views/vendor/pages'),
|
||||
], 'archtech-pages-views');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/../assets/config.php' => config_path('pages.php'),
|
||||
], 'archtech-pages-config');
|
||||
}
|
||||
}
|
||||
22
tests/CreatesApplication.php
Normal file
22
tests/CreatesApplication.php
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use Illuminate\Contracts\Console\Kernel;
|
||||
|
||||
trait CreatesApplication
|
||||
{
|
||||
/**
|
||||
* Creates the application.
|
||||
*
|
||||
* @return \Illuminate\Foundation\Application
|
||||
*/
|
||||
public function createApplication()
|
||||
{
|
||||
$app = require __DIR__.'/../bootstrap/app.php';
|
||||
|
||||
$app->make(Kernel::class)->bootstrap();
|
||||
|
||||
return $app;
|
||||
}
|
||||
}
|
||||
79
tests/Feature/PagesTest.php
Normal file
79
tests/Feature/PagesTest.php
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
use ArchTech\Pages\Page;
|
||||
|
||||
beforeEach(function () {
|
||||
Page::routes();
|
||||
|
||||
Page::query()->delete();
|
||||
|
||||
view()->addNamespace('test', __DIR__ . '/../views');
|
||||
|
||||
config([
|
||||
'pages.views.layout' => 'test::layout',
|
||||
'pages.views.path' => 'test::',
|
||||
'orbit.paths.content' => __DIR__ . '/../orbit/content',
|
||||
'orbit.paths.cache' => __DIR__ . '/../orbit/cache',
|
||||
]);
|
||||
});
|
||||
|
||||
test('a view is shown if it exists')
|
||||
->get('/example')
|
||||
->assertSee('Test view');
|
||||
|
||||
test('markdown is rendered if it exists', function () {
|
||||
Page::create([
|
||||
'slug' => 'test',
|
||||
'title' => 'Markdown page',
|
||||
'content' => 'This is a **test page**'
|
||||
]);
|
||||
|
||||
using($this)
|
||||
->get('/test')
|
||||
->assertSee('Markdown page')
|
||||
->assertSee('<strong>test page</strong>', false);
|
||||
});
|
||||
|
||||
test('view takes precedence over markdown', function () {
|
||||
Page::create([
|
||||
'slug' => 'example',
|
||||
'title' => 'Test page',
|
||||
'content' => 'This is a test page'
|
||||
]);
|
||||
|
||||
using($this)
|
||||
->get('/example')
|
||||
->assertSee('Test view')
|
||||
->assertDontSee('Test page');
|
||||
});
|
||||
|
||||
test('404 is returned if no view or markdown is found')
|
||||
->get('/foo')
|
||||
->assertNotFound();
|
||||
|
||||
test('a custom layout can be used', function () {
|
||||
config(['pages.views.layout' => 'test::layout2']);
|
||||
|
||||
Page::create([
|
||||
'slug' => 'test',
|
||||
'title' => 'Test page',
|
||||
'content' => 'This is a test page'
|
||||
]);
|
||||
|
||||
using($this)
|
||||
->get('/test')
|
||||
->assertSee('second layout');
|
||||
});
|
||||
|
||||
test('SEO metadata is set on markdown pages', function () {
|
||||
Page::create([
|
||||
'slug' => 'test',
|
||||
'title' => 'Test page',
|
||||
'content' => 'This is a test page'
|
||||
]);
|
||||
|
||||
using($this)
|
||||
->get('/test')
|
||||
->assertSee('<meta property="og:title" content="Test page" />', false)
|
||||
->assertSee('<meta property="og:description" content="This is a test page" />', false);
|
||||
});
|
||||
47
tests/Pest.php
Normal file
47
tests/Pest.php
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Test Case
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The closure you provide to your test functions is always bound to a specific PHPUnit test
|
||||
| case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may
|
||||
| need to change it using the "uses()" function to bind a different classes or traits.
|
||||
|
|
||||
*/
|
||||
|
||||
use ArchTech\Pages\Tests\TestCase;
|
||||
|
||||
uses(ArchTech\Pages\Tests\TestCase::class)->in('Feature');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Expectations
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When you're writing tests, you often need to check that values meet certain conditions. The
|
||||
| "expect()" function gives you access to a set of "expectations" methods that you can use
|
||||
| to assert different things. Of course, you may extend the Expectation API at any time.
|
||||
|
|
||||
*/
|
||||
|
||||
expect()->extend('toBeOne', function () {
|
||||
return $this->toBe(1);
|
||||
});
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Functions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| While Pest is very powerful out-of-the-box, you may have some testing code specific to your
|
||||
| project that you don't want to repeat in every file. Here you can also expose helpers as
|
||||
| global functions to help you to reduce the number of lines of code in your test files.
|
||||
|
|
||||
*/
|
||||
|
||||
function using($test): TestCase
|
||||
{
|
||||
return $test;
|
||||
}
|
||||
20
tests/TestCase.php
Normal file
20
tests/TestCase.php
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace ArchTech\Pages\Tests;
|
||||
|
||||
use Orchestra\Testbench\TestCase as TestbenchTestCase;
|
||||
use ArchTech\Pages\PagesServiceProvider;
|
||||
use ArchTech\SEO\SEOServiceProvider;
|
||||
use Orbit\OrbitServiceProvider;
|
||||
|
||||
class TestCase extends TestbenchTestCase
|
||||
{
|
||||
protected function getPackageProviders($app)
|
||||
{
|
||||
return [
|
||||
SEOServiceProvider::class,
|
||||
OrbitServiceProvider::class,
|
||||
PagesServiceProvider::class,
|
||||
];
|
||||
}
|
||||
}
|
||||
7
tests/orbit/content/pages/example.md
Normal file
7
tests/orbit/content/pages/example.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
slug: example
|
||||
title: 'Test page'
|
||||
updated_at: 2021-08-06T02:25:15+00:00
|
||||
created_at: 2021-08-06T02:25:15+00:00
|
||||
---
|
||||
This is a test page
|
||||
7
tests/orbit/content/pages/test.md
Normal file
7
tests/orbit/content/pages/test.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
slug: test
|
||||
title: 'Test page'
|
||||
updated_at: 2021-08-06T02:25:15+00:00
|
||||
created_at: 2021-08-06T02:25:15+00:00
|
||||
---
|
||||
This is a test page
|
||||
4
tests/views/components/layout.blade.php
Normal file
4
tests/views/components/layout.blade.php
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<div class="first layout">
|
||||
<x-seo::meta />
|
||||
{{ $slot }}
|
||||
</div>
|
||||
3
tests/views/components/layout2.blade.php
Normal file
3
tests/views/components/layout2.blade.php
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<div class="second layout">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
3
tests/views/example.blade.php
Normal file
3
tests/views/example.blade.php
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<x-test::layout>
|
||||
Test view
|
||||
</x-test::layout>
|
||||
Loading…
Add table
Add a link
Reference in a new issue