From f5263ddc7856ba61353e37c3829568f5d2f2c2e7 Mon Sep 17 00:00:00 2001 From: Mischa Date: Sat, 18 Apr 2026 23:43:45 +0200 Subject: [PATCH] Add error plugin v1.8.1 Co-Authored-By: Claude Sonnet 4.6 --- plugins/error/CHANGELOG.md | 98 ++++ plugins/error/LICENSE | 21 + plugins/error/README.md | 93 ++++ plugins/error/assets/readme_1.png | Bin 0 -> 41685 bytes plugins/error/blueprints.yaml | 36 ++ plugins/error/cli/LogCommand.php | 166 +++++++ plugins/error/composer.json | 39 ++ plugins/error/error.php | 117 +++++ plugins/error/error.yaml | 3 + plugins/error/hebe.json | 15 + plugins/error/languages.yaml | 55 +++ plugins/error/pages/error.md | 14 + plugins/error/templates/error.html.twig | 3 + plugins/error/templates/error.json.twig | 1 + plugins/error/vendor/autoload.php | 7 + plugins/error/vendor/composer/ClassLoader.php | 445 ++++++++++++++++++ plugins/error/vendor/composer/LICENSE | 21 + .../vendor/composer/autoload_classmap.php | 10 + .../vendor/composer/autoload_namespaces.php | 9 + .../error/vendor/composer/autoload_psr4.php | 10 + .../error/vendor/composer/autoload_real.php | 52 ++ .../error/vendor/composer/autoload_static.php | 36 ++ plugins/error/vendor/composer/installed.json | 1 + 23 files changed, 1252 insertions(+) create mode 100644 plugins/error/CHANGELOG.md create mode 100644 plugins/error/LICENSE create mode 100644 plugins/error/README.md create mode 100644 plugins/error/assets/readme_1.png create mode 100644 plugins/error/blueprints.yaml create mode 100644 plugins/error/cli/LogCommand.php create mode 100644 plugins/error/composer.json create mode 100644 plugins/error/error.php create mode 100644 plugins/error/error.yaml create mode 100644 plugins/error/hebe.json create mode 100644 plugins/error/languages.yaml create mode 100644 plugins/error/pages/error.md create mode 100644 plugins/error/templates/error.html.twig create mode 100644 plugins/error/templates/error.json.twig create mode 100644 plugins/error/vendor/autoload.php create mode 100644 plugins/error/vendor/composer/ClassLoader.php create mode 100644 plugins/error/vendor/composer/LICENSE create mode 100644 plugins/error/vendor/composer/autoload_classmap.php create mode 100644 plugins/error/vendor/composer/autoload_namespaces.php create mode 100644 plugins/error/vendor/composer/autoload_psr4.php create mode 100644 plugins/error/vendor/composer/autoload_real.php create mode 100644 plugins/error/vendor/composer/autoload_static.php create mode 100644 plugins/error/vendor/composer/installed.json diff --git a/plugins/error/CHANGELOG.md b/plugins/error/CHANGELOG.md new file mode 100644 index 0000000..80cd6cb --- /dev/null +++ b/plugins/error/CHANGELOG.md @@ -0,0 +1,98 @@ +# v1.8.1 +## 08/28/2025 + +1. [](#bugfix) + * Fixed an issue with error thrown during `bin/plugin error log` commands [#46](https://github.com/getgrav/grav-plugin-error/issues/46) + * Fixed output issue not showing all messages with log CLI command + +# v1.8.0 +## 09/07/2021 + +1. [](#new) + * Require **Grav 1.7.0** + * Added support for `{% throw 404 'Not Found' %}` from twig template to show the error page +1. [](#improved) + * Do not cache 404 error pages by default + +# v1.7.1 +## 10/08/2020 + +1. [](#bugfix) + * Fixed error page being cached, fixes issue with non-existing resources which later become available + +# v1.7.0 +## 07/01/2020 + +1. [](#new) + * Require Grav v1.6 +1. [](#bugfix) + * Added translated title programmatically [#40](https://github.com/getgrav/grav-plugin-error/pull/40) + +# v1.6.2 +## 05/09/2019 + +1. [](#new) + * Fixed a few issues found by phpstan + * Added `ru` and `uk` translations [#36](https://github.com/getgrav/grav-plugin-error/pull/36) + +# v1.6.1 +## 03/09/2018 + +1. [](#improved) + * Added Polish + Catalan translation + * Updated `README.md` to reference custom error pages + +# v1.6.0 +## 10/19/2016 + +1. [](#improved) + * Added Croatian translation + * Improved `autoescape: true` support +1. [](#bugfix) + * Fixed issue where template file for `error` page type is only available if page was not found + +# v1.5.1 +## 07/18/2016 + +1. [](#improved) + * Added chinese and german translations +1. [](#bugfix) + * Fixed issue with the Smartypants plugin running before Twig was processed + +# v1.5.0 +## 07/14/2015 + +1. [](#improved) + * Translate some blueprint configuration options + * Allow translating the error message + * Added french, russian, romanian, danish, italian + +# v1.4.1 +## 12/11/2015 + +1. [](#bugfix) + * Fixed CLI command for PHP 5.5 and lower + +# v1.4.0 +## 11/21/2015 + +1. [](#new) + * Implemented CLI commands for the plugin + +# v1.3.0 +## 08/25/2015 + +1. [](#improved) + * Added blueprints for Grav Admin plugin + +# v1.2.2 +## 01/06/2015 + +1. [](#new) + * Added a default `error.json.twig` file + +# v1.2.1 +## 11/30/2014 + +1. [](#new) + * ChangeLog started... diff --git a/plugins/error/LICENSE b/plugins/error/LICENSE new file mode 100644 index 0000000..484793a --- /dev/null +++ b/plugins/error/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Grav + +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. diff --git a/plugins/error/README.md b/plugins/error/README.md new file mode 100644 index 0000000..ef24726 --- /dev/null +++ b/plugins/error/README.md @@ -0,0 +1,93 @@ +# Grav Error Plugin + +![GPM Installation](assets/readme_1.png) + +`error` is a [Grav](http://github.com/getgrav/grav) Plugin and allows to redirect errors to nice output pages. + +This plugin is included in any package distributed that contains Grav. If you decide to clone Grav from GitHub you will most likely want to install this. + +# Installation + +Installing the Error plugin can be done in one of two ways. Our GPM (Grav Package Manager) installation method enables you to quickly and easily install the plugin with a simple terminal command, while the manual method enables you to do so via a zip file. + +## GPM Installation (Preferred) + +The simplest way to install this plugin is via the [Grav Package Manager (GPM)](http://learn.getgrav.org/advanced/grav-gpm) through your system's Terminal (also called the command line). From the root of your Grav install type: + + bin/gpm install error + +This will install the Error plugin into your `/user/plugins` directory within Grav. Its files can be found under `/your/site/grav/user/plugins/error`. + +## Manual Installation + +To install this plugin, just download the zip version of this repository and unzip it under `/your/site/grav/user/plugins`. Then, rename the folder to `error`. You can find these files either on [GitHub](https://github.com/getgrav/grav-plugin-error) or via [GetGrav.org](http://getgrav.org/downloads/plugins#extras). + +You should now have all the plugin files under + + /your/site/grav/user/plugins/error + +>> NOTE: This plugin is a modular component for Grav which requires [Grav](http://github.com/getgrav/grav), the [Problems](https://github.com/getgrav/grav-plugin-problems) plugin, and a theme to be installed in order to operate. + +# Usage + +The `error` plugin doesn't require any configuration. The moment you install it, it is ready to use. + +Something you might want to do is to override the look and feel of the error page, and with Grav it is super easy. + +### Template + +Copy the template file [error.html.twig](templates/error.html.twig) into the `templates` folder of your custom theme and that is it. + +``` +/your/site/grav/user/themes/custom-theme/templates/error.html.twig +``` + +You can now edit the override and tweak it however you prefer. + +### Page + +Copy the page file [error.md](pages/error.md) into the `pages` folder of your user directory and that is it. + +``` +/your/site/grav/user/pages/error/error.md +``` + +You can now edit the override and tweak it however you prefer. + +# Custom error pages + +The configuration allows to specify pages different than `/error` for specific error codes. By default, the `404` error leads to the `/error` page. If you change that, make sure the page you point to has a `error` template (which means, its markdown file is `error.md` or in the page frontmatter you specify `template: error`. + +# CLI Usage +The `error` plugin comes with a CLI command that outputs the `grav.log` in a beautified way, with possibility of limiting the amount of errors displayed, as well as include the trace in the output. + +### Commands + +| `bin/plugin error log` | | +|------------------------|-----------------------------------------------------------------| +| [ --limit N \| -l N ] | The amount of errors to display. Default is 5 | +| [ --trace \| -t ] | When used, it will add the backtrace in the output of the error | + + +# Updating + +As development for the Error plugin continues, new versions may become available that add additional features and functionality, improve compatibility with newer Grav releases, and generally provide a better user experience. Updating Error is easy, and can be done through Grav's GPM system, as well as manually. + +## GPM Update (Preferred) + +The simplest way to update this plugin is via the [Grav Package Manager (GPM)](http://learn.getgrav.org/advanced/grav-gpm). You can do this with this by navigating to the root directory of your Grav install using your system's Terminal (also called command line) and typing the following: + + bin/gpm update error + +This command will check your Grav install to see if your Error plugin is due for an update. If a newer release is found, you will be asked whether or not you wish to update. To continue, type `y` and hit enter. The plugin will automatically update and clear Grav's cache. + +## Manual Update + +Manually updating Error is pretty simple. Here is what you will need to do to get this done: + +* Delete the `your/site/user/plugins/error` directory. +* Download the new version of the Error plugin from either [GitHub](https://github.com/getgrav/grav-plugin-error) or [GetGrav.org](http://getgrav.org/downloads/plugins#extras). +* Unzip the zip file in `your/site/user/plugins` and rename the resulting folder to `error`. +* Clear the Grav cache. The simplest way to do this is by going to the root Grav directory in terminal and typing `bin/grav clear-cache`. + +> Note: Any changes you have made to any of the files listed under this directory will also be removed and replaced by the new set. Any files located elsewhere (for example a YAML settings file placed in `user/config/plugins`) will remain intact. diff --git a/plugins/error/assets/readme_1.png b/plugins/error/assets/readme_1.png new file mode 100644 index 0000000000000000000000000000000000000000..930b87bb017916a5c9ecb4e71cb3eb672bafed22 GIT binary patch literal 41685 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
bWh;kXEr` z^wew|BQi1(1LB`0G&7a;iFCysGw)3t36kP5F6#@VB^$bo1# zwcKX7=F+M~<=y2C3lsvlS!NguTV4-~algnh`$-um@g9N#mlmS6iL~VQ6NqAx=-xs# zL{pS5tXfn)_@{m#LLgxSSwtoAeLT1gCtW-qoqD8^rh;glY3B*OMmA2Jf29D(;3y|ir&mr#Ut9eI@mMRLn??uPDzkYt>|rxaYqUI03QAQoSoAz@w{V>p zIG@4(GkCpan;(<2-~Sw&tte2@Kne%6g>#~QVB`8d9k7#HZat2J>CtAJNl&mnaRz#vxYo+$mfMFOzlLzO zC)qkz%T%b;jrH(Z$?6AjPy&U)qS)4}t(&a9)J^w)i(38bq;zbFbm7c)e72< zPo0$W$682n&4R;%ggBYv1wtNLFrw4er?jjHIWjLQ=tATUq*Jk1bqw+W#kKT8p3w!^y1MhDll(xmgjf?)TKcEhGfEs<&IdB-)Q zn9>645u7NLZijVni{s+YSx$WEcIa>i%evBY)QSee%-u$K;^U;O zyLdDH8qu!a4SBhbj*qiIoWf1M7w>a{ZFCT<@P-|1mwF#+S;~07)haKKoVgzLihbLD zo!ocu$}?CwKUPAZ_aWENvr>|cIe5C;Du@S8Q zhvubvq|8kqzT3`p-|LzjHhYt5ZNC_<>5Rb9N_WSDd`MS&2F&HYBWiQ^(6zwEbCw?C z6Be0Ht!Twm%hTqu)!Ctp$T}1vBIFkDHk;LWF+byFiCrAp5ImgIA<#kg>DT~Apci5^ zr5v|Zc%c5=D03`+tkU?&XO1`V7a1es9&fQZ&Tkt0O}9<$L(Th_QcIL}My*32aV=A< zL^7%)3Zx#SkZZQ(;+H-IE4&$VoErFL8GgXM?+7!5{qW?@}LGjUD1!-X&#ypcNQ(7+fA|Dr<#`AWf!Z3th=H^ z9vTdxEN|FVqr{5}as@T5dz@5|*f_7zqZUJk;@eL;2ww%Rrre*YkC#U2QG-92kc1H~ zqbC^X!e{YrL;UNUA1}P;x8&Fb{pxvVNkep-=;U6^pG+!stqiMF8XsGU42q{nM>)0P zrdobB6m7O)1Dn(chO)l@0_%3LV)iu{UyfQbaW!|8OlAC_#n+ea$B`>xC)@n)qiPN} zA}NplXfi1oy2_@zO~PL7wby$r=URPd;mz2@qsBf3>8AxwANSXL5wEFj8qx2TEiQ#x zCT@epU)0=VS>$Xiq9RkZ;#MoyM-8u2vi0*tEg*|Q;#xyS>|gb#U|r>H+mG!L7L$i7 zO-0RK^qBhdwR48BpL!xvT#|WuXRJ}Ll&rT+?TDd3e#TdLXRQ%*xUw#3|A-gy1Eo5s zT*Okn8S%-|oA3U%KalgUNeYFa8Qh=Af-SJxP|3X^$=Qw{G^8cfs*N?1hT0Gp-SY7SxvjhC6qNI5jb^FoF F{{vy?43_`^ literal 0 HcmV?d00001 diff --git a/plugins/error/blueprints.yaml b/plugins/error/blueprints.yaml new file mode 100644 index 0000000..9525760 --- /dev/null +++ b/plugins/error/blueprints.yaml @@ -0,0 +1,36 @@ +name: Error +version: 1.8.1 +description: Displays the error page. +type: plugin +slug: error +icon: warning +author: + name: Team Grav + email: devs@getgrav.org + url: http://getgrav.org +homepage: https://github.com/getgrav/grav-plugin-error +keywords: error, plugin, required +bugs: https://github.com/getgrav/grav-plugin-error/issues +license: MIT +dependencies: + - { name: grav, version: '>=1.7.0' } + +form: + validation: strict + fields: + enabled: + type: toggle + label: PLUGIN_ADMIN.PLUGIN_STATUS + highlight: 1 + default: 0 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + + routes.404: + type: text + size: medium + label: PLUGIN_ERROR.ROUTE_404 + default: '/error' diff --git a/plugins/error/cli/LogCommand.php b/plugins/error/cli/LogCommand.php new file mode 100644 index 0000000..583d231 --- /dev/null +++ b/plugins/error/cli/LogCommand.php @@ -0,0 +1,166 @@ + 'green', + 'INFO' => 'cyan', + 'NOTICE' => 'yellow', + 'WARNING' => 'yellow', + 'ERROR' => 'red', + 'CRITICAL' => 'red', + 'ALERT' => 'red', + 'EMERGENCY' => 'magenta' + ]; + + /** + * + */ + protected function configure() + { + $this->logfile = LOG_DIR . 'grav.log'; + $this + ->setName("log") + ->setDescription("Outputs the Error Log") + ->addOption( + 'trace', + 't', + InputOption::VALUE_NONE, + 'Include the errors stack trace in the output' + ) + ->addOption( + 'limit', + 'l', + InputArgument::OPTIONAL, + 'Outputs only the last X amount of errors. Use as --limit 10 / -l 10 [default 5]', + 5 + ) + ->setHelp('The log outputs the Errors Log in Console') + ; + } + + /** + * @return int|null|void + */ + protected function serve() + { + $this->options = [ + 'trace' => $this->input->getOption('trace'), + 'limit' => $this->input->getOption('limit') + ]; + + if (!file_exists($this->logfile)) { + $this->output->writeln("\n" . "Log file not found." . "\n"); + exit; + } + + $log = file_get_contents($this->logfile); + $lines = explode("\n", $log); + + if (!is_numeric($this->options['limit'])) { + $this->options['limit'] = 5; + } + + $lines = array_slice($lines, -($this->options['limit'] + 1)); + + foreach ($lines as $line) { + $parsed = $this->parseLine($line); + if ($parsed !== null) { + $this->output->writeln($parsed); + } + } + } + + /** + * @param string $line + * + * @return null|string + */ + protected function parseLine($line) + { + // Skip empty lines + if (empty(trim($line))) { + return null; + } + + $bit = explode(': ', $line); + + // Check if we have at least the basic structure + if (count($bit) < 2) { + return null; + } + + $line1 = explode('] ', $bit[0]); + + if (!isset($line1[0]) || !$line1[0]) { + return null; + } + + // Check if we have the log type + if (!isset($line1[1])) { + return null; + } + + // Handle both formats: "Message - Trace" and just "Message" + $line2 = explode(' - ', $bit[1]); + + $date = $line1[0] . ']'; + $type = str_replace('grav.', '', $line1[1]); + + // Check if the log type has a color defined + if (!isset($this->colors[$type])) { + $color = 'white'; // Default color for unknown types + } else { + $color = $this->colors[$type]; + } + + // Get the full message (everything after the log level) + // Join back with ': ' in case the message itself contains colons + $fullMessage = implode(': ', array_slice($bit, 1)); + + // If there's a dash separator, use the part before it, otherwise use the full message + if (count($line2) > 1) { + $error = $line2[0]; + } else { + $error = $fullMessage; + } + $trace = implode(': ', array_slice($bit, 2)); + + $output = []; + + $output[] = ''; + $output[] = '' . $date . ''; + $output[] = sprintf(' <%s>%s ' . $error . '', $color, $type, $color); + + if ($this->options['trace']) { + $output[] = ' TRACE: '; + $output[] = ' ' . $trace; + } + + $output[] = '' . str_repeat('-', strlen($date)) . ''; + + return implode("\n", $output); + } +} + diff --git a/plugins/error/composer.json b/plugins/error/composer.json new file mode 100644 index 0000000..27ddfa9 --- /dev/null +++ b/plugins/error/composer.json @@ -0,0 +1,39 @@ +{ + "name": "getgrav/grav-plugin-error", + "type": "grav-plugin", + "description": "Error plugin for Grav CMS", + "keywords": ["error", "plugin"], + "homepage": "https://github.com/getgrav/grav-plugin-error", + "license": "MIT", + "authors": [ + { + "name": "Team Grav", + "email": "devs@getgrav.org", + "homepage": "https://getgrav.org", + "role": "Developer" + } + ], + "support": { + "issues": "https://github.com/getgrav/grav-plugin-error/issues", + "irc": "https://chat.getgrav.org", + "forum": "https://getgrav.org/forum", + "docs": "https://github.com/getgrav/grav-plugin-error/blob/master/README.md" + }, + "autoload": { + "psr-4": { + "Grav\\Plugin\\Console\\": "cli/" + }, + "classmap": [ + "error.php" + ] + }, + "config": { + "platform": { + "php": "7.1.3" + } + }, + "scripts": { + "test": "vendor/bin/codecept run unit", + "test-windows": "vendor\\bin\\codecept run unit" + } +} diff --git a/plugins/error/error.php b/plugins/error/error.php new file mode 100644 index 0000000..edbaaff --- /dev/null +++ b/plugins/error/error.php @@ -0,0 +1,117 @@ + [ + ['autoload', 100000], + ], + 'onPageNotFound' => [ + ['onPageNotFound', 0] + ], + 'onGetPageTemplates' => [ + ['onGetPageTemplates', 0] + ], + 'onTwigTemplatePaths' => [ + ['onTwigTemplatePaths', -10] + ], + 'onDisplayErrorPage.404'=> [ + ['onDisplayErrorPage404', -1] + ] + ]; + } + + /** + * [onPluginsInitialized:100000] Composer autoload. + * + * @return ClassLoader + */ + public function autoload(): ClassLoader + { + return require __DIR__ . '/vendor/autoload.php'; + } + + /** + * @param Event $event + */ + public function onDisplayErrorPage404(Event $event): void + { + if ($this->isAdmin()) { + return; + } + + $event['page'] = $this->getErrorPage(); + $event->stopPropagation(); + } + + /** + * Display error page if no page was found for the current route. + * + * @param Event $event + */ + public function onPageNotFound(Event $event): void + { + $event->page = $this->getErrorPage(); + $event->stopPropagation(); + } + + /** + * @return PageInterface + * @throws \Exception + */ + public function getErrorPage(): PageInterface + { + /** @var Pages $pages */ + $pages = $this->grav['pages']; + + // Try to load user error page. + $page = $pages->dispatch($this->config->get('plugins.error.routes.404', '/error'), true); + if (!$page) { + // If none provided use built in error page. + $page = new Page; + $page->init(new \SplFileInfo(__DIR__ . '/pages/error.md')); + $page->title($this->grav['language']->translate('PLUGIN_ERROR.ERROR') . ' ' . $page->header()->http_response_code); + + } + + // Login page may not have the correct Cache-Control header set, force no-store for the proxies. + $cacheControl = $page->cacheControl(); + if (!$cacheControl) { + $page->cacheControl('private, no-cache, must-revalidate'); + } + + return $page; + } + + /** + * Add page template types. + */ + public function onGetPageTemplates(Event $event): void + { + /** @var Types $types */ + $types = $event->types; + $types->register('error'); + } + + /** + * Add current directory to twig lookup paths. + */ + public function onTwigTemplatePaths(): void + { + $this->grav['twig']->twig_paths[] = __DIR__ . '/templates'; + } +} diff --git a/plugins/error/error.yaml b/plugins/error/error.yaml new file mode 100644 index 0000000..0a51d4c --- /dev/null +++ b/plugins/error/error.yaml @@ -0,0 +1,3 @@ +enabled: true +routes: + 404: '/error' diff --git a/plugins/error/hebe.json b/plugins/error/hebe.json new file mode 100644 index 0000000..3ca6ad8 --- /dev/null +++ b/plugins/error/hebe.json @@ -0,0 +1,15 @@ +{ + "project":"grav-plugin-error", + "platforms":{ + "grav":{ + "nodes":{ + "plugin":[ + { + "source":"/", + "destination":"/user/plugins/error" + } + ] + } + } + } +} diff --git a/plugins/error/languages.yaml b/plugins/error/languages.yaml new file mode 100644 index 0000000..650e617 --- /dev/null +++ b/plugins/error/languages.yaml @@ -0,0 +1,55 @@ +en: + PLUGIN_ERROR: + ERROR: "Error" + ERROR_MESSAGE: "Woops. Looks like this page doesn't exist." + ROUTE_404: "404 Route" +de: + PLUGIN_ERROR: + ERROR: "Fehler" + ERROR_MESSAGE: "Uuups. Sieht aus als ob diese Seite nicht existiert." +hr: + PLUGIN_ERROR: + ERROR: "Greška" + ERROR_MESSAGE: "Uups. Izgleda da ova stranica ne postoji." +ro: + PLUGIN_ERROR: + ERROR: "Eroare" + ERROR_MESSAGE: "Ooops. Se pare că pagina nu există." +fr: + PLUGIN_ERROR: + ERROR: "Erreur" + ERROR_MESSAGE: "Oups. Il semble que cette page n’existe pas." +it: + PLUGIN_ERROR: + ERROR: "Errore" + ERROR_MESSAGE: "Ooops. A quanto pare, questa pagina non esiste." +ru: + PLUGIN_ERROR: + ERROR: "Ошибка" + ERROR_MESSAGE: "Упс. Похоже, этой страницы не существует." + ROUTE_404: "Маршрут 404" +uk: + PLUGIN_ERROR: + ERROR: "Помилка" + ERROR_MESSAGE: "Упс. Схоже, цієї сторінки не існує." + ROUTE_404: "Маршрут 404" +da: + PLUGIN_ERROR: + ERROR: "Fejl" + ERROR_MESSAGE: "Ups. Det ser ud til at siden ikke eksisterer." +zh: + PLUGIN_ERROR: + ERROR: "错误" + ERROR_MESSAGE: "呃,似乎这个页面不存在。" +cs: + PLUGIN_ERROR: + ERROR: "Chyba" + ERROR_MESSAGE: "A jéje. Vypadá to, že hledaná stránka tu není." +pl: + PLUGIN_ERROR: + ERROR: "Błąd" + ERROR_MESSAGE: "Ups. Wygląda na to, że ta strona nie istnieje." +ca: + PLUGIN_ERROR: + ERROR: "Error" + ERROR_MESSAGE: "Ups. Sembla que aquesta pàgina no existeix." diff --git a/plugins/error/pages/error.md b/plugins/error/pages/error.md new file mode 100644 index 0000000..e9b344b --- /dev/null +++ b/plugins/error/pages/error.md @@ -0,0 +1,14 @@ +--- +title: Page not Found +robots: noindex,nofollow +template: error +routable: false +http_response_code: 404 +twig_first: true +process: + twig: true +expires: 0 +--- + +{{ 'PLUGIN_ERROR.ERROR_MESSAGE'|t }} + diff --git a/plugins/error/templates/error.html.twig b/plugins/error/templates/error.html.twig new file mode 100644 index 0000000..420702b --- /dev/null +++ b/plugins/error/templates/error.html.twig @@ -0,0 +1,3 @@ +

