Initial commit: apps.prometeysev.ru
This commit is contained in:
commit
96ccabcd8b
6561 files changed
+1270349
No files matched your search
@@ -0,0 +1,8 @@
|
||||
{"presets": [
|
||||
"@babel/env",
|
||||
["minify", {
|
||||
"keepFnName": true,
|
||||
"keepClassName": true,
|
||||
"mangle": false
|
||||
}]
|
||||
]}
|
||||
@@ -0,0 +1,24 @@
|
||||
; This file is for unifying the coding style for different editors and IDEs.
|
||||
; More information at http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.bat]
|
||||
end_of_line = crlf
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.twig]
|
||||
insert_final_newline = false
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
@@ -0,0 +1,5 @@
|
||||
tmp
|
||||
logs
|
||||
.idea
|
||||
files
|
||||
archive/*
|
||||
@@ -0,0 +1,13 @@
|
||||
# Uncomment the following to prevent the httpoxy vulnerability
|
||||
# See: https://httpoxy.org/
|
||||
#<IfModule mod_headers.c>
|
||||
# RequestHeader unset Proxy
|
||||
#</IfModule>
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine on
|
||||
RewriteBase /
|
||||
RewriteRule ^(\.well-known/.*)$ $1 [L]
|
||||
RewriteRule ^$ webroot/ [L]
|
||||
RewriteRule (.*) webroot/$1 [L]
|
||||
</IfModule>
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
language: php
|
||||
|
||||
dist: trusty
|
||||
|
||||
sudo: false
|
||||
|
||||
php:
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
include:
|
||||
- php: 7.0
|
||||
env: PHPCS=1
|
||||
|
||||
before_script:
|
||||
- if [[ $PHPCS = 1 ]]; then composer require cakephp/cakephp-codesniffer:~2.1; fi
|
||||
- if [[ $PHPCS != 1 ]]; then composer install; fi
|
||||
- if [[ $PHPCS != 1 ]]; then composer require phpunit/phpunit:"^5.7|^6.0"; fi
|
||||
- if [[ $PHPCS != 1 ]]; then composer run-script post-install-cmd --no-interaction; fi
|
||||
|
||||
script:
|
||||
- if [[ $PHPCS != 1 ]]; then vendor/bin/phpunit; fi
|
||||
- if [[ $PHPCS = 1 ]]; then vendor/bin/phpcs -p --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests ./config ./webroot; fi
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env sh
|
||||
################################################################################
|
||||
#
|
||||
# Cake is a shell script for invoking CakePHP shell commands
|
||||
#
|
||||
# CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
# Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
#
|
||||
# Licensed under The MIT License
|
||||
# For full copyright and license information, please see the LICENSE.txt
|
||||
# Redistributions of files must retain the above copyright notice.
|
||||
#
|
||||
# @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
# @link https://cakephp.org CakePHP(tm) Project
|
||||
# @since 1.2.0
|
||||
# @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# Canonicalize by following every symlink of the given name recursively
|
||||
canonicalize() {
|
||||
NAME="$1"
|
||||
if [ -f "$NAME" ]
|
||||
then
|
||||
DIR=$(dirname -- "$NAME")
|
||||
NAME=$(cd -P "$DIR" > /dev/null && pwd -P)/$(basename -- "$NAME")
|
||||
fi
|
||||
while [ -h "$NAME" ]; do
|
||||
DIR=$(dirname -- "$NAME")
|
||||
SYM=$(readlink "$NAME")
|
||||
NAME=$(cd "$DIR" > /dev/null && cd $(dirname -- "$SYM") > /dev/null && pwd)/$(basename -- "$SYM")
|
||||
done
|
||||
echo "$NAME"
|
||||
}
|
||||
|
||||
CONSOLE=$(dirname -- "$(canonicalize "$0")")
|
||||
APP=$(dirname "$CONSOLE")
|
||||
|
||||
if [ $(basename $0) != 'cake' ]
|
||||
then
|
||||
exec php "$CONSOLE"/cake.php $(basename $0) "$@"
|
||||
else
|
||||
exec php "$CONSOLE"/cake.php "$@"
|
||||
fi
|
||||
|
||||
exit
|
||||
@@ -0,0 +1,27 @@
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::
|
||||
:: Cake is a Windows batch script for invoking CakePHP shell commands
|
||||
::
|
||||
:: CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
:: Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
::
|
||||
:: Licensed under The MIT License
|
||||
:: Redistributions of files must retain the above copyright notice.
|
||||
::
|
||||
:: @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
:: @link https://cakephp.org CakePHP(tm) Project
|
||||
:: @since 2.0.0
|
||||
:: @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
@echo off
|
||||
|
||||
SET app=%0
|
||||
SET lib=%~dp0
|
||||
|
||||
c:\xampp\php7\php "%lib%cake.php" %*
|
||||
|
||||
echo.
|
||||
|
||||
exit /B %ERRORLEVEL%
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/php -q
|
||||
<?php
|
||||
// Check platform requirements
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
use App\Application;
|
||||
use Cake\Console\CommandRunner;
|
||||
|
||||
// Build the runner with an application and root executable name.
|
||||
$runner = new CommandRunner(new Application(dirname(__DIR__) . '/config'), 'cake');
|
||||
exit($runner->run($argv));
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "cakephp/app",
|
||||
"description": "CakePHP skeleton app",
|
||||
"homepage": "https://cakephp.org",
|
||||
"type": "project",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">=7.0",
|
||||
"ext-gd": "*",
|
||||
"ext-mbstring": "*",
|
||||
"cakephp/cakephp": "3.8.*",
|
||||
"cakephp/migrations": "^2.0.0",
|
||||
"cakephp/plugin-installer": "^1.0",
|
||||
"dompdf/dompdf": "^0.8.3",
|
||||
"josegonzalez/dotenv": "3.*",
|
||||
"mobiledetect/mobiledetectlib": "2.*",
|
||||
"mpdf/mpdf": "^8.0",
|
||||
"paragonie/random_compat": "^1.4|^2.0",
|
||||
"parsecsv/php-parsecsv": "^1.1",
|
||||
"phpmailer/phpmailer": "^6.0",
|
||||
"phpoffice/phpspreadsheet": "^1.8"
|
||||
},
|
||||
"require-dev": {
|
||||
"cakephp/bake": "^1.9.0",
|
||||
"cakephp/cakephp-codesniffer": "^3.0",
|
||||
"cakephp/debug_kit": "^3.2",
|
||||
"psy/psysh": "@stable"
|
||||
},
|
||||
"suggest": {
|
||||
"markstory/asset_compress": "An asset compression plugin which provides file concatenation and a flexible filter system for preprocessing and minification.",
|
||||
"dereuromark/cakephp-ide-helper": "After baking your code, this keeps your annotations in sync with the code evolving from there on for maximum IDE and PHPStan compatibility.",
|
||||
"phpunit/phpunit": "Allows automated tests to be run without system-wide install.",
|
||||
"cakephp/cakephp-codesniffer": "Allows to check the code against the coding standards used in CakePHP."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"App\\Test\\": "tests/",
|
||||
"Cake\\Test\\": "vendor/cakephp/cakephp/tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": "App\\Console\\Installer::postInstall",
|
||||
"post-create-project-cmd": "App\\Console\\Installer::postInstall",
|
||||
"post-autoload-dump": "Cake\\Composer\\Installer\\PluginInstaller::postAutoloadDump",
|
||||
"check": [
|
||||
"@test",
|
||||
"@cs-check"
|
||||
],
|
||||
"cs-check": "phpcs --colors -p --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests",
|
||||
"cs-fix": "phpcbf --colors --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests",
|
||||
"test": "phpunit --colors=always"
|
||||
},
|
||||
"prefer-stable": true,
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
Generated
+3612
File diff suppressed because it is too large.
Load diff
+156
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
return [
|
||||
'debug' => false,
|
||||
|
||||
'Release' => "2.4.165",
|
||||
|
||||
'App' => [
|
||||
'namespace' => 'App',
|
||||
'encoding' => env('APP_ENCODING', 'UTF-8'),
|
||||
'defaultLocale' => env('APP_DEFAULT_LOCALE', 'en_US'),
|
||||
'defaultTimezone' => env('APP_DEFAULT_TIMEZONE', 'UTC'),
|
||||
'base' => false,
|
||||
'dir' => 'src',
|
||||
'webroot' => 'webroot',
|
||||
'wwwRoot' => WWW_ROOT,
|
||||
'imageBaseUrl' => 'img/',
|
||||
'cssBaseUrl' => 'css/',
|
||||
'jsBaseUrl' => 'js/',
|
||||
'paths' => [
|
||||
'plugins' => [ROOT . DS . 'plugins' . DS],
|
||||
'templates' => [APP . 'Template' . DS],
|
||||
'locales' => [APP . 'Locale' . DS],
|
||||
],
|
||||
],
|
||||
|
||||
'Security' => [
|
||||
'salt' => env('SECURITY_SALT', '2ae8d3f453c9f6a290a2fcdb173be1cf4acc871c6e656411c82aa331bbfefc18'),
|
||||
],
|
||||
|
||||
'Asset' => [
|
||||
// 'timestamp' => true,
|
||||
],
|
||||
|
||||
'Cache' => [
|
||||
'default' => [
|
||||
'className' => 'File',
|
||||
'path' => CACHE,
|
||||
'url' => env('CACHE_DEFAULT_URL', null),
|
||||
],
|
||||
|
||||
'_cake_core_' => [
|
||||
'className' => 'File',
|
||||
'prefix' => 'myapp_cake_core_',
|
||||
'path' => CACHE . 'persistent/',
|
||||
'serialize' => true,
|
||||
'duration' => '+1 years',
|
||||
'url' => env('CACHE_CAKECORE_URL', null),
|
||||
],
|
||||
|
||||
'_cake_model_' => [
|
||||
'className' => 'File',
|
||||
'prefix' => 'myapp_cake_model_',
|
||||
'path' => CACHE . 'models/',
|
||||
'serialize' => true,
|
||||
'duration' => '+1 years',
|
||||
'url' => env('CACHE_CAKEMODEL_URL', null),
|
||||
],
|
||||
],
|
||||
|
||||
|
||||
'Error' => [
|
||||
'errorLevel' => E_ALL,
|
||||
'exceptionRenderer' => 'Cake\Error\ExceptionRenderer',
|
||||
'skipLog' => [],
|
||||
'log' => true,
|
||||
'trace' => true,
|
||||
],
|
||||
|
||||
|
||||
'Datasources' => [
|
||||
'default' => [
|
||||
'className' => 'Cake\Database\Connection',
|
||||
'driver' => 'Cake\Database\Driver\Mysql',
|
||||
'persistent' => false,
|
||||
'host' => 'localhost',
|
||||
|
||||
'username' => 'prometeysev',
|
||||
'password' => 'S!@ThrreICKM3occ',
|
||||
'database' => 'prometeysev_apps',
|
||||
'encoding' => 'utf8',
|
||||
'timezone' => 'UTC',
|
||||
'flags' => [],
|
||||
'cacheMetadata' => true,
|
||||
'log' => false,
|
||||
|
||||
'quoteIdentifiers' => true,
|
||||
'url' => env('DATABASE_URL', null),
|
||||
],
|
||||
],
|
||||
|
||||
'Log' => [
|
||||
'debug' => [
|
||||
'className' => 'Cake\Log\Engine\FileLog',
|
||||
'path' => LOGS,
|
||||
'file' => 'debug',
|
||||
'url' => env('LOG_DEBUG_URL', null),
|
||||
'scopes' => false,
|
||||
'levels' => ['notice', 'info', 'debug'],
|
||||
],
|
||||
'error' => [
|
||||
'className' => 'Cake\Log\Engine\FileLog',
|
||||
'path' => LOGS,
|
||||
'file' => 'error',
|
||||
'url' => env('LOG_ERROR_URL', null),
|
||||
'scopes' => false,
|
||||
'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'],
|
||||
],
|
||||
'queries' => [
|
||||
'className' => 'Cake\Log\Engine\FileLog',
|
||||
'path' => LOGS,
|
||||
'file' => 'queries',
|
||||
'url' => env('LOG_QUERIES_URL', null),
|
||||
'scopes' => ['queriesLog'],
|
||||
],
|
||||
],
|
||||
|
||||
'Session' => [
|
||||
'defaults' => 'php',
|
||||
'ini' => [
|
||||
'session.cookie_lifetime' => 18*60*60, //18h
|
||||
'session.cookie_httponly' => true
|
||||
],
|
||||
'timeout' => 12 * 60 //12h
|
||||
],
|
||||
|
||||
'mpdfPageParams' => [
|
||||
'mode' => 'utf-8',
|
||||
'format' => 'A4',
|
||||
'default_font_size' => 0,
|
||||
'default_font' => 'arial',
|
||||
'margin_left' => 15,
|
||||
'margin_right' => 15,
|
||||
'margin_top' => 17,
|
||||
'margin_bottom' => 30
|
||||
],
|
||||
'smsMinimalBalance' => 50,
|
||||
|
||||
"encrypt" => [
|
||||
"key" => 'fsjlksf$#%WEtfvV34v59fHgi3rs0gBB<T58903--.we8934W$w3',
|
||||
"cipher" => "AES-128-CBC",
|
||||
"options" => OPENSSL_RAW_DATA,
|
||||
"as_binary" => true
|
||||
],
|
||||
|
||||
'ftpParams' => [
|
||||
'ip' => '188.191.27.165',
|
||||
'port' => 53530,
|
||||
'username' => 'soronorus',
|
||||
'password' => '5#NqtYB;XOC;!wAtp',
|
||||
|
||||
'acquiringPrometeyOut' => '/prometeysev.ru/acquiring-in',
|
||||
'acquiringPrometeyIn' => '/prometeysev.ru/acquiring-out',
|
||||
'acquiringPrometeyRefund' => '/prometeysev.ru/refund',
|
||||
|
||||
]
|
||||
];
|
||||
@@ -0,0 +1,243 @@
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/paths.php';
|
||||
|
||||
|
||||
require CORE_PATH . 'config' . DS . 'bootstrap.php';
|
||||
|
||||
use Cake\Cache\Cache;
|
||||
use Cake\Console\ConsoleErrorHandler;
|
||||
use Cake\Core\App;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Core\Configure\Engine\PhpConfig;
|
||||
use Cake\Core\Plugin;
|
||||
use Cake\Database\Type;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
use Cake\Error\ErrorHandler;
|
||||
use Cake\Http\ServerRequest;
|
||||
use Cake\Log\Log;
|
||||
use Cake\Mailer\Email;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Utility\Inflector;
|
||||
use Cake\Utility\Security;
|
||||
|
||||
try {
|
||||
Configure::config('default', new PhpConfig());
|
||||
Configure::load('app', 'default', false);
|
||||
} catch (\Exception $e) {
|
||||
exit($e->getMessage() . "\n");
|
||||
}
|
||||
|
||||
|
||||
if (Configure::read('debug')) {
|
||||
Configure::write('Cache._cake_model_.duration', '+2 minutes');
|
||||
Configure::write('Cache._cake_core_.duration', '+2 minutes');
|
||||
// disable router cache during development
|
||||
Configure::write('Cache._cake_routes_.duration', '+2 seconds');
|
||||
}
|
||||
|
||||
|
||||
date_default_timezone_set('Europe/Moscow');
|
||||
|
||||
mb_internal_encoding(Configure::read('App.encoding'));
|
||||
|
||||
|
||||
ini_set('intl.default_locale', Configure::read('App.defaultLocale'));
|
||||
|
||||
|
||||
$isCli = PHP_SAPI === 'cli';
|
||||
if ($isCli) {
|
||||
(new ConsoleErrorHandler(Configure::read('Error')))->register();
|
||||
} else {
|
||||
(new ErrorHandler(Configure::read('Error')))->register();
|
||||
}
|
||||
|
||||
|
||||
if ($isCli) {
|
||||
require __DIR__ . '/bootstrap_cli.php';
|
||||
}
|
||||
|
||||
|
||||
if (!Configure::read('App.fullBaseUrl')) {
|
||||
$s = null;
|
||||
if (env('HTTPS')) {
|
||||
$s = 's';
|
||||
}
|
||||
|
||||
$httpHost = env('HTTP_HOST');
|
||||
if (isset($httpHost)) {
|
||||
Configure::write('App.fullBaseUrl', 'http' . $s . '://' . $httpHost);
|
||||
}
|
||||
unset($httpHost, $s);
|
||||
}
|
||||
|
||||
Cache::setConfig(Configure::consume('Cache'));
|
||||
ConnectionManager::setConfig(Configure::consume('Datasources'));
|
||||
//Email::setConfigTransport(Configure::consume('EmailTransport'));
|
||||
//Email::setConfig(Configure::consume('Email'));
|
||||
Log::setConfig(Configure::consume('Log'));
|
||||
Security::setSalt(Configure::consume('Security.salt'));
|
||||
|
||||
|
||||
ServerRequest::addDetector('mobile', function ($request) {
|
||||
$detector = new \Detection\MobileDetect();
|
||||
|
||||
return $detector->isMobile();
|
||||
});
|
||||
ServerRequest::addDetector('tablet', function ($request) {
|
||||
$detector = new \Detection\MobileDetect();
|
||||
|
||||
return $detector->isTablet();
|
||||
});
|
||||
|
||||
|
||||
Type::build('time')
|
||||
->useImmutable();
|
||||
Type::build('date')
|
||||
->useImmutable();
|
||||
Type::build('datetime')
|
||||
->useImmutable();
|
||||
Type::build('timestamp')
|
||||
->useImmutable();
|
||||
|
||||
require_once(ROOT . DS . 'vendor' . DS . 'dbf' . DS . 'DBF.class.php');
|
||||
require_once(ROOT . DS . 'vendor' . DS . 'sms' . DS . 'sms.ru.php');
|
||||
require_once(ROOT . DS . 'vendor' . DS . 'browser_detection' . DS . 'BrowserDetection.php');
|
||||
//require_once(ROOT . DS . 'vendor' . DS . 'mpdf' . DS . 'mpdf.php');
|
||||
|
||||
function cmpDetailsByBothSides($a, $b) {
|
||||
if (max($a->width, $a->height) != max($b->width, $b->height)) {
|
||||
return (max($a->width, $a->height) > max($b->width, $b->height)) ? -1 : 1;
|
||||
} else {
|
||||
if (min($a->width, $a->height) != min($b->width, $b->height)) {
|
||||
return (min($a->width, $a->height) > min($b->width, $b->height)) ? -1 : 1;
|
||||
} else {
|
||||
if ($a->height != $b->height) {
|
||||
return ($a->height > $b->height ) ? -1 : 1;
|
||||
} else {
|
||||
if ($a->width == $b->width ) {
|
||||
return 0;
|
||||
}
|
||||
return ($a->width > $b->width ) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cmpDetailsByBothSidesReversed($a, $b) {
|
||||
if (max($a->width, $a->height) != max($b->width, $b->height)) {
|
||||
return (max($a->width, $a->height) > max($b->width, $b->height)) ? 1 : -1;
|
||||
} else {
|
||||
if (min($a->width, $a->height) != min($b->width, $b->height)) {
|
||||
return (min($a->width, $a->height) > min($b->width, $b->height)) ? 1 : -1;
|
||||
} else {
|
||||
if ($a->height != $b->height) {
|
||||
return ($a->height > $b->height ) ? 1 : -1;
|
||||
} else {
|
||||
if ($a->width == $b->width ) {
|
||||
return 0;
|
||||
}
|
||||
return ($a->width > $b->width ) ? 1 : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function cmpDetailsByWidth($a, $b) {
|
||||
if ($a->width != $b->width) {
|
||||
return ($a->width > $b->width ) ? -1 : 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function cmpDetailsByWidthReversed($a, $b) {
|
||||
if ($a->width != $b->width) {
|
||||
return ($a->width > $b->width ) ? 1 : -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function cmpDetailsByHeight($a, $b) {
|
||||
if ($a->height != $b->height) {
|
||||
return ($a->height > $b->height ) ? -1 : 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function cmpDetailsByHeightReversed($a, $b) {
|
||||
if ($a->height != $b->height) {
|
||||
return ($a->height > $b->height ) ? 1 : -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function cmpDetailsByBothSidesForToTop($a, $b) {
|
||||
if ($a->height != $b->height) {
|
||||
return ($a->height > $b->height ) ? -1 : 1;
|
||||
} else {
|
||||
if ($a->width != $b->width) {
|
||||
return ($a->width > $b->width ) ? -1 : 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('mb_ucfirst') && function_exists('mb_substr')) {
|
||||
function mb_ucfirst($string) {
|
||||
$string = mb_strtoupper(mb_substr($string, 0, 1)) . mb_substr($string, 1);
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
function toFixed2($num) {
|
||||
return str_replace(".00", "", number_format(ceil($num * 10000) / 10000, 2, ".", ""));
|
||||
}
|
||||
|
||||
function toFixed2Price($num) {
|
||||
return number_format(str_replace(" ", "", $num), 2, ".", " ");
|
||||
}
|
||||
|
||||
function cleanupPhone($phone) {
|
||||
return str_replace(["+", "-", " ", "(", ")"], "", $phone);
|
||||
}
|
||||
|
||||
function formatPhone($phone) {
|
||||
return "+7 (" . substr($phone, 1, 3) . ") " . substr($phone, 4, 3) . "-" . substr($phone, 7, 2) . "-" . substr($phone, 9, 2);
|
||||
}
|
||||
|
||||
function cleanupEmail($email) {
|
||||
return str_replace([" "], "", $email);
|
||||
}
|
||||
|
||||
function br2nl($str) {
|
||||
return preg_replace('/\<br(\s*)?\/?\>/ui', "\r\n", $str);
|
||||
}
|
||||
|
||||
function cleanupDetailLabel($label) {
|
||||
return preg_replace("/_{2,}/", "_", preg_replace("/[^\w\d\\*]/ui", "_" , $label));
|
||||
}
|
||||
|
||||
function cleanupDetailLabel2($label) {
|
||||
return preg_replace("/_{2,}/", "_", preg_replace("/[^\w\d\\*\-]/ui", "_" , $label));
|
||||
}
|
||||
|
||||
|
||||
function counterPluralForm($number, $before, $after, $echoResults = false ) {
|
||||
$cases = array(2,0,1,1,1,2);
|
||||
|
||||
$result = $before[($number % 100 > 4 && $number % 100 < 20) ? 2 : $cases[min($number % 10, 5)]] . ' ' . $number . ' ' . $after[($number % 100 > 4 && $number % 100 < 20) ? 2 : $cases[min($number % 10, 5)]];
|
||||
|
||||
if ($echoResults) {
|
||||
echo $result;
|
||||
} else {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
use App\Application;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Core\Exception\MissingPluginException;
|
||||
use Cake\Core\Plugin;
|
||||
|
||||
|
||||
Configure::write('Log.error.file', 'cli-error');
|
||||
|
||||
try {
|
||||
Application::addPlugin('Bake');
|
||||
} catch (MissingPluginException $e) {
|
||||
|
||||
}
|
||||
|
||||
Application::addPlugin('Migrations');
|
||||
|
||||
function isLocked($lock_file) {
|
||||
# If lock file exists, check if stale. If exists and is not stale, return TRUE
|
||||
# Else, create lock file and return FALSE.
|
||||
|
||||
if( file_exists( $lock_file ) ) {
|
||||
# check if it's stale
|
||||
$lockingPID = trim( file_get_contents( $lock_file ) );
|
||||
|
||||
# Get all active PIDs.
|
||||
$pids = explode( "\n", trim( `ps -e | awk '{print $1}'` ) );
|
||||
|
||||
# If PID is still active, return true
|
||||
if( in_array( $lockingPID, $pids ) ) return true;
|
||||
|
||||
# Lock-file is stale, so kill it. Then move on to re-creating it.
|
||||
//echo "Removing stale lock file.\n";
|
||||
unlink( $lock_file );
|
||||
}
|
||||
|
||||
file_put_contents( $lock_file, getmypid() . "\n" );
|
||||
return false;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.0
|
||||
* @license MIT License (https://opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Use the DS to separate the directories in other defines
|
||||
*/
|
||||
if (!defined('DS')) {
|
||||
define('DS', DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* These defines should only be edited if you have cake installed in
|
||||
* a directory layout other than the way it is distributed.
|
||||
* When using custom settings be sure to use the DS and do not add a trailing DS.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The full path to the directory which holds "src", WITHOUT a trailing DS.
|
||||
*/
|
||||
define('ROOT', dirname(__DIR__));
|
||||
|
||||
/**
|
||||
* The actual directory name for the application directory. Normally
|
||||
* named 'src'.
|
||||
*/
|
||||
define('APP_DIR', 'src');
|
||||
|
||||
/**
|
||||
* Path to the application's directory.
|
||||
*/
|
||||
define('APP', ROOT . DS . APP_DIR . DS);
|
||||
|
||||
/**
|
||||
* Path to the config directory.
|
||||
*/
|
||||
define('CONFIG', ROOT . DS . 'config' . DS);
|
||||
|
||||
/**
|
||||
* File path to the webroot directory.
|
||||
*/
|
||||
define('WWW_ROOT', ROOT . DS . 'webroot' . DS);
|
||||
|
||||
/**
|
||||
* Path to the tests directory.
|
||||
*/
|
||||
define('TESTS', ROOT . DS . 'tests' . DS);
|
||||
|
||||
/**
|
||||
* Path to the temporary files directory.
|
||||
*/
|
||||
define('TMP', ROOT . DS . 'tmp' . DS);
|
||||
|
||||
/**
|
||||
* Path to the logs directory.
|
||||
*/
|
||||
define('LOGS', ROOT . DS . 'logs' . DS);
|
||||
|
||||
/**
|
||||
* Path to the cache files directory. It can be shared between hosts in a multi-server setup.
|
||||
*/
|
||||
define('CACHE', TMP . 'cache' . DS);
|
||||
|
||||
/**
|
||||
* The absolute path to the "cake" directory, WITHOUT a trailing DS.
|
||||
*
|
||||
* CakePHP should always be installed with composer, so look there.
|
||||
*/
|
||||
define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'vendor' . DS . 'cakephp' . DS . 'cakephp');
|
||||
|
||||
/**
|
||||
* Path to the cake directory.
|
||||
*/
|
||||
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
|
||||
define('CAKE', CORE_PATH . 'src' . DS);
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
use Cake\Core\Plugin;
|
||||
use Cake\Routing\RouteBuilder;
|
||||
use Cake\Routing\Router;
|
||||
use Cake\Routing\Route\DashedRoute;
|
||||
|
||||
Router::defaultRouteClass(DashedRoute::class);
|
||||
|
||||
|
||||
Router::scope('/', function (RouteBuilder $routes) {
|
||||
$routes->connect('/', ['controller' => 'OrderPayment', 'action' => 'display']);
|
||||
$routes->fallbacks(DashedRoute::class);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
#
|
||||
# Licensed under The MIT License
|
||||
# For full copyright and license information, please see the LICENSE.txt
|
||||
# Redistributions of files must retain the above copyright notice.
|
||||
# MIT License (https://opensource.org/licenses/mit-license.php)
|
||||
|
||||
CREATE TABLE i18n (
|
||||
id int NOT NULL auto_increment,
|
||||
locale varchar(6) NOT NULL,
|
||||
model varchar(255) NOT NULL,
|
||||
foreign_key int(10) NOT NULL,
|
||||
field varchar(255) NOT NULL,
|
||||
content text,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field),
|
||||
INDEX I18N_FIELD(model, foreign_key, field)
|
||||
);
|
||||
@@ -0,0 +1,15 @@
|
||||
# Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
#
|
||||
# Licensed under The MIT License
|
||||
# For full copyright and license information, please see the LICENSE.txt
|
||||
# Redistributions of files must retain the above copyright notice.
|
||||
# MIT License (https://opensource.org/licenses/mit-license.php)
|
||||
|
||||
CREATE TABLE `sessions` (
|
||||
`id` char(40) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`created` datetime DEFAULT CURRENT_TIMESTAMP, -- optional, requires MySQL 5.6.5+
|
||||
`modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- optional, requires MySQL 5.6.5+
|
||||
`data` blob DEFAULT NULL, -- for PostgreSQL use bytea instead of blob
|
||||
`expires` int(10) unsigned DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 0.10.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
require 'webroot' . DIRECTORY_SEPARATOR . 'index.php';
|
||||
Generated
+3031
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
colors="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="./tests/bootstrap.php"
|
||||
>
|
||||
<php>
|
||||
<ini name="memory_limit" value="-1"/>
|
||||
<ini name="apc.enable_cli" value="1"/>
|
||||
</php>
|
||||
|
||||
<!-- Add any additional test suites you want to run here -->
|
||||
<testsuites>
|
||||
<testsuite name="app">
|
||||
<directory>./tests/TestCase</directory>
|
||||
</testsuite>
|
||||
<!-- Add plugin test suites here. -->
|
||||
</testsuites>
|
||||
|
||||
<!-- Setup a listener for fixtures -->
|
||||
<listeners>
|
||||
<listener
|
||||
class="\Cake\TestSuite\Fixture\FixtureInjector"
|
||||
file="./vendor/cakephp/cakephp/src/TestSuite/Fixture/FixtureInjector.php">
|
||||
<arguments>
|
||||
<object class="\Cake\TestSuite\Fixture\FixtureManager" />
|
||||
</arguments>
|
||||
</listener>
|
||||
</listeners>
|
||||
|
||||
<!-- Ignore vendor tests in code coverage reports -->
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">./src/</directory>
|
||||
<directory suffix=".php">./plugins/*/src/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.3.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace App;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Error\Middleware\ErrorHandlerMiddleware;
|
||||
use Cake\Http\BaseApplication;
|
||||
use Cake\Routing\Middleware\AssetMiddleware;
|
||||
use Cake\Routing\Middleware\RoutingMiddleware;
|
||||
|
||||
/**
|
||||
* Application setup class.
|
||||
*
|
||||
* This defines the bootstrapping logic and middleware layers you
|
||||
* want to use in your application.
|
||||
*/
|
||||
class Application extends BaseApplication
|
||||
{
|
||||
/**
|
||||
* Setup the middleware queue your application will use.
|
||||
*
|
||||
* @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to setup.
|
||||
* @return \Cake\Http\MiddlewareQueue The updated middleware queue.
|
||||
*/
|
||||
public function middleware($middlewareQueue)
|
||||
{
|
||||
$middlewareQueue
|
||||
// Catch any exceptions in the lower layers,
|
||||
// and make an error page/response
|
||||
->add(ErrorHandlerMiddleware::class)
|
||||
|
||||
// Handle plugin/theme assets like CakePHP normally does.
|
||||
->add(AssetMiddleware::class)
|
||||
|
||||
// Add routing middleware.
|
||||
->add(new RoutingMiddleware($this));
|
||||
|
||||
return $middlewareQueue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace App\Console;
|
||||
|
||||
if (!defined('STDIN')) {
|
||||
define('STDIN', fopen('php://stdin', 'r'));
|
||||
}
|
||||
|
||||
use Cake\Utility\Security;
|
||||
use Composer\Script\Event;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Provides installation hooks for when this application is installed via
|
||||
* composer. Customize this class to suit your needs.
|
||||
*/
|
||||
class Installer
|
||||
{
|
||||
|
||||
/**
|
||||
* An array of directories to be made writable
|
||||
*/
|
||||
const WRITABLE_DIRS = [
|
||||
'logs',
|
||||
'tmp',
|
||||
'tmp/cache',
|
||||
'tmp/cache/models',
|
||||
'tmp/cache/persistent',
|
||||
'tmp/cache/views',
|
||||
'tmp/sessions',
|
||||
'tmp/tests'
|
||||
];
|
||||
|
||||
/**
|
||||
* Does some routine installation tasks so people don't have to.
|
||||
*
|
||||
* @param \Composer\Script\Event $event The composer event object.
|
||||
* @throws \Exception Exception raised by validator.
|
||||
* @return void
|
||||
*/
|
||||
public static function postInstall(Event $event)
|
||||
{
|
||||
$io = $event->getIO();
|
||||
|
||||
$rootDir = dirname(dirname(__DIR__));
|
||||
|
||||
static::createAppConfig($rootDir, $io);
|
||||
static::createWritableDirectories($rootDir, $io);
|
||||
|
||||
// ask if the permissions should be changed
|
||||
if ($io->isInteractive()) {
|
||||
$validator = function ($arg) {
|
||||
if (in_array($arg, ['Y', 'y', 'N', 'n'])) {
|
||||
return $arg;
|
||||
}
|
||||
throw new Exception('This is not a valid answer. Please choose Y or n.');
|
||||
};
|
||||
$setFolderPermissions = $io->askAndValidate(
|
||||
'<info>Set Folder Permissions ? (Default to Y)</info> [<comment>Y,n</comment>]? ',
|
||||
$validator,
|
||||
10,
|
||||
'Y'
|
||||
);
|
||||
|
||||
if (in_array($setFolderPermissions, ['Y', 'y'])) {
|
||||
static::setFolderPermissions($rootDir, $io);
|
||||
}
|
||||
} else {
|
||||
static::setFolderPermissions($rootDir, $io);
|
||||
}
|
||||
|
||||
static::setSecuritySalt($rootDir, $io);
|
||||
|
||||
if (class_exists('\Cake\Codeception\Console\Installer')) {
|
||||
\Cake\Codeception\Console\Installer::customizeCodeceptionBinary($event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the config/app.php file if it does not exist.
|
||||
*
|
||||
* @param string $dir The application's root directory.
|
||||
* @param \Composer\IO\IOInterface $io IO interface to write to console.
|
||||
* @return void
|
||||
*/
|
||||
public static function createAppConfig($dir, $io)
|
||||
{
|
||||
$appConfig = $dir . '/config/app.php';
|
||||
$defaultConfig = $dir . '/config/app.default.php';
|
||||
if (!file_exists($appConfig)) {
|
||||
copy($defaultConfig, $appConfig);
|
||||
$io->write('Created `config/app.php` file');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the `logs` and `tmp` directories.
|
||||
*
|
||||
* @param string $dir The application's root directory.
|
||||
* @param \Composer\IO\IOInterface $io IO interface to write to console.
|
||||
* @return void
|
||||
*/
|
||||
public static function createWritableDirectories($dir, $io)
|
||||
{
|
||||
foreach (static::WRITABLE_DIRS as $path) {
|
||||
$path = $dir . '/' . $path;
|
||||
if (!file_exists($path)) {
|
||||
mkdir($path);
|
||||
$io->write('Created `' . $path . '` directory');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set globally writable permissions on the "tmp" and "logs" directory.
|
||||
*
|
||||
* This is not the most secure default, but it gets people up and running quickly.
|
||||
*
|
||||
* @param string $dir The application's root directory.
|
||||
* @param \Composer\IO\IOInterface $io IO interface to write to console.
|
||||
* @return void
|
||||
*/
|
||||
public static function setFolderPermissions($dir, $io)
|
||||
{
|
||||
// Change the permissions on a path and output the results.
|
||||
$changePerms = function ($path, $perms, $io) {
|
||||
// Get permission bits from stat(2) result.
|
||||
$currentPerms = fileperms($path) & 0777;
|
||||
if (($currentPerms & $perms) == $perms) {
|
||||
return;
|
||||
}
|
||||
|
||||
$res = chmod($path, $currentPerms | $perms);
|
||||
if ($res) {
|
||||
$io->write('Permissions set on ' . $path);
|
||||
} else {
|
||||
$io->write('Failed to set permissions on ' . $path);
|
||||
}
|
||||
};
|
||||
|
||||
$walker = function ($dir, $perms, $io) use (&$walker, $changePerms) {
|
||||
$files = array_diff(scandir($dir), ['.', '..']);
|
||||
foreach ($files as $file) {
|
||||
$path = $dir . '/' . $file;
|
||||
|
||||
if (!is_dir($path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$changePerms($path, $perms, $io);
|
||||
$walker($path, $perms, $io);
|
||||
}
|
||||
};
|
||||
|
||||
$worldWritable = bindec('0000000111');
|
||||
$walker($dir . '/tmp', $worldWritable, $io);
|
||||
$changePerms($dir . '/tmp', $worldWritable, $io);
|
||||
$changePerms($dir . '/logs', $worldWritable, $io);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the security.salt value in the application's config file.
|
||||
*
|
||||
* @param string $dir The application's root directory.
|
||||
* @param \Composer\IO\IOInterface $io IO interface to write to console.
|
||||
* @return void
|
||||
*/
|
||||
public static function setSecuritySalt($dir, $io)
|
||||
{
|
||||
$newKey = hash('sha256', Security::randomBytes(64));
|
||||
static::setSecuritySaltInFile($dir, $io, $newKey, 'app.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the security.salt value in a given file
|
||||
*
|
||||
* @param string $dir The application's root directory.
|
||||
* @param \Composer\IO\IOInterface $io IO interface to write to console.
|
||||
* @param string $newKey key to set in the file
|
||||
* @param string $file A path to a file relative to the application's root
|
||||
* @return void
|
||||
*/
|
||||
public static function setSecuritySaltInFile($dir, $io, $newKey, $file)
|
||||
{
|
||||
$config = $dir . '/config/' . $file;
|
||||
$content = file_get_contents($config);
|
||||
|
||||
$content = str_replace('__SALT__', $newKey, $content, $count);
|
||||
|
||||
if ($count == 0) {
|
||||
$io->write('No Security.salt placeholder to replace.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$result = file_put_contents($config, $content);
|
||||
if ($result) {
|
||||
$io->write('Updated Security.salt value in config/' . $file);
|
||||
|
||||
return;
|
||||
}
|
||||
$io->write('Unable to update Security.salt value.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the APP_NAME value in a given file
|
||||
*
|
||||
* @param string $dir The application's root directory.
|
||||
* @param \Composer\IO\IOInterface $io IO interface to write to console.
|
||||
* @param string $appName app name to set in the file
|
||||
* @param string $file A path to a file relative to the application's root
|
||||
* @return void
|
||||
*/
|
||||
public static function setAppNameInFile($dir, $io, $appName, $file)
|
||||
{
|
||||
$config = $dir . '/config/' . $file;
|
||||
$content = file_get_contents($config);
|
||||
$content = str_replace('__APP_NAME__', $appName, $content, $count);
|
||||
|
||||
if ($count == 0) {
|
||||
$io->write('No __APP_NAME__ placeholder to replace.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$result = file_put_contents($config, $content);
|
||||
if ($result) {
|
||||
$io->write('Updated __APP_NAME__ value in config/' . $file);
|
||||
|
||||
return;
|
||||
}
|
||||
$io->write('Unable to update __APP_NAME__ value.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\Controller\Controller;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Http\Exception\NotFoundException;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Routing\Router;
|
||||
use BrowserDetection;
|
||||
use Cake\Utility\Hash;
|
||||
|
||||
class AppController extends Controller
|
||||
{
|
||||
public $config = null;
|
||||
|
||||
public function initialize() {
|
||||
parent::initialize();
|
||||
|
||||
$this->loadComponent('RequestHandler', [
|
||||
'enableBeforeRedirect' => false
|
||||
]);
|
||||
|
||||
$this->loadComponent('Flash');
|
||||
|
||||
}
|
||||
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
|
||||
$browser = new BrowserDetection();
|
||||
if (($browser->getName() == BrowserDetection::BROWSER_IE &&
|
||||
$browser->compareVersions($browser->getVersion(), '11.0') < 0) ||
|
||||
|
||||
($browser->getName() == BrowserDetection::BROWSER_OPERA &&
|
||||
$browser->compareVersions($browser->getVersion(), '20.0') < 0) ||
|
||||
|
||||
($browser->getName() == BrowserDetection::BROWSER_CHROME &&
|
||||
$browser->compareVersions($browser->getVersion(), '40.0') < 0) ||
|
||||
|
||||
($browser->getName() == BrowserDetection::BROWSER_FIREFOX &&
|
||||
$browser->compareVersions($browser->getVersion(), '50.0') < 0)
|
||||
){
|
||||
$this->set("isRejectedBrowser", true);
|
||||
}
|
||||
|
||||
$request = Router::getRequest();
|
||||
$controller = $request->getParam('controller');
|
||||
|
||||
if (in_array($controller, ["OrderPayment"])) {
|
||||
$currentApp = "orderPayment";
|
||||
}
|
||||
|
||||
$this->config = $this->getAppConfig($currentApp);
|
||||
$this->set('siteTitle', $this->config['common']['siteTitle']['value']);
|
||||
}
|
||||
|
||||
public function jsonSimpleResponse($result, $withCORS = false) {
|
||||
if ($withCORS) {
|
||||
$this->response->setHeader('Access-Control-Allow-Origin: *');
|
||||
}
|
||||
|
||||
$this->set(compact('result'));
|
||||
$this->RequestHandler->renderAs($this, 'json');
|
||||
$this->render('/Element/json_result');
|
||||
}
|
||||
|
||||
public function getAppConfig($app) {
|
||||
$config = [];
|
||||
|
||||
$settings = TableRegistry::getTableLocator()->get('Settings')->find('all')->toArray();
|
||||
foreach ($settings as $s) {
|
||||
if (!isset($config[$s['group']])) {
|
||||
$config[$s['group']] = [];
|
||||
}
|
||||
|
||||
if (in_array($s['key'], ["smtpParams"])) {
|
||||
$s['value'] = @json_decode($s['value'], true);
|
||||
}
|
||||
|
||||
$config[$s['group']][$s['key']] = [
|
||||
"id" => $s['key'],
|
||||
"label" => $s['label'],
|
||||
"value" => $s['value']
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
$tmpDelivery = $this->getDeliveryListForJS();
|
||||
$config['delivery'] = [];
|
||||
foreach ($tmpDelivery as $delivery) {
|
||||
$config['delivery'][$delivery['id']] = $delivery->toArray();
|
||||
}
|
||||
|
||||
$config["encrypt"] = Configure::read("encrypt");
|
||||
|
||||
$config["appsList"] = [
|
||||
"cut" => [
|
||||
"id" => "cut",
|
||||
"label" => "Раскрой ДСП",
|
||||
"label_long" => "Раскрой ДСП",
|
||||
"site_label" => "Online распил ДСП",
|
||||
"url" => "https://apps.supersamsev.ru/cut",
|
||||
],
|
||||
"fasad" => [
|
||||
"id" => "fasad",
|
||||
"label" => "Распил фасадов",
|
||||
"label_long" => "Распил фасадов",
|
||||
"site_label" => "Online распил фасадов",
|
||||
"url" => "fasad",
|
||||
],
|
||||
"calcDoors" => [
|
||||
"id" => "calcDoors",
|
||||
"label" => "Двери",
|
||||
"label_long" => "Расчет стоимости изготовления дверей",
|
||||
//"url" => "https://apps.supersamsev.ru/calc-doors",
|
||||
],
|
||||
"ordersInfo" => [
|
||||
"id" => "ordersInfo",
|
||||
"label" => "Информация по счетам",
|
||||
"label_long" => "Информация по счетам",
|
||||
"url" => "https://apps.supersamsev.ru/orders-info",
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
public function getAppJsConfig($app = "", $isManager = false, $savedOrderData = null, $orderClientId = null) {
|
||||
$conditions = [];
|
||||
$jsConfig = [
|
||||
"urls" => [],
|
||||
"primarySiteUrl" => "https://prometeysev.ru/",
|
||||
"siteDomain" => "prometeysev.ru",
|
||||
"primarySiteTitle" => 'ООО ТЦ Прометей',
|
||||
"branches" => [],
|
||||
"delivery" => [],
|
||||
"global_labels" => $this->config["global_labels"],
|
||||
];
|
||||
|
||||
$conditions = ['is_active' => true];
|
||||
|
||||
$jsConfig = array_merge($jsConfig, [
|
||||
"version" => Configure::read('Release')
|
||||
]);
|
||||
|
||||
$jsConfig = array_merge($jsConfig, [
|
||||
"common" => $this->config["common"],
|
||||
"global" => $this->config["global"],
|
||||
]);
|
||||
|
||||
|
||||
if ($app == "orderPayment") {
|
||||
$jsConfig = array_merge($jsConfig, [
|
||||
"getPaymentStatusUrl" => Router::url(['controller' => 'OrderPayment', 'action' => 'get_payment_status', 'prefix' => false]),
|
||||
"orderPayment" => (isset($this->config["order_payment"]) ? $this->config["order_payment"] : []),
|
||||
]);
|
||||
}
|
||||
|
||||
$request = Router::getRequest();
|
||||
$jsConfig["appsList"] = $this->config["appsList"];
|
||||
|
||||
foreach ($this->config["delivery"] as $cfgKey => $cfgDelivery) {
|
||||
if (empty($cfgDelivery["is_deleted"])) {
|
||||
$jsConfig["delivery"][] = array_merge(['id' => $cfgKey], $cfgDelivery);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$jsConfig['savedOrderData'] = $savedOrderData;
|
||||
}
|
||||
|
||||
return $jsConfig;
|
||||
}
|
||||
|
||||
public function patchTimestampForJS($date, $delta = 1, $returnDateString = true, $format = 'd-m-Y H:i') {
|
||||
$date = new \DateTime($date);
|
||||
date_sub($date, date_interval_create_from_date_string($delta . ' hour'));
|
||||
|
||||
if ($returnDateString) {
|
||||
return $date->format($format);
|
||||
} else {
|
||||
return $date;
|
||||
}
|
||||
}
|
||||
|
||||
public function getDeliveryListForJS() {
|
||||
return TableRegistry::getTableLocator()->get('Delivery')->find('all')->order(['Delivery.label' => 'ASC'])->all()->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Whitespace-only changes.
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\Event\Event;
|
||||
|
||||
class ErrorController extends AppController {
|
||||
|
||||
public $config = null;
|
||||
|
||||
public function initialize() {
|
||||
$this->loadComponent('RequestHandler');
|
||||
}
|
||||
|
||||
public function beforeFilter(Event $event) {
|
||||
}
|
||||
|
||||
public function beforeRender(Event $event) {
|
||||
parent::beforeRender($event);
|
||||
|
||||
$this->viewBuilder()->setTemplatePath('Error');
|
||||
$this->config = $this->getAppConfig("");
|
||||
$this->set('jsConfig', $this->getAppJsConfig("", false));
|
||||
}
|
||||
|
||||
public function afterFilter(Event $event) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
class OrderPaymentController extends AppController {
|
||||
public function display() {
|
||||
$this->redirect('https://apps.supersamsev.ru/services');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace App\Model\Entity;
|
||||
|
||||
|
||||
use Cake\ORM\Entity;
|
||||
use Cake\Auth\DefaultPasswordHasher;
|
||||
|
||||
class User extends Entity {
|
||||
|
||||
protected $_accessible = [
|
||||
'*' => true,
|
||||
'id' => false
|
||||
];
|
||||
|
||||
protected function _setPassword($password) {
|
||||
return (new DefaultPasswordHasher)->hash($password);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
$class = 'message';
|
||||
if (!empty($params['class'])) {
|
||||
$class .= ' ' . $params['class'];
|
||||
}
|
||||
if (!isset($params['escape']) || $params['escape'] !== false) {
|
||||
$message = h($message);
|
||||
}
|
||||
?>
|
||||
<div class="<?= h($class) ?>" onclick="this.classList.add('hidden');"><?= $message ?></div>
|
||||
@@ -0,0 +1,4 @@
|
||||
<div class="alert alert-danger alert-dismissable">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<p><?= $message ?></p>
|
||||
</div>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
if (!isset($params['escape']) || $params['escape'] !== false) {
|
||||
$message = h($message);
|
||||
}
|
||||
?>
|
||||
<div class="message success" onclick="this.classList.add('hidden')"><?= $message ?></div>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php use Cake\Core\Configure;?>
|
||||
|
||||
<script type="text/javascript">
|
||||
prometeysevApp.factory('config', function() {
|
||||
return <?php echo json_encode(isset($jsConfig) ? $jsConfig : []); ?>;
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,38 @@
|
||||
<script type="text/javascript">
|
||||
function getCookie(name) {
|
||||
var value = "; " + document.cookie;
|
||||
var parts = value.split("; " + name + "=");
|
||||
if (parts.length == 2) return parts.pop().split(";").shift();
|
||||
else return null;
|
||||
}
|
||||
|
||||
function setCookie(name,value,days) {
|
||||
var expires = "";
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days*24*60*60*1000));
|
||||
expires = "; expires=" + date.toUTCString();
|
||||
}
|
||||
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
||||
}
|
||||
|
||||
(function($, document) {
|
||||
$(document).ready(function () {
|
||||
var cookieConsent = getCookie("cookie_consent");
|
||||
if (cookieConsent == null) {
|
||||
$("<div class=\"cookie-consent-container-wrap\"><div class=\"cookie-consent-container\"></div>"+
|
||||
"<div class=\"cookie-consent-content\">"+
|
||||
"<div><span>Мы используем файлы cookie, чтобы обеспечить максимальное удобство пользователям. Продолжая использовать этот сайт, вы даете согласие на использование файлов cookies.</span> <a href=\"https://prometeysev.ru/cookie-policy\" class=\"cookie-consent-more\" target=\"_blank\">Подробнее</a></div>"+
|
||||
"<a class=\"cookie-consent-ok\">Согласен</a>"+
|
||||
"</div>"+
|
||||
"</div>").appendTo('body');
|
||||
|
||||
|
||||
$(".cookie-consent-ok").on('click', function () {
|
||||
setCookie('cookie_consent', true, 1095);
|
||||
$(".cookie-consent-container-wrap").css({'opacity': '0', 'visibility': 'hidden'});
|
||||
});
|
||||
}
|
||||
})
|
||||
})(jQuery, document);
|
||||
</script>
|
||||
@@ -0,0 +1,8 @@
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon/favicon_32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon/favicon_16.png">
|
||||
|
||||
<link rel="shortcut icon" type="image/png" href="/img/favicon/favicon_16.png" />
|
||||
<?php foreach(['57', '60', '76', '114', '120', '128', '144', '152', '167', '180', '192'] as $s) {
|
||||
echo '<link rel="apple-touch-icon-precomposed" sizes="' . $s . 'x' . $s . '" href="/img/favicon/apple-touch-icon-' . $s . '-precomposed.png" />' . "\n";
|
||||
} ?>
|
||||
<link rel="apple-touch-icon-precomposed" href="/img/favicon/apple-touch-icon-57-precomposed.png" />
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo json_encode($result);
|
||||
@@ -0,0 +1,15 @@
|
||||
<div class="page-404">
|
||||
<div class="container">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
<a href="<?=$jsConfig['primarySiteUrl'];?>" title="<?=$jsConfig['primarySiteTitle'];?>"><img class="apps-logo" src="/img/logo-<?=$jsConfig['siteDomain'];?>.png"></a><br/><br/>
|
||||
|
||||
<?= $this->element("services");?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,36 @@
|
||||
<div>
|
||||
<a href="https://supersam24.ru" class="services-link btn btn-primary">Магазин фурнитуры</a>
|
||||
<a href="https://supersamsev.ru" class="services-link btn btn-primary">Магазин ДСП</a>
|
||||
<a href="https://prometeysev.ru" class="services-link btn btn-primary">Все для кухни, ремонта и дома</a>
|
||||
|
||||
<div class="services-social-links">
|
||||
<a class="vk" href="https://vk.com/supersam_aristo" target="_blank">
|
||||
<img src="/img/social/vk-h.png">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<br/><br/></div>
|
||||
|
||||
<b>Также вы можете воспользоваться нашими сервисами:</b><br/>
|
||||
<div>
|
||||
<?php
|
||||
foreach ($jsConfig["appsList"] as $app) {
|
||||
if (!empty($app['url'])) {
|
||||
echo '<a href="' . $app['url'] . '" class="services-link btn btn-info">' . (!empty($app['site_label']) ? $app['site_label'] : $app['label_long']) . '</a>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
<div>
|
||||
<?php
|
||||
foreach ($jsConfig["delivery"] as $delivery) {
|
||||
if (empty($delivery['is_deleted'])) {
|
||||
echo '<a href="/delivery/' . $delivery['slug'] . '" class="services-link btn btn-info">' . $delivery['label404'] . '</a>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 0.10.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
$content = explode("\n", $content);
|
||||
|
||||
foreach ($content as $line) :
|
||||
echo '<p> ' . $line . "</p>\n";
|
||||
endforeach;
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 0.10.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
echo $content;
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Error\Debugger;
|
||||
|
||||
$this->layout = 'error';
|
||||
|
||||
if (Configure::read('debug')) :
|
||||
$this->layout = 'dev_error';
|
||||
|
||||
$this->assign('title', $message);
|
||||
$this->assign('templateName', 'error400.ctp');
|
||||
|
||||
$this->start('file');
|
||||
?>
|
||||
<?php if (!empty($error->queryString)) : ?>
|
||||
<p class="notice">
|
||||
<strong>SQL Query: </strong>
|
||||
<?= h($error->queryString) ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($error->params)) : ?>
|
||||
<strong>SQL Query Params: </strong>
|
||||
<?php Debugger::dump($error->params) ?>
|
||||
<?php endif; ?>
|
||||
<?= $this->element('auto_table_warning') ?>
|
||||
<?php
|
||||
if (extension_loaded('xdebug')) :
|
||||
xdebug_print_function_stack();
|
||||
endif;
|
||||
|
||||
$this->end();
|
||||
endif;
|
||||
?>
|
||||
<?= $this->element("page404");?>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Error\Debugger;
|
||||
|
||||
$this->layout = 'error';
|
||||
|
||||
if (Configure::read('debug')) :
|
||||
$this->layout = 'dev_error';
|
||||
|
||||
$this->assign('title', $message);
|
||||
$this->assign('templateName', 'error500.ctp');
|
||||
|
||||
$this->start('file');
|
||||
?>
|
||||
<?php if (!empty($error->queryString)) : ?>
|
||||
<p class="notice">
|
||||
<strong>SQL Query: </strong>
|
||||
<?= h($error->queryString) ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($error->params)) : ?>
|
||||
<strong>SQL Query Params: </strong>
|
||||
<?php Debugger::dump($error->params) ?>
|
||||
<?php endif; ?>
|
||||
<?php if ($error instanceof Error) : ?>
|
||||
<strong>Error in: </strong>
|
||||
<?= sprintf('%s, line %s', str_replace(ROOT, 'ROOT', $error->getFile()), $error->getLine()) ?>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
echo $this->element('auto_table_warning');
|
||||
|
||||
if (extension_loaded('xdebug')) :
|
||||
xdebug_print_function_stack();
|
||||
endif;
|
||||
|
||||
$this->end();
|
||||
endif;
|
||||
?>
|
||||
<?= $this->element("page404");?>
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 0.10.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title><?= $this->fetch('title') ?></title>
|
||||
</head>
|
||||
<body>
|
||||
<?= $this->fetch('content') ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 0.10.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
echo $this->fetch('content');
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 0.10.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
echo $this->fetch('content');
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php use Cake\Core\Configure; ?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<?= $this->Html->charset() ?>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>СуперСам :: 404</title>
|
||||
<?php echo $this->element("favicon"); ?>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
||||
<?php if (empty($isRejectedBrowser)) {
|
||||
$release = "?v".Configure::read('Release');
|
||||
|
||||
$cssList = [
|
||||
"bootstrap.min.css",
|
||||
"styles.css",
|
||||
];
|
||||
|
||||
foreach ($cssList as $key => $css) {
|
||||
$cssList[$key] = $css.$release;
|
||||
}
|
||||
echo $this->Html->css($cssList);
|
||||
} else {
|
||||
echo $this->Html->css('jquery.reject');
|
||||
} ?>
|
||||
|
||||
<?= $this->fetch('meta'); ?>
|
||||
<?= $this->fetch('css'); ?>
|
||||
<?= $this->fetch('script'); ?>
|
||||
|
||||
<base href="/">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<?php if (empty($isRejectedBrowser)) {
|
||||
$scripts = [
|
||||
"jquery.min.js",
|
||||
];
|
||||
|
||||
foreach ($scripts as $key => $script) {
|
||||
$scripts[$key] = $script.$release;
|
||||
}
|
||||
|
||||
echo $this->Html->script($scripts);
|
||||
echo $this->fetch('content');
|
||||
echo $this->element('cookie_consent');
|
||||
} else {
|
||||
echo $this->Html->script("jquery-1.min.js");
|
||||
echo $this->Html->script("jquery.reject.js");
|
||||
echo $this->Html->script("jquery.reject-config.js");
|
||||
} ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
if (!isset($channel)) :
|
||||
$channel = [];
|
||||
endif;
|
||||
if (!isset($channel['title'])) :
|
||||
$channel['title'] = $this->fetch('title');
|
||||
endif;
|
||||
|
||||
echo $this->Rss->document(
|
||||
$this->Rss->channel([], $channel, $this->fetch('content'))
|
||||
);
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.4
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace App\View;
|
||||
|
||||
use Cake\Event\EventManager;
|
||||
use Cake\Http\Response;
|
||||
use Cake\Http\ServerRequest;
|
||||
|
||||
/**
|
||||
* A view class that is used for AJAX responses.
|
||||
* Currently only switches the default layout and sets the response type -
|
||||
* which just maps to text/html by default.
|
||||
*/
|
||||
class AjaxView extends AppView
|
||||
{
|
||||
|
||||
/**
|
||||
* The name of the layout file to render the view inside of. The name
|
||||
* specified is the filename of the layout in /src/Template/Layout without
|
||||
* the .ctp extension.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $layout = 'ajax';
|
||||
|
||||
/**
|
||||
* Initialization hook method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
$this->response = $this->response->withType('ajax');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace App\View;
|
||||
|
||||
use Cake\View\View;
|
||||
|
||||
/**
|
||||
* Application View
|
||||
*
|
||||
* Your application’s default view class
|
||||
*
|
||||
* @link https://book.cakephp.org/3.0/en/views.html#the-app-view
|
||||
*/
|
||||
class AppView extends View
|
||||
{
|
||||
|
||||
/**
|
||||
* Initialization hook method.
|
||||
*
|
||||
* Use this method to add common initialization code like loading helpers.
|
||||
*
|
||||
* e.g. `$this->loadHelper('Html');`
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
}
|
||||
}
|
||||
Whitespace-only changes.
Whitespace-only changes.
@@ -0,0 +1,4 @@
|
||||
/vendor/
|
||||
*.cache
|
||||
composer.lock
|
||||
phpunit.xml
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
$header = <<<EOF
|
||||
AJGL Breakpoint Twig Extension Component
|
||||
|
||||
Copyright (C) Antonio J. García Lagar <aj@garcialagar.es>
|
||||
|
||||
For the full copyright and license information, please view the LICENSE
|
||||
file that was distributed with this source code.
|
||||
EOF;
|
||||
|
||||
return \PhpCsFixer\Config::create()
|
||||
->setRiskyAllowed(true)
|
||||
->setRules(
|
||||
[
|
||||
'@Symfony' => true,
|
||||
'@Symfony:risky' => true,
|
||||
'array_syntax' => array('syntax' => 'short'),
|
||||
'fully_qualified_strict_types' => true,
|
||||
'header_comment' => array('header' => $header),
|
||||
'native_function_invocation' => false,
|
||||
'ordered_imports' => [
|
||||
'imports_order' => ['class', 'const', 'function'],
|
||||
],
|
||||
'phpdoc_order' => true,
|
||||
'psr4' => true,
|
||||
'strict_comparison' => true,
|
||||
'strict_param' => true,
|
||||
]
|
||||
)
|
||||
->setFinder(
|
||||
\PhpCsFixer\Finder::create()
|
||||
->in(__DIR__.'/src')
|
||||
->in(__DIR__.'/tests')
|
||||
)
|
||||
;
|
||||
@@ -0,0 +1,7 @@
|
||||
# .scrutinizer.yml
|
||||
checks:
|
||||
php: true
|
||||
|
||||
tools:
|
||||
external_code_coverage:
|
||||
timeout: 900
|
||||
@@ -0,0 +1,68 @@
|
||||
language: php
|
||||
sudo: false
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache/files
|
||||
- $HOME/symfony-bridge/.phpunit
|
||||
|
||||
env:
|
||||
global:
|
||||
- PHPUNIT_FLAGS="-v"
|
||||
- SYMFONY_PHPUNIT_DIR="$HOME/symfony-bridge/.phpunit"
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
# Minimum supported dependencies with the latest and oldest PHP version
|
||||
- php: 7.3
|
||||
env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" SYMFONY_DEPRECATIONS_HELPER="weak_vendors"
|
||||
- php: 5.6
|
||||
env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" SYMFONY_DEPRECATIONS_HELPER="weak_vendors"
|
||||
|
||||
# Test the latest stable release
|
||||
- php: 5.6
|
||||
- php: 7.0
|
||||
- php: 7.1
|
||||
- php: 7.2
|
||||
- php: 7.3
|
||||
env: COVERAGE=true PHPUNIT_FLAGS="-v --coverage-text" LINT=true
|
||||
|
||||
# Test LTS versions. This makes sure we do not use Symfony packages with version greater
|
||||
# than 2 or 3 respectively. Read more at https://github.com/symfony/lts
|
||||
- php: 7.3
|
||||
env: DEPENDENCIES="symfony/lts:^2"
|
||||
- php: 7.3
|
||||
env: DEPENDENCIES="symfony/lts:^3"
|
||||
|
||||
# Latest commit to master
|
||||
- php: 7.3
|
||||
env: STABILITY="dev"
|
||||
- php: 7.4
|
||||
env: STABILITY="dev"
|
||||
- php: nightly
|
||||
env: STABILITY="dev"
|
||||
|
||||
allow_failures:
|
||||
# Dev-master is allowed to fail.
|
||||
- env: STABILITY="dev"
|
||||
|
||||
before_install:
|
||||
- if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi
|
||||
- if ! [ -z "$STABILITY" ]; then composer config minimum-stability ${STABILITY}; fi;
|
||||
- if ! [ -v "$DEPENDENCIES" ]; then composer require --no-update ${DEPENDENCIES}; fi;
|
||||
- if [[ $LINT = true ]]; then wget https://cs.symfony.com/download/php-cs-fixer-v2.phar; fi
|
||||
|
||||
install:
|
||||
- composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction
|
||||
- ./vendor/bin/simple-phpunit install
|
||||
|
||||
script:
|
||||
- composer validate --strict --no-check-lock
|
||||
- if [[ $LINT = true ]]; then php php-cs-fixer-v2.phar fix --dry-run --diff --no-ansi; fi
|
||||
# simple-phpunit is the PHPUnit wrapper provided by the PHPUnit Bridge component and
|
||||
# it helps with testing legacy code and deprecations (composer require symfony/phpunit-bridge)
|
||||
- ./vendor/bin/simple-phpunit $PHPUNIT_FLAGS
|
||||
|
||||
after_script:
|
||||
- wget https://scrutinizer-ci.com/ocular.phar
|
||||
- php ocular.phar code-coverage:upload --format=php-clover coverage.clover
|
||||
@@ -0,0 +1,60 @@
|
||||
# [CHANGELOG](http://keepachangelog.com/)
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [Unreleased][unreleased]
|
||||
|
||||
|
||||
## [0.3.4] - 2019-04-10
|
||||
|
||||
### Fixed
|
||||
- Population of `$arguments` variable
|
||||
|
||||
|
||||
## [0.3.3] - 2019-03-18
|
||||
|
||||
### Fixed
|
||||
- Population of `$arguments` variable
|
||||
- Usage of deprecated classes
|
||||
|
||||
|
||||
## [0.3.2] - 2018-12-10
|
||||
|
||||
### Added
|
||||
- Add support for Symfony 4
|
||||
|
||||
## [0.3.1] - 2017-11-20
|
||||
|
||||
### Changed
|
||||
- Require PHP 5.6
|
||||
|
||||
### Fixed
|
||||
- Update requirements to allow twig 2.x
|
||||
|
||||
|
||||
## [0.3.0] - 2016-03-31
|
||||
|
||||
### Added
|
||||
- Add `$environment` and `$context` variables
|
||||
- Allow to inspect function arguments
|
||||
|
||||
|
||||
## [0.2.0] - 2016-03-10
|
||||
|
||||
### Added
|
||||
- Add Symfony Bundle
|
||||
|
||||
|
||||
## 0.1.0 - 2016-03-09
|
||||
|
||||
### Added
|
||||
- Add `breakpoint` function
|
||||
|
||||
|
||||
[unreleased]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.3.4...master
|
||||
[0.3.4]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.3.3...0.3.4
|
||||
[0.3.3]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.3.2...0.3.3
|
||||
[0.3.2]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.3.1...0.3.2
|
||||
[0.3.1]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.3.0...0.3.1
|
||||
[0.3.0]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.2.0...0.3.0
|
||||
[0.2.0]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.1.0...0.2.0
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
Copyright (c) 2013-2016 Antonio J. García Lagar <aj@garcialagar.es>
|
||||
|
||||
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.
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
AjglBreakpointTwigExtension
|
||||
===========================
|
||||
|
||||
The AjglBreakpointTwigExtension component allows you set breakpoints in twig templates.
|
||||
|
||||
[](https://travis-ci.org/ajgarlag/AjglBreakpointTwigExtension)
|
||||
[](https://packagist.org/packages/ajgl/breakpoint-twig-extension)
|
||||
[](https://packagist.org/packages/ajgl/breakpoint-twig-extension)
|
||||
[](https://packagist.org/packages/ajgl/breakpoint-twig-extension)
|
||||
[](https://packagist.org/packages/ajgl/breakpoint-twig-extension)
|
||||
[](https://packagist.org/packages/ajgl/breakpoint-twig-extension)
|
||||
[](https://packagist.org/packages/ajgl/breakpoint-twig-extension)
|
||||
[](https://scrutinizer-ci.com/g/ajgarlag/AjglBreakpointTwigExtension/?branch=master)
|
||||
[](https://scrutinizer-ci.com/g/ajgarlag/AjglBreakpointTwigExtension/?branch=master)
|
||||
[](https://insight.sensiolabs.com/projects/e0f1276d-6ded-4a20-9b3f-1a7c77a92015)
|
||||
|
||||
This component requires the [Xdebug] PHP extension to be installed.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
To install the latest stable version of this component, open a console and execute the following command:
|
||||
```
|
||||
$ composer require ajgl/breakpoint-twig-extension
|
||||
```
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The first step is to register the extension into the twig environment
|
||||
```php
|
||||
/* @var $twig Twig_Environment */
|
||||
$twig->addExtension(new Ajgl\Twig\Extension\BreakpointExtension());
|
||||
```
|
||||
|
||||
Once registered, you can call the new `breakpoint` function:
|
||||
```twig
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>title</title>
|
||||
</head>
|
||||
<body>
|
||||
{{ breakpoint() }}
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Once stopped, your debugger will allow you to inspect the `$environment` and `$context` variables.
|
||||
|
||||
### Function arguments
|
||||
|
||||
Any argument passed to the twig function will be added to the `$arguments` array, so you can inspect it easily.
|
||||
|
||||
```twig
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>title</title>
|
||||
</head>
|
||||
<body>
|
||||
{{ breakpoint(app.user, app.session) }}
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Symfony Bundle
|
||||
--------------
|
||||
|
||||
If you want to use this extension in your Symfony application, you can enable the
|
||||
Symfony Bundle included in this package.
|
||||
|
||||
The bundle will register the twig extension automatically. So, once enabled, you
|
||||
can insert the `breakpoint` twig function in your templates.
|
||||
|
||||
### Symfony 2/3
|
||||
|
||||
```php
|
||||
// app/AppKernel.php
|
||||
if (in_array($this->getEnvironment(), array('dev', 'test'), true)) {
|
||||
$bundles[] = new Ajgl\Twig\Extension\SymfonyBundle\AjglBreakpointTwigExtensionBundle();
|
||||
}
|
||||
```
|
||||
|
||||
### Symfony 4
|
||||
|
||||
```php
|
||||
// config/bundles.php
|
||||
//...
|
||||
return [
|
||||
//...
|
||||
Ajgl\Twig\Extension\SymfonyBundle\AjglBreakpointTwigExtensionBundle::class => ['dev' => true]
|
||||
];
|
||||
```
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This component is under the MIT license. See the complete license in the [LICENSE] file.
|
||||
|
||||
|
||||
Reporting an issue or a feature request
|
||||
---------------------------------------
|
||||
|
||||
Issues and feature requests are tracked in the [Github issue tracker].
|
||||
|
||||
|
||||
Author Information
|
||||
------------------
|
||||
|
||||
Developed with ♥ by [Antonio J. García Lagar].
|
||||
|
||||
If you find this component useful, please add a ★ in the [GitHub repository page] and/or the [Packagist package page].
|
||||
|
||||
[Xdebug]: https://xdebug.org/
|
||||
[LICENSE]: LICENSE
|
||||
[Github issue tracker]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/issues
|
||||
[Antonio J. García Lagar]: http://aj.garcialagar.es
|
||||
[GitHub repository page]: https://github.com/ajgarlag/AjglBreakpointTwigExtension
|
||||
[Packagist package page]: https://packagist.org/packages/ajgl/breakpoint-twig-extension
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "ajgl/breakpoint-twig-extension",
|
||||
"description": "Twig extension to set breakpoints",
|
||||
"keywords": ["twig", "xdebug", "breakpoint"],
|
||||
"homepage": "https://github.com/ajgarlag/AjglBreakpointTwigExtension",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Antonio J. García Lagar",
|
||||
"email": "aj@garcialagar.es",
|
||||
"homepage": "http://aj.garcialagar.es",
|
||||
"role": "developer"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": { "Ajgl\\Twig\\Extension\\": "src/" }
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": { "Ajgl\\Twig\\Extension\\Tests\\": "tests/" }
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.6",
|
||||
"twig/twig": "^1.14|^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/framework-bundle": "^2.7|^3.2|^4.1",
|
||||
"symfony/twig-bundle": "^2.7|^3.2|^4.1",
|
||||
"symfony/phpunit-bridge": "^3.4|^4.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-xdebug": "The Xdebug extension is required for the breakpoint to work",
|
||||
"symfony/framework-bundle": "The framework bundle to integrate the extension into Symfony",
|
||||
"symfony/twig-bundle": "The twig bundle to integrate the extension into Symfony"
|
||||
},
|
||||
"scripts": {
|
||||
"phpunit": "vendor/bin/simple-phpunit --colors=always",
|
||||
"test": [
|
||||
"@phpunit"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.3.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.0/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="AjglBreakpointTwigExtension Test Suite">
|
||||
<directory>./tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>./src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
|
||||
</phpunit>
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* AJGL Breakpoint Twig Extension Component
|
||||
*
|
||||
* Copyright (C) Antonio J. García Lagar <aj@garcialagar.es>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Ajgl\Twig\Extension;
|
||||
|
||||
use Twig\Environment;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* @author Antonio J. García Lagar <aj@garcialagar.es>
|
||||
*/
|
||||
class BreakpointExtension extends AbstractExtension
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'breakpoint';
|
||||
}
|
||||
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new TwigFunction('breakpoint', [$this, 'setBreakpoint'], ['needs_environment' => true, 'needs_context' => true]),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* If Xdebug is detected, makes the debugger break.
|
||||
*
|
||||
* @param Environment $environment the environment instance
|
||||
* @param mixed $context variables from the Twig template
|
||||
*/
|
||||
public function setBreakpoint(Environment $environment, $context)
|
||||
{
|
||||
if (function_exists('xdebug_break')) {
|
||||
$arguments = func_get_args();
|
||||
$arguments = array_slice($arguments, 2);
|
||||
xdebug_break();
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* AJGL Breakpoint Twig Extension Component
|
||||
*
|
||||
* Copyright (C) Antonio J. García Lagar <aj@garcialagar.es>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Ajgl\Twig\Extension\SymfonyBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
/**
|
||||
* @author Antonio J. García Lagar <aj@garcialagar.es>
|
||||
*/
|
||||
class AjglBreakpointTwigExtensionBundle extends Bundle
|
||||
{
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* AJGL Breakpoint Twig Extension Component
|
||||
*
|
||||
* Copyright (C) Antonio J. García Lagar <aj@garcialagar.es>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Ajgl\Twig\Extension\SymfonyBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Loader;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
|
||||
/**
|
||||
* @author Antonio J. García Lagar <aj@garcialagar.es>
|
||||
*/
|
||||
class AjglBreakpointTwigExtensionExtension extends Extension
|
||||
{
|
||||
public function load(array $config, ContainerBuilder $container)
|
||||
{
|
||||
$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||
$loader->load('twig.xml');
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<container xmlns="http://symfony.com/schema/dic/services"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<services>
|
||||
<service id="ajgl_twig_extension.breakpoint" class="Ajgl\Twig\Extension\BreakpointExtension" public="false">
|
||||
<tag name="twig.extension"/>
|
||||
</service>
|
||||
</services>
|
||||
|
||||
</container>
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* AJGL Breakpoint Twig Extension Component
|
||||
*
|
||||
* Copyright (C) Antonio J. García Lagar <aj@garcialagar.es>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Ajgl\Twig\Extension\Tests;
|
||||
|
||||
use Ajgl\Twig\Extension\BreakpointExtension;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @author Antonio J. García Lagar <aj@garcialagar.es>
|
||||
*/
|
||||
class BreakpointExtensionTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var BreakpointExtension
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->extension = new BreakpointExtension();
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$this->assertSame('breakpoint', $this->extension->getName());
|
||||
}
|
||||
|
||||
public function testGetFunctions()
|
||||
{
|
||||
$functions = $this->extension->getFunctions();
|
||||
$this->assertCount(1, $functions);
|
||||
$function = reset($functions);
|
||||
$this->assertInstanceOf('Twig_SimpleFunction', $function);
|
||||
$callable = $function->getCallable();
|
||||
$this->assertTrue(is_array($callable));
|
||||
$this->assertCount(2, $callable);
|
||||
$this->assertSame($this->extension, $callable[0]);
|
||||
$this->assertSame('setBreakpoint', $callable[1]);
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* AJGL Breakpoint Twig Extension Component
|
||||
*
|
||||
* Copyright (C) Antonio J. García Lagar <aj@garcialagar.es>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Ajgl\Twig\Extension\Tests\SymfonyBundle\DependencyInjection;
|
||||
|
||||
use Ajgl\Twig\Extension\SymfonyBundle\DependencyInjection\AjglBreakpointTwigExtensionExtension;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* @author Antonio J. García Lagar <aj@garcialagar.es>
|
||||
*/
|
||||
class AjglBreakpointTwigExtensionExtensionTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var ContainerBuilder
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* @var AjglBreakpointTwigExtensionExtension
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->container = new ContainerBuilder();
|
||||
$this->extension = new AjglBreakpointTwigExtensionExtension();
|
||||
}
|
||||
|
||||
public function testTwigExtensionsDefinition()
|
||||
{
|
||||
$this->extension->load([], $this->container);
|
||||
$this->assertTrue($this->container->hasDefinition('ajgl_twig_extension.breakpoint'));
|
||||
$definition = $this->container->getDefinition('ajgl_twig_extension.breakpoint');
|
||||
$this->assertSame(
|
||||
'Ajgl\Twig\Extension\BreakpointExtension',
|
||||
$definition->getClass()
|
||||
);
|
||||
$this->assertNotNull($definition->getTag('twig.extension'));
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
language: php
|
||||
sudo: false
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7
|
||||
|
||||
env:
|
||||
global:
|
||||
# travis encrypt CODECLIMATE_REPO_TOKEN=<https://codeclimate.com/repos/53e0fcc8e30ba02d78013d4c/coverage_setup>
|
||||
- secure: "n4I9GwRCxi9UGjhDGe79SV6Nr/fRKpA8N+qqqbkveJv01Z4IRcAsRBRxKrSAX8zJUoFhlJK73VeRnBfdSBddsL3RqgDMbHilZFy6yC7Dj/vVyNe90RPWxc5J7w3sidT2g1OsgWueiUis8y3dGOQd2sewfcb2pZa29/eQusBV5i0="
|
||||
|
||||
install:
|
||||
- composer install
|
||||
|
||||
before_script:
|
||||
- mkdir -p build/logs
|
||||
|
||||
script:
|
||||
- vendor/bin/phpunit --coverage-clover build/logs/clover.xml
|
||||
|
||||
after_script:
|
||||
- php vendor/bin/coveralls -v
|
||||
- ./vendor/bin/test-reporter --stdout > codeclimate.json
|
||||
- "curl -X POST -d @codeclimate.json -H 'Content-Type: application/json' -H 'User-Agent: Code Climate (PHP Test Reporter v1.0.1-dev)' https://codeclimate.com/test_reports"
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
2.0.0
|
||||
-----
|
||||
|
||||
- **BC**: Require Twig v1.12, in order to replace deprecated Twig_Filter_Method with Twig_SimpleFilter
|
||||
- **Added**: Add support for ParsedownEnging
|
||||
|
||||
1.2.0
|
||||
-----
|
||||
|
||||
- **Added**: Add support for GitHub's markdown engine
|
||||
|
||||
1.1.0
|
||||
-----
|
||||
|
||||
- **Added**: Add support for PHP League CommonMark engine
|
||||
|
||||
1.0.0
|
||||
-----
|
||||
|
||||
- **BC**: Remove deprecated dflydev-markdown parser
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
Twig Markdown Extension
|
||||
=======================
|
||||
|
||||
[](http://travis-ci.org/aptoma/twig-markdown)
|
||||
[](https://coveralls.io/r/aptoma/twig-markdown)
|
||||
|
||||
Twig Markdown extension provides a new filter and a tag to allow parsing of
|
||||
content as Markdown in [Twig][1] templates.
|
||||
|
||||
This extension could be integrated with several Markdown parser as it provides an interface, which allows you to customize your Markdown parser.
|
||||
|
||||
### Supported parsers
|
||||
|
||||
* [michelf/php-markdown](https://github.com/michelf/php-markdown) (+ MarkdownExtra)
|
||||
* [league/commonmark](http://commonmark.thephpleague.com/)
|
||||
* [KnpLabs/php-github-api](https://github.com/KnpLabs/php-github-api)
|
||||
* [erusev/parsedown](https://github.com/erusev/parsedown)
|
||||
|
||||
## Features
|
||||
|
||||
* Filter support `{{ "# Heading Level 1"|markdown }}`
|
||||
* Tag support `{% markdown %}{% endmarkdown %}`
|
||||
|
||||
When used as a tag, the indentation level of the first line sets the default indentation level for the rest of the tag content.
|
||||
From this indentation level, all same indentation or outdented levels text will be transformed as regular text.
|
||||
|
||||
This feature allows you to write your Markdown content at any indentation level without caring of Markdown internal transformation:
|
||||
|
||||
```php
|
||||
<div>
|
||||
<h1 class="someClass">{{ title }}</h1>
|
||||
|
||||
{% markdown %}
|
||||
This is a list that is indented to match the context around the markdown tag:
|
||||
|
||||
* List item 1
|
||||
* List item 2
|
||||
* Sub List Item
|
||||
* Sub Sub List Item
|
||||
|
||||
The following block will be transformed as code, as it is indented more than the
|
||||
surrounding content:
|
||||
|
||||
$code = "good";
|
||||
|
||||
{% endmarkdown %}
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
Run the composer command to install the latest stable version:
|
||||
|
||||
```bash
|
||||
composer require aptoma/twig-markdown
|
||||
```
|
||||
|
||||
Or update your `composer.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"aptoma/twig-markdown": "~1.1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can choose to provide your own Markdown engine, although we recommend
|
||||
using [michelf/php-markdown](https://github.com/michelf/php-markdown):
|
||||
|
||||
```bash
|
||||
composer require michelf/php-markdown ~1.3
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"michelf/php-markdown": "~1.3"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You may also use the [PHP League CommonMark engine](http://commonmark.thephpleague.com/):
|
||||
|
||||
```bash
|
||||
composer require league/commonmark ~0.5
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"league/commonmark": "~0.5"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Twig Extension
|
||||
|
||||
The Twig extension provides the `markdown` tag and filter support.
|
||||
|
||||
Assuming that you are using [composer](http://getcomposer.org) autoloading,
|
||||
add the extension to the Twig environment:
|
||||
|
||||
```php
|
||||
|
||||
use Aptoma\Twig\Extension\MarkdownExtension;
|
||||
use Aptoma\Twig\Extension\MarkdownEngine;
|
||||
|
||||
$engine = new MarkdownEngine\MichelfMarkdownEngine();
|
||||
|
||||
$twig->addExtension(new MarkdownExtension($engine));
|
||||
```
|
||||
|
||||
### Twig Token Parser
|
||||
|
||||
The Twig token parser provides the `markdown` tag only!
|
||||
|
||||
```php
|
||||
use Aptoma\Twig\Extension\MarkdownEngine;
|
||||
use Aptoma\Twig\TokenParser\MarkdownTokenParser;
|
||||
|
||||
$engine = new MarkdownEngine\MichelfMarkdownEngine();
|
||||
|
||||
$twig->addTokenParser(new MarkdownTokenParser($engine));
|
||||
```
|
||||
|
||||
### GitHub Markdown Engine
|
||||
|
||||
`MarkdownEngine\GitHubMarkdownEngine` provides an interface to GitHub's markdown engine using their public API via [`KnpLabs\php-github-api`][2]. To reduce API calls, rendered documents are hashed and cached in the filesystem. You can pass a GitHub repository and the path to be used for caching to the constructor:
|
||||
|
||||
```php
|
||||
use Aptoma\Twig\Extension\MarkdownEngine;
|
||||
|
||||
$engine = new MarkdownEngine\GitHubMarkdownEngine(
|
||||
'aptoma/twig-markdown', // The GitHub repository to use as a context
|
||||
true, // Whether to use GitHub's Flavored Markdown (GFM)
|
||||
'/tmp/markdown-cache', // Path on filesystem to store rendered documents
|
||||
);
|
||||
```
|
||||
|
||||
In order to authenticate the API client (for instance), it's possible to pass an own instance of `\GitHub\Client` instead of letting the engine create one itself:
|
||||
|
||||
```php
|
||||
$client = new \GitHub\Client;
|
||||
$client->authenticate('GITHUB_CLIENT_ID', 'GITHUB_CLIENT_SECRET', \Github\Client::AUTH_URL_CLIENT_ID);
|
||||
|
||||
$engine = new MarkdownEngine\GitHubMarkdownEngine('aptoma/twig-markdown', true, '/tmp/markdown-cache', $client);
|
||||
```
|
||||
|
||||
### Using a different Markdown parser engine
|
||||
|
||||
If you want to use a different Markdown parser, you need to create an adapter
|
||||
that implements `Aptoma\Twig\Extension\MarkdownEngineInterface.php`. Have
|
||||
a look at `Aptoma\Twig\Extension\MarkdownEngine\MichelfMarkdownEngine` for an
|
||||
example.
|
||||
|
||||
## Tests
|
||||
|
||||
The test suite uses PHPUnit:
|
||||
|
||||
$ phpunit
|
||||
|
||||
## License
|
||||
|
||||
Twig Markdown Extension is licensed under the MIT license.
|
||||
|
||||
[1]: http://twig.sensiolabs.org
|
||||
[2]: https://github.com/knplabs/php-github-api
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "aptoma/twig-markdown",
|
||||
"description": "Twig extension to work with Markdown content",
|
||||
"keywords": ["twig", "markdown"],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Gunnar Lium",
|
||||
"email": "gunnar@aptoma.com"
|
||||
},
|
||||
{
|
||||
"name": "Joris Berthelot",
|
||||
"email": "joris@berthelot.tel"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"twig/twig": "~1.12"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0",
|
||||
"satooshi/php-coveralls": "~0.6",
|
||||
"codeclimate/php-test-reporter": "dev-master",
|
||||
"michelf/php-markdown": "~1",
|
||||
"league/commonmark": "~0.5",
|
||||
"knplabs/github-api": "~1.2",
|
||||
"erusev/parsedown": "^1.6"
|
||||
},
|
||||
"suggest": {
|
||||
"michelf/php-markdown": "Original Markdown engine with MarkdownExtra.",
|
||||
"knplabs/github-api": "Needed for using GitHub's Markdown engine provided through their API."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Aptoma": "src/" }
|
||||
}
|
||||
}
|
||||
+1772
File diff suppressed because it is too large.
Load diff
+18
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="vendor/autoload.php"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Aptoma Markdown Test Suite">
|
||||
<directory>./tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
Vendored
+76
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
||||
|
||||
use Aptoma\Twig\Extension\MarkdownEngineInterface;
|
||||
|
||||
/**
|
||||
* GithubMarkdownEngine.php
|
||||
*
|
||||
* Maps GitHub's Markdown engine API to Aptoma\Twig Markdown Extension using
|
||||
* KnpLabs\php-github-api.
|
||||
*
|
||||
* @author Lukas W <lukaswhl@gmail.com>
|
||||
*/
|
||||
class GitHubMarkdownEngine implements MarkdownEngineInterface
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $contextRepo The repository context. Pass a GitHub repo
|
||||
* such as 'aptoma/twig-markdown' to render e.g. issues #23 in the
|
||||
* context of the repo.
|
||||
* @param bool $gfm Whether to use GitHub's Flavored Markdown or the
|
||||
* standard markdown. Default is true.
|
||||
* @param string $cacheDir Location on disk where rendered documents should
|
||||
* be stored.
|
||||
* @param \Github\Client $client Client object to use. A new Github\Client()
|
||||
* object is constructed automatically if $client is null.
|
||||
*/
|
||||
public function __construct($contextRepo = null, $gfm = true, $cacheDir = '/tmp/github-markdown-cache', \GitHub\Client $client=null)
|
||||
{
|
||||
$this->repo = $contextRepo;
|
||||
$this->mode = $gfm ? 'gfm' : 'markdown';
|
||||
$this->cacheDir = rtrim($cacheDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
if (!is_dir($this->cacheDir)) {
|
||||
@mkdir($this->cacheDir, 0777, true);
|
||||
}
|
||||
|
||||
if ($client === null) {
|
||||
$client = new \Github\Client();
|
||||
}
|
||||
$this->api = $client->api('markdown');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($content)
|
||||
{
|
||||
$cacheFile = $this->getCachePath($content);
|
||||
if (file_exists($cacheFile)) {
|
||||
return file_get_contents($cacheFile);;
|
||||
}
|
||||
|
||||
$response = $this->api->render($content, $this->mode, $this->repo);
|
||||
file_put_contents($cacheFile, $response);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'KnpLabs\php-github-api';
|
||||
}
|
||||
|
||||
private function getCachePath($content)
|
||||
{
|
||||
return $this->cacheDir . md5($content) . '_' . $this->mode. '_' . str_replace('/', '.', $this->repo);
|
||||
}
|
||||
|
||||
private $api;
|
||||
private $cacheDir;
|
||||
private $repo;
|
||||
private $mode;
|
||||
}
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
||||
|
||||
use Aptoma\Twig\Extension\MarkdownEngineInterface;
|
||||
use Michelf\MarkdownExtra;
|
||||
|
||||
/**
|
||||
* MichelfMarkdownEngine.php
|
||||
*
|
||||
* Maps Michelf\MarkdownExtra to Aptoma\Twig Markdown Extension
|
||||
*
|
||||
* @author Joris Berthelot <joris@berthelot.tel>
|
||||
*/
|
||||
class MichelfMarkdownEngine implements MarkdownEngineInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($content)
|
||||
{
|
||||
return MarkdownExtra::defaultTransform($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'Michelf\Markdown';
|
||||
}
|
||||
}
|
||||
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
||||
|
||||
use Aptoma\Twig\Extension\MarkdownEngineInterface;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
|
||||
/**
|
||||
* PHPLeagueCommonMarkEngine.php
|
||||
*
|
||||
* Maps League\CommonMark\CommonMarkConverter to Aptoma\Twig Markdown Extension
|
||||
*
|
||||
* @author Casey McLaughlin <caseyamcl@gmail.com>
|
||||
*/
|
||||
class PHPLeagueCommonMarkEngine implements MarkdownEngineInterface
|
||||
{
|
||||
/**
|
||||
* @var \League\CommonMark\CommonMarkConverter
|
||||
*/
|
||||
private $converter;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Accepts CommonMarkConverter or creates one automatically
|
||||
*
|
||||
* @param \League\CommonMark\CommonMarkConverter $converter
|
||||
*/
|
||||
public function __construct(CommonMarkConverter $converter = null)
|
||||
{
|
||||
$this->converter = $converter ?: new CommonMarkConverter();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($content)
|
||||
{
|
||||
return $this->converter->convertToHtml($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'League\CommonMark';
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
||||
|
||||
use Aptoma\Twig\Extension\MarkdownEngineInterface;
|
||||
use Parsedown;
|
||||
|
||||
/**
|
||||
* ParsedownEngine.php
|
||||
*
|
||||
* Maps erusev/parsedown to Aptoma\Twig Markdown Extension
|
||||
*
|
||||
* @author Sébastien Lourseau <https://github.com/SebLours>
|
||||
*/
|
||||
class ParsedownEngine implements MarkdownEngineInterface
|
||||
{
|
||||
/**
|
||||
* @var Parsedown
|
||||
*/
|
||||
protected $engine;
|
||||
|
||||
/**
|
||||
* @param string|null $instanceName
|
||||
*/
|
||||
public function __construct($instanceName = null)
|
||||
{
|
||||
$this->engine = Parsedown::instance($instanceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($content)
|
||||
{
|
||||
return $this->engine->parse($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'erusev/parsedown';
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Aptoma\Twig\Extension;
|
||||
|
||||
/**
|
||||
* MarkdownEngineInterface.php
|
||||
*
|
||||
* Provide software interface to maps various Markdown engines
|
||||
*
|
||||
* @author Joris Berthelot <joris@berthelot.tel>
|
||||
*/
|
||||
interface MarkdownEngineInterface
|
||||
{
|
||||
/**
|
||||
* Transforms the given markdown data in HTML
|
||||
*
|
||||
* @param $content Markdown data
|
||||
* @return string
|
||||
*/
|
||||
public function transform($content);
|
||||
|
||||
/**
|
||||
* Return Markdown engine vendor ID
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Aptoma\Twig\Extension;
|
||||
|
||||
use Aptoma\Twig\TokenParser\MarkdownTokenParser;
|
||||
|
||||
/**
|
||||
* MarkdownExtension provides support for Markdown.
|
||||
*
|
||||
* @author Gunnar Lium <gunnar@aptoma.com>
|
||||
* @author Joris Berthelot <joris@berthelot.tel>
|
||||
*/
|
||||
class MarkdownExtension extends \Twig_Extension
|
||||
{
|
||||
|
||||
/**
|
||||
* @var MarkdownEngineInterface $markdownEngine
|
||||
*/
|
||||
private $markdownEngine;
|
||||
|
||||
/**
|
||||
* @param MarkdownEngineInterface $markdownEngine The Markdown parser engine
|
||||
*/
|
||||
public function __construct(MarkdownEngineInterface $markdownEngine)
|
||||
{
|
||||
$this->markdownEngine = $markdownEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return array(
|
||||
new \Twig_SimpleFilter(
|
||||
'markdown',
|
||||
array($this, 'parseMarkdown'),
|
||||
array('is_safe' => array('html'))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform Markdown content to HTML
|
||||
*
|
||||
* @param $content The Markdown content to be transformed
|
||||
* @return string The result of the Markdown engine transformation
|
||||
*/
|
||||
public function parseMarkdown($content)
|
||||
{
|
||||
return $this->markdownEngine->transform($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTokenParsers()
|
||||
{
|
||||
return array(new MarkdownTokenParser($this->markdownEngine));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'markdown';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Aptoma\Twig\Node;
|
||||
|
||||
/**
|
||||
* Represents a markdown node.
|
||||
*
|
||||
* It parses content as Markdown.
|
||||
*
|
||||
* @author Gunnar Lium <gunnar@aptoma.com>
|
||||
* @author Joris Berthelot <joris@berthelot.tel>
|
||||
*/
|
||||
class MarkdownNode extends \Twig_Node
|
||||
{
|
||||
public function __construct(\Twig_NodeInterface $body, $lineno, $tag = 'markdown')
|
||||
{
|
||||
parent::__construct(array('body' => $body), array(), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param \Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(\Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write('ob_start();' . PHP_EOL)
|
||||
->subcompile($this->getNode('body'))
|
||||
->write('$content = ob_get_clean();' . PHP_EOL)
|
||||
->write('preg_match("/^\s*/", $content, $matches);' . PHP_EOL)
|
||||
->write('$lines = explode("\n", $content);' . PHP_EOL)
|
||||
->write('$content = preg_replace(\'/^\' . $matches[0]. \'/\', "", $lines);' . PHP_EOL)
|
||||
->write('$content = join("\n", $content);' . PHP_EOL)
|
||||
->write('echo $this->env->getTokenParsers()->getTokenParser(\'markdown\')->getEngine()->transform($content);' . PHP_EOL);
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Aptoma\Twig\TokenParser;
|
||||
|
||||
use Aptoma\Twig\Node\MarkdownNode;
|
||||
use Aptoma\Twig\Extension\MarkdownEngineInterface;
|
||||
|
||||
/**
|
||||
* @author Gunnar Lium <gunnar@aptoma.com>
|
||||
* @author Joris Berthelot <joris@berthelot.tel>
|
||||
*/
|
||||
class MarkdownTokenParser extends \Twig_TokenParser
|
||||
{
|
||||
/**
|
||||
* @var The Markdown engine
|
||||
*/
|
||||
protected $markdownEngine;
|
||||
|
||||
/**
|
||||
* @param MarkdownEngineInterface $markdownEngine The Markdown parser engine
|
||||
*/
|
||||
public function __construct(MarkdownEngineInterface $markdownEngine)
|
||||
{
|
||||
$this->markdownEngine = $markdownEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Markdown parser engine getter
|
||||
*
|
||||
* @return MarkdownEngineInterface
|
||||
*/
|
||||
public function getEngine()
|
||||
{
|
||||
return $this->markdownEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a token and returns a node.
|
||||
*
|
||||
* @param \Twig_Token $token A \Twig_Token instance
|
||||
*
|
||||
* @throws \Twig_Error_Syntax
|
||||
* @return \Twig_NodeInterface A \Twig_NodeInterface instance
|
||||
*/
|
||||
public function parse(\Twig_Token $token)
|
||||
{
|
||||
$lineno = $token->getLine();
|
||||
|
||||
$this->parser->getStream()->expect(\Twig_Token::BLOCK_END_TYPE);
|
||||
$body = $this->parser->subparse(array($this, 'decideMarkdownEnd'), true);
|
||||
$this->parser->getStream()->expect(\Twig_Token::BLOCK_END_TYPE);
|
||||
|
||||
return new MarkdownNode($body, $lineno, $this->getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide if current token marks end of Markdown block.
|
||||
*
|
||||
* @param \Twig_Token $token
|
||||
* @return bool
|
||||
*/
|
||||
public function decideMarkdownEnd(\Twig_Token $token)
|
||||
{
|
||||
return $token->test('endmarkdown');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tag name associated with this token parser.
|
||||
*
|
||||
* @return string The tag name
|
||||
*/
|
||||
public function getTag()
|
||||
{
|
||||
return 'markdown';
|
||||
}
|
||||
}
|
||||
Vendored
+31
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
||||
|
||||
use Aptoma\Twig\Extension\MarkdownExtensionTest;
|
||||
|
||||
require_once(__DIR__ . '/../MarkdownExtensionTest.php');
|
||||
|
||||
/**
|
||||
* Class GitHubMarkdownEngineTest
|
||||
*
|
||||
* @author Lukas W <lukaswhl@gmail.com>
|
||||
*/
|
||||
class GitHubMarkdownEngineTest extends MarkdownExtensionTest
|
||||
{
|
||||
public function getParseMarkdownTests()
|
||||
{
|
||||
return array(
|
||||
array('{{ "# Main Title"|markdown }}', '<h1>Main Title</h1>'),
|
||||
array('{{ content|markdown }}', '<h1>Main Title</h1>', array('content' => '# Main Title')),
|
||||
// Check if GFM is working
|
||||
array('{{ "@aptoma"|markdown }}',
|
||||
'<p><a href="https://github.com/aptoma" class="user-mention">@aptoma</a></p>'),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getEngine()
|
||||
{
|
||||
return new GitHubMarkdownEngine();
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
||||
|
||||
use Aptoma\Twig\Extension\MarkdownExtensionTest;
|
||||
|
||||
// Require parent class if not autoloaded
|
||||
if (!class_exists('\Aptoma\Twig\Extension\MarkdownExtensionTest')) {
|
||||
require_once(__DIR__ . '/../MarkdownExtensionTest.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Class PHPLeagueCommonMarkEngineTest
|
||||
*
|
||||
* @author Casey McLaughlin <caseyamcl@gmail.com>
|
||||
*/
|
||||
class PHPLeagueCommonMarkEngineTest extends MarkdownExtensionTest
|
||||
{
|
||||
protected function getEngine()
|
||||
{
|
||||
return new PHPLeagueCommonMarkEngine();
|
||||
}
|
||||
}
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
||||
|
||||
use Aptoma\Twig\Extension\MarkdownExtensionTest;
|
||||
|
||||
// Require parent class if not autoloaded
|
||||
if (!class_exists('\Aptoma\Twig\Extension\MarkdownExtensionTest')) {
|
||||
require_once(__DIR__ . '/../MarkdownExtensionTest.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParsedownEngineTest
|
||||
*
|
||||
* @author Sébastien Lourseau <https://github.com/SebLours>
|
||||
*/
|
||||
class ParsedownEngineTest extends MarkdownExtensionTest
|
||||
{
|
||||
public function getParseMarkdownTests()
|
||||
{
|
||||
return array(
|
||||
array('{{ "# Main Title"|markdown }}', '<h1>Main Title</h1>'),
|
||||
array('{{ content|markdown }}', '<h1>Main Title</h1>', array('content' => '# Main Title')),
|
||||
array('{% markdown %}{{ content }}{% endmarkdown %}', '<h1>Main Title</h1>', array('content' => '# Main Title'))
|
||||
);
|
||||
}
|
||||
|
||||
protected function getEngine()
|
||||
{
|
||||
return new ParsedownEngine();
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Aptoma\Twig\Extension;
|
||||
|
||||
use Aptoma\Twig\Extension\MarkdownEngine\MichelfMarkdownEngine;
|
||||
|
||||
/**
|
||||
* @author Gunnar Liun <gunnar@aptoma.com>
|
||||
*/
|
||||
class MarkdownExtensionTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getParseMarkdownTests
|
||||
*/
|
||||
public function testParseMarkdown($template, $expected, $context = array())
|
||||
{
|
||||
$this->assertEquals($expected, $this->getTemplate($template)->render($context));
|
||||
}
|
||||
|
||||
public function getParseMarkdownTests()
|
||||
{
|
||||
return array(
|
||||
array('{{ "# Main Title"|markdown }}', '<h1>Main Title</h1>' . PHP_EOL),
|
||||
array('{{ content|markdown }}', '<h1>Main Title</h1>' . PHP_EOL, array('content' => '# Main Title'))
|
||||
);
|
||||
}
|
||||
|
||||
protected function getEngine()
|
||||
{
|
||||
return new MichelfMarkdownEngine();
|
||||
}
|
||||
|
||||
protected function getTemplate($template)
|
||||
{
|
||||
$loader = new \Twig_Loader_Array(array('index' => $template));
|
||||
$twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
|
||||
$twig->addExtension(new MarkdownExtension($this->getEngine()));
|
||||
|
||||
return $twig->loadTemplate('index');
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Aptoma\Twig\TokenParser;
|
||||
|
||||
use Aptoma\Twig\Extension\MarkdownEngine\MichelfMarkdownEngine;
|
||||
use Aptoma\Twig\Node\MarkdownNode;
|
||||
|
||||
/**
|
||||
* @author Gunnar Lium <gunnar@aptoma.com>
|
||||
*/
|
||||
class MarkdownTokenParserTest extends \Twig_Test_NodeTestCase
|
||||
{
|
||||
public function testConstructor()
|
||||
{
|
||||
$body = new \Twig_Node(array(new \Twig_Node_Text("#Title\n\nparagraph\n", 1)));
|
||||
$node = new MarkdownNode($body, 1);
|
||||
|
||||
$this->assertEquals($body, $node->getNode('body'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the generated code actually do what we expect
|
||||
*
|
||||
* The contents of this test is the same that we write in the compile method.
|
||||
* This requires manual synchronization, which we should probably not rely on.
|
||||
*/
|
||||
public function testMarkdownPrepareBehavior()
|
||||
{
|
||||
$body = " #Title\n\n paragraph\n\n code";
|
||||
$bodyPrepared = "#Title\n\nparagraph\n\n code";
|
||||
|
||||
ob_start();
|
||||
echo $body;
|
||||
$content = ob_get_clean();
|
||||
preg_match("/^\s*/", $content, $matches);
|
||||
$lines = explode("\n", $content);
|
||||
$content = preg_replace('/^' . $matches[0]. '/', "", $lines);
|
||||
$content = join("\n", $content);
|
||||
|
||||
// Assert prepared content looks right
|
||||
$this->assertEquals($bodyPrepared, $content);
|
||||
|
||||
// Assert Markdown output
|
||||
$expectedOutput = "<h1>Title</h1>\n\n<p>paragraph</p>\n\n<pre><code>code\n</code></pre>\n";
|
||||
$this->assertEquals($expectedOutput, $this->getEngine()->transform($content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the generated code looks as expected
|
||||
*
|
||||
* @dataProvider getTests
|
||||
*/
|
||||
public function testCompile($node, $source, $environment = null)
|
||||
{
|
||||
parent::testCompile($node, $source, $environment);
|
||||
}
|
||||
|
||||
protected function getEngine()
|
||||
{
|
||||
return new MichelfMarkdownEngine();
|
||||
}
|
||||
|
||||
public function getTests()
|
||||
{
|
||||
$tests = array();
|
||||
|
||||
$body = new \Twig_Node(array(new \Twig_Node_Text("#Title\n\nparagraph\n", 1)));
|
||||
$node = new MarkdownNode($body, 1);
|
||||
|
||||
$tests['simple text'] = array($node, <<<EOF
|
||||
// line 1
|
||||
ob_start();
|
||||
echo "#Title
|
||||
|
||||
paragraph
|
||||
";
|
||||
\$content = ob_get_clean();
|
||||
preg_match("/^\s*/", \$content, \$matches);
|
||||
\$lines = explode("\\n", \$content);
|
||||
\$content = preg_replace('/^' . \$matches[0]. '/', "", \$lines);
|
||||
\$content = join("\\n", \$content);
|
||||
echo \$this->env->getTokenParsers()->getTokenParser('markdown')->getEngine()->transform(\$content);
|
||||
EOF
|
||||
);
|
||||
|
||||
$body = new \Twig_Node(array(new \Twig_Node_Text(" #Title\n\n paragraph\n\n code\n", 1)));
|
||||
$node = new MarkdownNode($body, 1);
|
||||
|
||||
$tests['text with leading indent'] = array($node, <<<EOF
|
||||
// line 1
|
||||
ob_start();
|
||||
echo " #Title
|
||||
|
||||
paragraph
|
||||
|
||||
code
|
||||
";
|
||||
\$content = ob_get_clean();
|
||||
preg_match("/^\s*/", \$content, \$matches);
|
||||
\$lines = explode("\\n", \$content);
|
||||
\$content = preg_replace('/^' . \$matches[0]. '/', "", \$lines);
|
||||
\$content = join("\\n", \$content);
|
||||
echo \$this->env->getTokenParsers()->getTokenParser('markdown')->getEngine()->transform(\$content);
|
||||
EOF
|
||||
);
|
||||
|
||||
return $tests;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
phpunit.xml
|
||||
composer.lock
|
||||
composer.phar
|
||||
/vendor/
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
language: php
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- php: 5.6
|
||||
dist: xenial
|
||||
env: 'COMPOSER_FLAGS="--prefer-stable --prefer-lowest" TWIG_VERSION="^1.0"'
|
||||
- php: 5.6
|
||||
dist: xenial
|
||||
env: TWIG_VERSION="^1.0"
|
||||
- php: 7.0
|
||||
dist: xenial
|
||||
env: TWIG_VERSION="^1.0"
|
||||
- php: 7.1
|
||||
dist: bionic
|
||||
env: TWIG_VERSION="^1.0"
|
||||
- php: 7.2
|
||||
dist: bionic
|
||||
env: TWIG_VERSION="^1.0"
|
||||
- php: 7.3
|
||||
dist: bionic
|
||||
env: TWIG_VERSION="^1.0"
|
||||
- php: 7.4
|
||||
dist: bionic
|
||||
env: TWIG_VERSION="^1.0"
|
||||
- php: 7.0
|
||||
dist: xenial
|
||||
env: TWIG_VERSION="^2.0"
|
||||
- php: 7.1
|
||||
dist: bionic
|
||||
env: TWIG_VERSION="^2.0"
|
||||
- php: 7.2
|
||||
dist: bionic
|
||||
env: TWIG_VERSION="^2.0"
|
||||
- php: 7.3
|
||||
dist: bionic
|
||||
env: TWIG_VERSION="^2.0"
|
||||
- php: 7.4
|
||||
dist: bionic
|
||||
env: TWIG_VERSION="^2.0"
|
||||
|
||||
install: composer require twig/twig:${TWIG_VERSION}
|
||||
|
||||
script: composer test
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2013 Alexander <iam.asm89@gmail.com>
|
||||
|
||||
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.
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
Twig cache extension
|
||||
====================
|
||||
|
||||
The missing cache extension for Twig. The extension allows for caching rendered parts of
|
||||
templates using several cache strategies.
|
||||
|
||||
[](http://travis-ci.org/asm89/twig-cache-extension)
|
||||
|
||||
## Installation
|
||||
|
||||
The extension is installable via composer:
|
||||
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"asm89/twig-cache-extension": "~1.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
### Setup
|
||||
|
||||
A minimal setup for adding the extension with the `LifeTimeCacheStrategy` and
|
||||
doctrine array cache is as following:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Doctrine\Common\Cache\ArrayCache;
|
||||
use Asm89\Twig\CacheExtension\CacheProvider\DoctrineCacheAdapter;
|
||||
use Asm89\Twig\CacheExtension\CacheStrategy\LifetimeCacheStrategy;
|
||||
use Asm89\Twig\CacheExtension\Extension as CacheExtension;
|
||||
|
||||
$cacheProvider = new DoctrineCacheAdapter(new ArrayCache());
|
||||
$cacheStrategy = new LifetimeCacheStrategy($cacheProvider);
|
||||
$cacheExtension = new CacheExtension($cacheStrategy);
|
||||
|
||||
$twig->addExtension($cacheExtension);
|
||||
```
|
||||
|
||||
### Want to use a PSR-6 cache pool?
|
||||
|
||||
Instead of using the default `DoctrineCacheAdapter` the extension also has
|
||||
a `PSR-6` compatible adapter. You need to instantiate one of the cache pool
|
||||
implementations as can be found on: http://php-cache.readthedocs.io/en/latest/
|
||||
|
||||
Example: Making use of the `ApcuCachePool` via the `PsrCacheAdapter`:
|
||||
|
||||
```bash
|
||||
composer require cache/apcu-adapter
|
||||
```
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Asm89\Twig\CacheExtension\CacheProvider\PsrCacheAdapter;
|
||||
use Asm89\Twig\CacheExtension\CacheStrategy\LifetimeCacheStrategy;
|
||||
use Asm89\Twig\CacheExtension\Extension as CacheExtension;
|
||||
use Cache\Adapter\Apcu\ApcuCachePool;
|
||||
|
||||
$cacheProvider = new PsrCacheAdapter(new ApcuCachePool());
|
||||
$cacheStrategy = new LifetimeCacheStrategy($cacheProvider);
|
||||
$cacheExtension = new CacheExtension($cacheStrategy);
|
||||
|
||||
$twig->addExtension($cacheExtension);
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
To cache a part of a template in Twig surround the code with a `cache` block.
|
||||
The cache block takes two parameters, first an "annotation" part, second the
|
||||
"value" the cache strategy can work with. Example:
|
||||
|
||||
```jinja
|
||||
{% cache 'v1/summary' 900 %}
|
||||
{# heavy lifting template stuff here, include/render other partials etc #}
|
||||
{% endcache %}
|
||||
```
|
||||
|
||||
Cache blocks can be nested:
|
||||
|
||||
```jinja
|
||||
{% cache 'v1' 900 %}
|
||||
{% for item in items %}
|
||||
{% cache 'v1' item %}
|
||||
{# ... #}
|
||||
{% endcache %}
|
||||
{% endfor %}
|
||||
{% endcache %}
|
||||
```
|
||||
|
||||
The annotation can also be an expression:
|
||||
|
||||
```jinja
|
||||
{% set version = 42 %}
|
||||
{% cache 'hello_v' ~ version 900 %}
|
||||
Hello {{ name }}!
|
||||
{% endcache %}
|
||||
```
|
||||
|
||||
## Cache strategies
|
||||
|
||||
The extension ships with a few cache strategies out of the box. Setup and usage
|
||||
of all of them is described below.
|
||||
|
||||
### Lifetime
|
||||
|
||||
See the ["Quick start"](#quick-start) for usage information of the `LifetimeCacheStrategy`.
|
||||
|
||||
### Generational
|
||||
|
||||
Strategy for generational caching.
|
||||
|
||||
In theory the strategy only saves fragments to the cache with infinite
|
||||
lifetime. The key of the strategy lies in the fact that the keys for blocks
|
||||
will change as the value for which the key is generated changes.
|
||||
|
||||
For example: entities containing a last update time, would include a timestamp
|
||||
in the key. For an interesting blog post about this type of caching see:
|
||||
http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works
|
||||
|
||||
### Blackhole
|
||||
|
||||
Strategy for development mode.
|
||||
|
||||
In development mode it often not very useful to cache fragments. The blackhole
|
||||
strategy provides an easy way to not cache anything it all. It always generates
|
||||
a new key and does not fetch or save any fragments.
|
||||
|
||||
#### Setup
|
||||
|
||||
In order to use the strategy you need to setup a `KeyGenerator` class that is
|
||||
able to generate a cache key for a given value.
|
||||
|
||||
The following naive example always assumes the value is an object with the methods
|
||||
`getId()` and `getUpdatedAt()` method. The key then composed from the class
|
||||
name, the id and the updated time of the object:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Asm89\Twig\CacheExtension\CacheStrategy\KeyGeneratorInterface;
|
||||
|
||||
class MyKeyGenerator implements KeyGeneratorInterface
|
||||
{
|
||||
public function generateKey($value)
|
||||
{
|
||||
return get_class($value) . '_' . $value->getId() . '_' . $value->getUpdatedAt();
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Next the `GenerationalCacheStrategy` needs to be setup with the keygenerator.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Asm89\Twig\CacheExtension\CacheStrategy\GenerationalCacheStrategy;
|
||||
use Asm89\Twig\CacheExtension\Extension as CacheExtension;
|
||||
|
||||
$keyGenerator = new MyKeyGenerator();
|
||||
$cacheProvider = /* see Quick start */;
|
||||
$cacheStrategy = new GenerationalCacheStrategy($cacheProvider, $keyGenerator, 0 /* = infinite lifetime */);
|
||||
$cacheExtension = new CacheExtension($cacheStrategy);
|
||||
|
||||
$twig->addExtension($cacheExtension);
|
||||
```
|
||||
|
||||
#### Usage
|
||||
|
||||
The strategy expects an object as value for determining the cache key of the
|
||||
block:
|
||||
|
||||
```jinja
|
||||
{% cache 'v1/summary' item %}
|
||||
{# heavy lifting template stuff here, include/render other partials etc #}
|
||||
{% endcache %}
|
||||
```
|
||||
|
||||
### Using multiple strategies
|
||||
|
||||
Different cache strategies are useful for different usecases. It is possible to
|
||||
mix multiple strategies in an application with the
|
||||
`IndexedChainingCacheStrategy`. The strategy takes an array of `'name' =>
|
||||
$strategy` and delegates the caching to the appropriate strategy.
|
||||
|
||||
#### Setup
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Asm89\Twig\CacheExtension\CacheStrategy\IndexedChainingCacheStrategy;
|
||||
use Asm89\Twig\CacheExtension\Extension as CacheExtension;
|
||||
|
||||
$cacheStrategy = new IndexedChainingCacheStrategy(array(
|
||||
'time' => $lifetimeCacheStrategy,
|
||||
'gen' => $generationalCacheStrategy,
|
||||
));
|
||||
$cacheExtension = new CacheExtension($cacheStrategy);
|
||||
|
||||
$twig->addExtension($cacheExtension);
|
||||
```
|
||||
|
||||
#### Usage
|
||||
|
||||
The strategy expects an array with as key the name of the strategy which it
|
||||
needs to delegate to and as value the appropriate value for the delegated
|
||||
strategy.
|
||||
|
||||
```jinja
|
||||
{# delegate to lifetime strategy #}
|
||||
{% cache 'v1/summary' {time: 300} %}
|
||||
{# heavy lifting template stuff here, include/render other partials etc #}
|
||||
{% endcache %}
|
||||
|
||||
{# delegate to generational strategy #}
|
||||
{% cache 'v1/summary' {gen: item} %}
|
||||
{# heavy lifting template stuff here, include/render other partials etc #}
|
||||
{% endcache %}
|
||||
```
|
||||
|
||||
## Implementing a cache strategy
|
||||
|
||||
Creating separate caches for different access levels, languages or other
|
||||
usecases can be done by implementing a custom cache strategy. In order to do so
|
||||
implement the `CacheProviderInterface`. It is recommended to use composition
|
||||
and wrap a custom strategy around an existing one.
|
||||
|
||||
## Authors
|
||||
|
||||
Alexander <iam.asm89@gmail.com>
|
||||
|
||||
## License
|
||||
|
||||
twig-cache-extension is licensed under the MIT License - see the LICENSE file for details
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "asm89/twig-cache-extension",
|
||||
"description": "Cache fragments of templates directly within Twig.",
|
||||
"keywords": ["twig", "cache", "extension"],
|
||||
"homepage": "https://github.com/asm89/twig-cache-extension",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alexander",
|
||||
"email": "iam.asm89@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.2",
|
||||
"twig/twig": "^1.0|^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.0 || ^4.8.10",
|
||||
"doctrine/cache": "~1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "phpunit"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/cache-implementation": "To make use of PSR-6 cache implementation via PsrCacheAdapter."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"": "lib/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"": "test/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of twig-cache-extension.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Twig\CacheExtension\CacheProvider;
|
||||
|
||||
use Asm89\Twig\CacheExtension\CacheProviderInterface;
|
||||
use Doctrine\Common\Cache\Cache;
|
||||
|
||||
/**
|
||||
* Adapter class to use the cache classes provider by Doctrine.
|
||||
*
|
||||
* @author Alexander <iam.asm89@gmail.com>
|
||||
*/
|
||||
class DoctrineCacheAdapter implements CacheProviderInterface
|
||||
{
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* @param Cache $cache
|
||||
*/
|
||||
public function __construct(Cache $cache)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function fetch($key)
|
||||
{
|
||||
return $this->cache->fetch($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function save($key, $value, $lifetime = 0)
|
||||
{
|
||||
return $this->cache->save($key, $value, $lifetime);
|
||||
}
|
||||
}
|
||||
Vendored
+68
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of twig-cache-extension.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Twig\CacheExtension\CacheProvider;
|
||||
|
||||
use Asm89\Twig\CacheExtension\CacheProviderInterface;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
|
||||
/**
|
||||
* Adapter class to make extension interoperable with every PSR-6 adapter.
|
||||
*
|
||||
* @see http://php-cache.readthedocs.io/
|
||||
*
|
||||
* @author Rvanlaak <rvanlaak@gmail.com>
|
||||
*/
|
||||
class PsrCacheAdapter implements CacheProviderInterface
|
||||
{
|
||||
/**
|
||||
* @var CacheItemPoolInterface
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* @param CacheItemPoolInterface $cache
|
||||
*/
|
||||
public function __construct(CacheItemPoolInterface $cache)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return mixed|false
|
||||
*/
|
||||
public function fetch($key)
|
||||
{
|
||||
// PSR-6 implementation returns null, CacheProviderInterface expects false
|
||||
$item = $this->cache->getItem($key);
|
||||
if ($item->isHit()) {
|
||||
return $item->get();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @param int|\DateInterval $lifetime
|
||||
* @return bool
|
||||
*/
|
||||
public function save($key, $value, $lifetime = 0)
|
||||
{
|
||||
$item = $this->cache->getItem($key);
|
||||
$item->set($value);
|
||||
$item->expiresAfter($lifetime);
|
||||
|
||||
return $this->cache->save($item);
|
||||
}
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of twig-cache-extension.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Twig\CacheExtension;
|
||||
|
||||
/**
|
||||
* Cache provider interface.
|
||||
*
|
||||
* @author Alexander <iam.asm89@gmail.com>
|
||||
*/
|
||||
interface CacheProviderInterface
|
||||
{
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return mixed False, if there was no value to be fetched. Null or a string otherwise.
|
||||
*/
|
||||
public function fetch($key);
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @param integer $lifetime
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function save($key, $value, $lifetime = 0);
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of twig-cache-extension.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Twig\CacheExtension\CacheStrategy;
|
||||
|
||||
use Asm89\Twig\CacheExtension\CacheStrategyInterface;
|
||||
|
||||
/**
|
||||
* CacheStrategy which doesn't cache at all
|
||||
*
|
||||
* This strategy can be used in development mode, e.g. editing twig templates,
|
||||
* to prevent previously cached versions from being rendered.
|
||||
*
|
||||
* @see https://github.com/asm89/twig-cache-extension/pull/29
|
||||
*
|
||||
* @author Hagen Hübel <hhuebel@itinance.com>
|
||||
*
|
||||
* @package Asm89\Twig\CacheExtension\CacheStrategy
|
||||
*/
|
||||
class BlackholeCacheStrategy implements CacheStrategyInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function fetchBlock($key)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function generateKey($annotation, $value)
|
||||
{
|
||||
return microtime(true) . mt_rand();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function saveBlock($key, $block)
|
||||
{
|
||||
// fire and forget
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of twig-cache-extension.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Twig\CacheExtension\CacheStrategy;
|
||||
|
||||
use Asm89\Twig\CacheExtension\CacheProviderInterface;
|
||||
use Asm89\Twig\CacheExtension\CacheStrategyInterface;
|
||||
use Asm89\Twig\CacheExtension\Exception\InvalidCacheKeyException;
|
||||
|
||||
/**
|
||||
* Strategy for generational caching.
|
||||
*
|
||||
* In theory the strategy only saves fragments to the cache with infinite
|
||||
* lifetime. The key of the strategy lies in the fact that the keys for blocks
|
||||
* will change as the value for which the key is generated changes.
|
||||
*
|
||||
* For example: entities containing a last update time, would include a
|
||||
* timestamp in the key.
|
||||
*
|
||||
* @see http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works
|
||||
*
|
||||
* @author Alexander <iam.asm89@gmail.com>
|
||||
*/
|
||||
class GenerationalCacheStrategy implements CacheStrategyInterface
|
||||
{
|
||||
private $keyGenerator;
|
||||
private $cache;
|
||||
private $lifetime;
|
||||
|
||||
/**
|
||||
* @param CacheProviderInterface $cache
|
||||
* @param KeyGeneratorInterface $keyGenerator
|
||||
* @param integer $lifetime
|
||||
*/
|
||||
public function __construct(CacheProviderInterface $cache, KeyGeneratorInterface $keyGenerator, $lifetime = 0)
|
||||
{
|
||||
$this->keyGenerator = $keyGenerator;
|
||||
$this->cache = $cache;
|
||||
$this->lifetime = $lifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function fetchBlock($key)
|
||||
{
|
||||
return $this->cache->fetch($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function generateKey($annotation, $value)
|
||||
{
|
||||
$key = $this->keyGenerator->generateKey($value);
|
||||
|
||||
if (null === $key) {
|
||||
throw new InvalidCacheKeyException();
|
||||
}
|
||||
|
||||
return $annotation . '__GCS__' . $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function saveBlock($key, $block)
|
||||
{
|
||||
return $this->cache->save($key, $block, $this->lifetime);
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of twig-cache-extension.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Twig\CacheExtension\CacheStrategy;
|
||||
|
||||
use Asm89\Twig\CacheExtension\CacheStrategyInterface;
|
||||
use Asm89\Twig\CacheExtension\Exception\NonExistingStrategyException;
|
||||
use Asm89\Twig\CacheExtension\Exception\NonExistingStrategyKeyException;
|
||||
|
||||
/**
|
||||
* Combines several configured cache strategies.
|
||||
*
|
||||
* Useful for combining for example generational cache strategy with a lifetime
|
||||
* cache strategy, but also useful when combining several generational cache
|
||||
* strategies which differ on cache lifetime (infinite, 1hr, 5m).
|
||||
*
|
||||
* @author Alexander <iam.asm89@gmail.com>
|
||||
*/
|
||||
class IndexedChainingCacheStrategy implements CacheStrategyInterface
|
||||
{
|
||||
/**
|
||||
* @var CacheStrategyInterface[]
|
||||
*/
|
||||
private $strategies;
|
||||
|
||||
/**
|
||||
* @param array $strategies
|
||||
*/
|
||||
public function __construct(array $strategies)
|
||||
{
|
||||
$this->strategies = $strategies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function fetchBlock($key)
|
||||
{
|
||||
return $this->strategies[$key['strategyKey']]->fetchBlock($key['key']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function generateKey($annotation, $value)
|
||||
{
|
||||
if (!is_array($value) || null === $strategyKey = key($value)) {
|
||||
throw new NonExistingStrategyKeyException();
|
||||
}
|
||||
|
||||
if (!isset($this->strategies[$strategyKey])) {
|
||||
throw new NonExistingStrategyException($strategyKey);
|
||||
}
|
||||
|
||||
return array(
|
||||
'strategyKey' => $strategyKey,
|
||||
'key' => $this->strategies[$strategyKey]->generateKey($annotation, current($value)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function saveBlock($key, $block)
|
||||
{
|
||||
return $this->strategies[$key['strategyKey']]->saveBlock($key['key'], $block);
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of twig-cache-extension.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Twig\CacheExtension\CacheStrategy;
|
||||
|
||||
/**
|
||||
* Generates a key for a given value.
|
||||
*
|
||||
* @author Alexander <iam.asm89@gmail.com>
|
||||
*/
|
||||
interface KeyGeneratorInterface
|
||||
{
|
||||
/**
|
||||
* Generate a cache key for a given value.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateKey($value);
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of twig-cache-extension.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Twig\CacheExtension\CacheStrategy;
|
||||
|
||||
use Asm89\Twig\CacheExtension\CacheProviderInterface;
|
||||
use Asm89\Twig\CacheExtension\CacheStrategyInterface;
|
||||
use Asm89\Twig\CacheExtension\Exception\InvalidCacheLifetimeException;
|
||||
|
||||
/**
|
||||
* Strategy for caching with a pre-defined lifetime.
|
||||
*
|
||||
* The value passed to the strategy is the lifetime of the cache block in
|
||||
* seconds.
|
||||
*
|
||||
* @author Alexander <iam.asm89@gmail.com>
|
||||
*/
|
||||
class LifetimeCacheStrategy implements CacheStrategyInterface
|
||||
{
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* @param CacheProviderInterface $cache
|
||||
*/
|
||||
public function __construct(CacheProviderInterface $cache)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function fetchBlock($key)
|
||||
{
|
||||
return $this->cache->fetch($key['key']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function generateKey($annotation, $value)
|
||||
{
|
||||
if (!is_numeric($value)) {
|
||||
throw new InvalidCacheLifetimeException($value);
|
||||
}
|
||||
|
||||
return array(
|
||||
'lifetime' => $value,
|
||||
'key' => '__LCS__' . $annotation,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function saveBlock($key, $block)
|
||||
{
|
||||
return $this->cache->save($key['key'], $block, $key['lifetime']);
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of twig-cache-extension.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Twig\CacheExtension;
|
||||
|
||||
/**
|
||||
* Cache strategy interface.
|
||||
*
|
||||
* @author Alexander <iam.asm89@gmail.com>
|
||||
*/
|
||||
interface CacheStrategyInterface
|
||||
{
|
||||
/**
|
||||
* Fetch the block for a given key.
|
||||
*
|
||||
* @param mixed $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchBlock($key);
|
||||
|
||||
/**
|
||||
* Generate a key for the value.
|
||||
*
|
||||
* @param string $annotation
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function generateKey($annotation, $value);
|
||||
|
||||
/**
|
||||
* Save the contents of a rendered block.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param string $block
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function saveBlock($key, $block);
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of twig-cache-extension.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Twig\CacheExtension\Exception;
|
||||
|
||||
/**
|
||||
* @todo Replace \RuntimeException with \InvalidArgumentException at version 2.0
|
||||
*/
|
||||
class BaseException extends \RuntimeException
|
||||
{
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of twig-cache-extension.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Twig\CacheExtension\Exception;
|
||||
|
||||
class InvalidCacheKeyException extends BaseException
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct($message = 'Key generator did not return a key.', $code = 0, \Exception $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of twig-cache-extension.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Twig\CacheExtension\Exception;
|
||||
|
||||
class InvalidCacheLifetimeException extends BaseException
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct($lifetime, $code = 0, \Exception $previous = null)
|
||||
{
|
||||
parent::__construct(sprintf('Value "%s" is not a valid lifetime.', gettype($lifetime)), $code, $previous);
|
||||
}
|
||||
}
|
||||
Loaded 100 of 6561 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user