{{ 'PLUGIN_ERROR.ERROR'|t }} {{ header.http_response_code }}

+ +

{{ page.content|raw }}

diff --git a/plugins/error/templates/error.json.twig b/plugins/error/templates/error.json.twig new file mode 100644 index 0000000..27472f1 --- /dev/null +++ b/plugins/error/templates/error.json.twig @@ -0,0 +1 @@ +{{ page.content|json_encode()|raw }} \ No newline at end of file diff --git a/plugins/error/vendor/autoload.php b/plugins/error/vendor/autoload.php new file mode 100644 index 0000000..b30c4e0 --- /dev/null +++ b/plugins/error/vendor/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + private $classMapAuthoritative = false; + private $missingClasses = array(); + private $apcuPrefix; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath.'\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/plugins/error/vendor/composer/LICENSE b/plugins/error/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/plugins/error/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +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. + diff --git a/plugins/error/vendor/composer/autoload_classmap.php b/plugins/error/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..71c4666 --- /dev/null +++ b/plugins/error/vendor/composer/autoload_classmap.php @@ -0,0 +1,10 @@ + $baseDir . '/error.php', +); diff --git a/plugins/error/vendor/composer/autoload_namespaces.php b/plugins/error/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..b7fc012 --- /dev/null +++ b/plugins/error/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + array($baseDir . '/cli'), +); diff --git a/plugins/error/vendor/composer/autoload_real.php b/plugins/error/vendor/composer/autoload_real.php new file mode 100644 index 0000000..ee6a4c0 --- /dev/null +++ b/plugins/error/vendor/composer/autoload_real.php @@ -0,0 +1,52 @@ += 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInit4e2f762c713c4d4aae8969c74f5623a3::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + return $loader; + } +} diff --git a/plugins/error/vendor/composer/autoload_static.php b/plugins/error/vendor/composer/autoload_static.php new file mode 100644 index 0000000..11ca02a --- /dev/null +++ b/plugins/error/vendor/composer/autoload_static.php @@ -0,0 +1,36 @@ + + array ( + 'Grav\\Plugin\\Console\\' => 20, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Grav\\Plugin\\Console\\' => + array ( + 0 => __DIR__ . '/../..' . '/cli', + ), + ); + + public static $classMap = array ( + 'Grav\\Plugin\\ErrorPlugin' => __DIR__ . '/../..' . '/error.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInit4e2f762c713c4d4aae8969c74f5623a3::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit4e2f762c713c4d4aae8969c74f5623a3::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInit4e2f762c713c4d4aae8969c74f5623a3::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/plugins/error/vendor/composer/installed.json b/plugins/error/vendor/composer/installed.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/plugins/error/vendor/composer/installed.json @@ -0,0 +1 @@ +[]