Initial commit: apps.supersam24.ru
This commit is contained in:
commit
e955e1da36
6566 files changed
+1271095
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
+155
@@ -0,0 +1,155 @@
|
||||
<?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' => 'supersam_apps',
|
||||
'password' => 'Ft8wV%e3Fre#ZaH-nJ',
|
||||
'database' => 'supersam_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',
|
||||
|
||||
'acquiring24Out' => '/supersam24.ru/acquiring-in',
|
||||
'acquiring24In' => '/supersam24.ru/acquiring-out',
|
||||
'acquiring24Refund' => '/supersam24.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,19 @@
|
||||
<?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->connect('/delivery', ['controller' => 'Delivery', 'action' => 'display']);
|
||||
$routes->connect('/delivery/:city', ['controller' => 'Delivery', 'action' => 'display'], ['city' => '\w+', 'pass' => ['city']]);
|
||||
|
||||
$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;
|
||||
+427
@@ -0,0 +1,427 @@
|
||||
DROP TABLE IF EXISTS `cut_borders`;
|
||||
CREATE TABLE `cut_borders` (
|
||||
`id` int(11) NOT NULL,
|
||||
`label` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`short_label` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
INSERT INTO `cut_borders` (`id`, `label`, `short_label`) VALUES
|
||||
(1, 'ORIGIN Рехау 087Т дуб сонома', 'Р 087Т'),
|
||||
(2, 'ORIGIN Рехау 14650 крем', 'Р 14650'),
|
||||
(3, 'ORIGIN Рехау 200V венге темный', 'Р 200V'),
|
||||
(4, 'ORIGIN Рехау 226W акация лэйклэнд', 'Р 226W'),
|
||||
(5, 'ORIGIN Рехау 4163 Орех', 'Р 4163'),
|
||||
(6, 'ORIGIN Рехау 4214 Вишня', 'Р 4214'),
|
||||
(7, 'ORIGIN Рехау 4526 бук', 'Р 4526'),
|
||||
(8, 'ORIGIN Рехау 463W ноче экко', 'Р 463W'),
|
||||
(9, 'ORIGIN Рехау 4919 береза', 'Р 4919'),
|
||||
(10, 'ORIGIN Рехау 553W вудлайн кремовый', 'Р 553W'),
|
||||
(11, 'ORIGIN Рехау 6240', 'Р 6240'),
|
||||
(12, 'ORIGIN Рехау 77002 капучино', 'Р 77002'),
|
||||
(13, 'ORIGIN Рехау 848 W капуччино т-36', 'Р 848W'),
|
||||
(14, 'ORIGIN Рехау 849W дуб дымчатый', 'Р 849W'),
|
||||
(15, 'ORIGIN Рехау 91470 Ш. Б./ORIGIN 77039', 'Р 91470-O 77039'),
|
||||
(16, 'ORIGIN Рехау 9991 Клен', 'Р 9991'),
|
||||
(17, 'ORIGINAL Рехау 710 W Маслина Севилья', 'Р 710W'),
|
||||
(18, 'TREND RAL9010 / ORIGIN Белый структура', 'T RAL9010'),
|
||||
(19, 'TREND/ORIGINAL Рехау 599V Орех', 'T-Р 599V'),
|
||||
(20, 'TREND Рехау 1147W Дуб серый', 'T-Р 1147W'),
|
||||
(21, 'TREND Рехау 1416W Твист светлый', 'T-Р1416W'),
|
||||
(22, 'TREND Рехау 15504 розовый', 'T-Р 15504'),
|
||||
(23, 'TREND Рехау 2127W Ясень Шимо темный', 'T-Р 2127W'),
|
||||
(24, 'TREND Рехау 2128W Ясень Шимо светлый 454', 'T-Р 2128W'),
|
||||
(25, 'TREND Рехау 2459W Орех темный Селект', 'T-Р 2459W'),
|
||||
(26, 'TREND Рехау 322W дуб феррара', 'T-Р 322W'),
|
||||
(27, 'TREND Рехау 589V орех аида натуральный', 'T-Р 589V'),
|
||||
(28, 'TREND Рехау 69164 желто-зеленый', 'T-Р 69164'),
|
||||
(29, 'TREND Рехау 69165 Голубой', 'T-Р 69165'),
|
||||
(30, 'TREND Рехау 76399 Ваниль', 'T-Р 76399'),
|
||||
(31, 'TREND Рехау 76401 Черный/ORIGIN 601', 'T-Р 76401/O-601'),
|
||||
(32, 'TREND Рехау 76962 желтый', 'T-Р 76962'),
|
||||
(33, 'TREND Рехау 76973 черный графит', 'T-Р 76973'),
|
||||
(34, 'TREND Рехау 76989 светло-серый', 'T-Р 76989'),
|
||||
(35, 'TREND Рехау 76996 оранжевый', 'T-Р 76996'),
|
||||
(36, 'TREND Рехау 77039 белый гладкий', 'T-Р 77039'),
|
||||
(37, 'TREND Рехау 78243 Ирис', 'T-Р 78243'),
|
||||
(38, 'TREND Рехау 812V Дуб Шато серый', 'T-Р 812V'),
|
||||
(39, 'TREND/ORIGINAL Рехау 6071 дуб выбеленный', 'T/O-Р 6071'),
|
||||
(40, 'TREND/ORIGINAL Рехау 1309W сосна лоредо', 'T/O-Р 1309W'),
|
||||
(41, 'TREND/ORIGINAL Рехау 7064 дуб молочный', 'T/O-Р 7064');
|
||||
|
||||
DROP TABLE IF EXISTS `cut_border_available_dimensions`;
|
||||
CREATE TABLE `cut_border_available_dimensions` (
|
||||
`id` int(11) NOT NULL,
|
||||
`border_id` int(11) DEFAULT NULL,
|
||||
`border_dimension_id` int(11) NOT NULL,
|
||||
`price` decimal(10,2) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
INSERT INTO `cut_border_available_dimensions` (`id`, `border_id`, `border_dimension_id`, `price`) VALUES
|
||||
(1, 1, 1, '8.10'),
|
||||
(2, 1, 4, '41.80'),
|
||||
(3, 13, 3, '22.10'),
|
||||
(4, 14, 1, '8.10'),
|
||||
(5, 14, 3, '22.10'),
|
||||
(6, 14, 4, '31.70'),
|
||||
(7, 3, 1, '8.10'),
|
||||
(8, 3, 3, '22.10'),
|
||||
(9, 3, 4, '31.70'),
|
||||
(10, 7, 1, '8.10'),
|
||||
(11, 7, 3, '22.10'),
|
||||
(12, 7, 4, '31.70'),
|
||||
(13, 10, 1, '8.10'),
|
||||
(14, 10, 3, '22.10'),
|
||||
(15, 10, 4, '31.70'),
|
||||
(16, 41, 1, '8.10'),
|
||||
(17, 41, 3, '22.10'),
|
||||
(18, 41, 4, '31.70'),
|
||||
(22, 4, 1, '8.10'),
|
||||
(23, 4, 2, '28.09'),
|
||||
(24, 4, 4, '31.70'),
|
||||
(25, 9, 1, '8.10'),
|
||||
(26, 9, 2, '28.09'),
|
||||
(27, 9, 4, '31.70'),
|
||||
(28, 6, 1, '8.10'),
|
||||
(29, 6, 3, '28.09'),
|
||||
(30, 6, 4, '31.70'),
|
||||
(31, 16, 1, '8.10'),
|
||||
(32, 16, 3, '28.09'),
|
||||
(33, 16, 4, '31.70'),
|
||||
(34, 2, 1, '6.20'),
|
||||
(35, 2, 3, '20.50'),
|
||||
(36, 2, 4, '24.90'),
|
||||
(37, 12, 1, '6.20'),
|
||||
(38, 12, 3, '20.50'),
|
||||
(39, 12, 4, '24.90'),
|
||||
(40, 15, 1, '6.20'),
|
||||
(41, 15, 3, '20.50'),
|
||||
(42, 15, 4, '24.90'),
|
||||
(43, 30, 1, '7.30'),
|
||||
(44, 30, 3, '22.00'),
|
||||
(45, 30, 4, '30.00'),
|
||||
(46, 34, 1, '7.30'),
|
||||
(47, 34, 3, '22.00'),
|
||||
(48, 34, 4, '30.00'),
|
||||
(49, 35, 1, '7.30'),
|
||||
(50, 35, 3, '22.00'),
|
||||
(51, 35, 4, '30.00'),
|
||||
(52, 36, 1, '7.30'),
|
||||
(53, 36, 3, '22.00'),
|
||||
(54, 36, 4, '30.00'),
|
||||
(55, 26, 1, '10.30'),
|
||||
(56, 26, 3, '25.90'),
|
||||
(57, 26, 4, '41.80'),
|
||||
(58, 38, 1, '10.30'),
|
||||
(59, 38, 3, '25.90'),
|
||||
(60, 38, 4, '41.80'),
|
||||
(61, 40, 1, '10.30'),
|
||||
(62, 40, 3, '25.90'),
|
||||
(63, 40, 4, '31.70'),
|
||||
(64, 5, 1, '7.00'),
|
||||
(65, 5, 3, '22.10'),
|
||||
(66, 5, 4, '31.70'),
|
||||
(67, 27, 1, '10.30'),
|
||||
(68, 27, 4, '31.70'),
|
||||
(69, 23, 1, '10.30'),
|
||||
(70, 23, 4, '41.80'),
|
||||
(71, 24, 1, '10.30'),
|
||||
(72, 24, 4, '41.80'),
|
||||
(73, 20, 1, '10.30'),
|
||||
(74, 20, 4, '41.80'),
|
||||
(75, 21, 1, '10.30'),
|
||||
(76, 21, 4, '41.80'),
|
||||
(77, 25, 1, '10.30'),
|
||||
(78, 25, 4, '41.80'),
|
||||
(79, 39, 1, '10.30'),
|
||||
(80, 39, 4, '31.70'),
|
||||
(81, 33, 1, '7.30'),
|
||||
(82, 33, 4, '30.00'),
|
||||
(83, 22, 1, '7.30'),
|
||||
(84, 22, 4, '30.00'),
|
||||
(85, 28, 1, '7.30'),
|
||||
(86, 28, 4, '30.00'),
|
||||
(87, 29, 1, '7.30'),
|
||||
(88, 29, 4, '30.00'),
|
||||
(89, 32, 1, '7.30'),
|
||||
(90, 32, 4, '30.00'),
|
||||
(91, 37, 1, '7.30'),
|
||||
(92, 37, 4, '30.00'),
|
||||
(93, 19, 1, '8.10'),
|
||||
(94, 19, 4, '41.80'),
|
||||
(95, 31, 3, '22.00'),
|
||||
(96, 31, 4, '24.90'),
|
||||
(97, 11, 2, '20.00'),
|
||||
(98, 11, 4, '31.70'),
|
||||
(99, 17, 2, '28.09'),
|
||||
(100, 17, 4, '31.70'),
|
||||
(101, 8, 3, '28.09'),
|
||||
(102, 18, 3, '25.90'),
|
||||
(103, 18, 1, '8.10'),
|
||||
(104, 18, 4, '31.70');
|
||||
|
||||
DROP TABLE IF EXISTS `cut_border_dimensions`;
|
||||
CREATE TABLE `cut_border_dimensions` (
|
||||
`id` int(11) NOT NULL,
|
||||
`label` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
|
||||
`short_label` varchar(16) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
|
||||
`gluing_price` decimal(10,2) DEFAULT NULL,
|
||||
`2dp_id` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
INSERT INTO `cut_border_dimensions` (`id`, `label`, `short_label`, `gluing_price`, `2dp_id`) VALUES
|
||||
(1, '19*0,4 ПВХ', '19*0,4', '18.00', '8'),
|
||||
(2, '23*0,8 ПВХ', '23*0,8', '19.00', '12'),
|
||||
(3, '19*1 ПВХ', '19*1', '19.00', '1'),
|
||||
(4, '19*2 ПВХ', '19*2', '22.00', '2');
|
||||
|
||||
DROP TABLE IF EXISTS `cut_sheets`;
|
||||
CREATE TABLE `cut_sheets` (
|
||||
`id` int(11) NOT NULL,
|
||||
`label` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`sheet_dimension_id` int(11) NOT NULL,
|
||||
`default_border_id` int(11) DEFAULT NULL,
|
||||
`price` decimal(10,2) NOT NULL,
|
||||
`is_active` tinyint(1) NOT NULL DEFAULT '1'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
INSERT INTO `cut_sheets` (`id`, `label`, `sheet_dimension_id`, `default_border_id`, `price`, `is_active`) VALUES
|
||||
(1, 'Белая структура 605 SWA', 2, 18, '1990.00', 1),
|
||||
(2, 'Белая шагрень 605 PE', 2, 15, '1990.00', 1),
|
||||
(3, 'Белый 605 SG', 3, 36, '2255.00', 1),
|
||||
(4, 'Белый 605 SWN', 3, 18, '2255.00', 1),
|
||||
(5, 'Белый гладкий 605 SМ', 2, 15, '1990.00', 1),
|
||||
(6, 'Береза 261 SWN', 3, 13, '2310.00', 1),
|
||||
(7, 'Бодега 100 SWA', 2, 10, '1990.00', 1),
|
||||
(8, 'Бодега 101 SWA', 2, 40, '2040.00', 1),
|
||||
(9, 'Бук Бавария 124 SWA', 2, 7, '1990.00', 1),
|
||||
(10, 'Бук Бавария 124 SWN', 3, 7, '2200.00', 1),
|
||||
(11, 'Ваниль 630 РЕ', 3, 30, '2140.00', 1),
|
||||
(12, 'Венге 175 SWA', 2, 3, '1990.00', 1),
|
||||
(13, 'Венге 175 SWN', 3, 3, '2200.00', 1),
|
||||
(14, 'Графит 665 РЕ', 3, 33, '2410.00', 1),
|
||||
(15, 'Дуб Атланта 302 SWA', 2, 39, '2040.00', 1),
|
||||
(16, 'Дуб Бонифаций 348 SWN', 3, 4, '2310.00', 1),
|
||||
(17, 'Дуб Веллингтон 370 SWN', 3, 23, '2310.00', 1),
|
||||
(18, 'Дуб Кантри 1007 Тиснение WL', 1, 25, '1560.00', 0),
|
||||
(19, 'Дуб Килкини 7225 Тиснение WL', 1, 21, '1850.00', 0),
|
||||
(20, 'Дуб молочный 315 SWA', 2, 41, '1990.00', 1),
|
||||
(21, 'Дуб Сантана 322 SWN', 3, 26, '2260.00', 1),
|
||||
(22, 'Дуб Саттер 369 SWN', 3, 5, '2260.00', 1),
|
||||
(23, 'Дуб Сонома 325 SWA', 2, 1, '1990.00', 1),
|
||||
(24, 'Дуб Сонома 325 SWN', 3, 1, '2210.00', 1),
|
||||
(25, 'Дуб Сонома 351 SWN', 3, 38, '2210.00', 1),
|
||||
(26, 'Дуб Шамони св.331 SWA', 2, 24, '2040.00', 1),
|
||||
(27, 'Дуб Юккон 358 SWN', 3, 14, '2360.00', 1),
|
||||
(28, 'Желтый 650 РЕ', 3, 32, '2720.00', 1),
|
||||
(29, 'Зелёный 651 РЕ', 3, 28, '2720.00', 1),
|
||||
(30, 'Капучино 806 PE', 3, 12, '2280.00', 1),
|
||||
(31, 'Клен Танзау 482 SWA', 2, 16, '1990.00', 1),
|
||||
(32, 'Крем 625 PE', 2, 2, '2050.00', 1),
|
||||
(33, 'Лиственница Сибирская 525 SWN', 3, 10, '2310.00', 1),
|
||||
(34, 'Ноче Гуарнери 408 SWA', 2, 5, '1990.00', 1),
|
||||
(35, 'Ноче Экко 412 SWA', 2, 8, '1990.00', 1),
|
||||
(36, 'Ольха 250 SWA', 2, 6, '2040.00', 1),
|
||||
(37, 'Ольха Горная светлая 254 SWN', 3, 9, '2260.00', 1),
|
||||
(38, 'Оранжевый 655 PE', 3, 35, '2720.00', 1),
|
||||
(39, 'Орех Донской 202 SWA', 2, 19, '1990.00', 1),
|
||||
(40, 'Орех Лион 204 SWN', 3, 27, '2210.00', 1),
|
||||
(41, 'Пепел 621 PE', 2, 34, '1940.00', 1),
|
||||
(42, 'Платина 801 PE', 3, 11, '2280.00', 1),
|
||||
(43, 'Розовый 657 PE', 2, 22, '2165.00', 1),
|
||||
(44, 'Серебро 802 PE', 3, 11, '2280.00', 1),
|
||||
(45, 'Синий 652 PE', 3, 29, '2280.00', 1),
|
||||
(46, 'Сиреневый 658 РЕ', 3, 37, '2410.00', 1),
|
||||
(47, 'Сосна Каньон 529 SWN', 3, 10, '2360.00', 1),
|
||||
(48, 'Таксус 570 SWN', 3, 27, '2310.00', 1),
|
||||
(49, 'Черный 660 PE', 3, 31, '2280.00', 1),
|
||||
(50, 'Эбони индийский светлый 3132 Тиснение WL', 1, 17, '1550.00', 0),
|
||||
(51, 'Ясень Шимо 454 SWA светлый', 2, 24, '1990.00', 1),
|
||||
(52, 'Ясень Шимо 455 SWA темный', 2, 23, '1990.00', 1),
|
||||
(53, 'Ясень Рибейра 3130 Тиснение WL', 1, 20, '1600.00', 0);
|
||||
|
||||
DROP TABLE IF EXISTS `cut_sheet_dimensions`;
|
||||
CREATE TABLE `cut_sheet_dimensions` (
|
||||
`id` int(11) NOT NULL,
|
||||
`width` int(11) DEFAULT NULL,
|
||||
`height` int(11) NOT NULL,
|
||||
`thick` int(11) NOT NULL,
|
||||
`2dp_id` int(11) NOT NULL,
|
||||
`is_active` tinyint(1) NOT NULL DEFAULT '1'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
INSERT INTO `cut_sheet_dimensions` (`id`, `width`, `height`, `thick`, `2dp_id`, `is_active`) VALUES
|
||||
(1, 2440, 1830, 16, 1, 0),
|
||||
(2, 2750, 1830, 16, 1, 1),
|
||||
(3, 2800, 2070, 16, 1, 1);
|
||||
|
||||
ALTER TABLE `cut_borders` ADD PRIMARY KEY (`id`), ADD KEY `label` (`label`);
|
||||
ALTER TABLE `cut_border_available_dimensions` ADD PRIMARY KEY (`id`);
|
||||
ALTER TABLE `cut_border_dimensions` ADD PRIMARY KEY (`id`);
|
||||
ALTER TABLE `cut_sheets` ADD PRIMARY KEY (`id`), ADD KEY `label` (`label`);
|
||||
ALTER TABLE `cut_sheet_dimensions` ADD PRIMARY KEY (`id`);
|
||||
ALTER TABLE `cut_borders` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=42;
|
||||
ALTER TABLE `cut_border_available_dimensions` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=105;
|
||||
ALTER TABLE `cut_border_dimensions` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
|
||||
ALTER TABLE `cut_sheets` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=54;
|
||||
ALTER TABLE `cut_sheet_dimensions` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||
|
||||
DROP TABLE IF EXISTS `cut_orders`;
|
||||
CREATE TABLE `cut_orders` (
|
||||
`id` int(11) NOT NULL,
|
||||
`order_num` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`email` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`phone` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`comment` text COLLATE utf32_unicode_ci,
|
||||
`is_rotate_allowed` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`sheet_data` text CHARACTER SET utf8,
|
||||
`details` text CHARACTER SET utf8 NOT NULL,
|
||||
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf32 COLLATE=utf32_unicode_ci;
|
||||
|
||||
ALTER TABLE `cut_orders` ADD PRIMARY KEY (`id`);
|
||||
ALTER TABLE `cut_orders` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
ALTER TABLE `cut_orders` ADD `order_type` ENUM('order','print') NOT NULL DEFAULT 'order' AFTER `id`, ADD `branch_id` INT NULL DEFAULT NULL AFTER `order_type`;
|
||||
|
||||
CREATE USER 'supersam_cut'@'%' IDENTIFIED WITH mysql_native_password AS 'Ft8wV%e3Fre#ZaH-nJS';GRANT USAGE ON *.* TO 'supersam_cut'@'%' REQUIRE NONE WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;GRANT ALL PRIVILEGES ON `supersam_cut`.* TO 'supersam_cut'@'%';
|
||||
|
||||
ALTER USER 'supersam_cut'@'%' IDENTIFIED BY 'Ft8wV%e3Fre#ZaH-nJ';
|
||||
|
||||
ALTER TABLE `orders` ADD `print_url` VARCHAR(255) NULL DEFAULT NULL AFTER `taken_date`;
|
||||
|
||||
ALTER TABLE `sheets` ADD `image` VARCHAR(100) NULL DEFAULT NULL AFTER `is_active`, ADD `thumb` VARCHAR(100) NULL DEFAULT NULL AFTER `image`;
|
||||
update borders set image = concat(id, '.jpg');
|
||||
update sheets set image = concat(id, '.jpg');
|
||||
update sheets set thumb = concat(id, '.jpg');
|
||||
|
||||
ALTER TABLE `users` ADD `email` VARCHAR(128) NOT NULL AFTER `name`;
|
||||
ALTER TABLE `orders` ADD `html_letter` TEXT NULL AFTER `print_url`;
|
||||
ALTER TABLE `orders` ADD `text_letter` TEXT NULL AFTER `html_letter`;
|
||||
|
||||
ALTER TABLE `orders` ADD `statistics` TEXT NULL DEFAULT NULL AFTER `text_letter`;
|
||||
|
||||
INSERT INTO `settings` (`id`, `label`, `key`, `value`, `group`) VALUES (NULL, NULL, 'notifySaveOrderDataMessage', 'Заказ был успешно сохранен.', 'labels');
|
||||
|
||||
ALTER TABLE `orders` ADD `price` DECIMAL(10,2) NOT NULL DEFAULT '0' AFTER `details`;
|
||||
|
||||
INSERT INTO `settings` (`id`, `label`, `key`, `value`, `group`) VALUES (NULL, 'Сообщение об ошибке по умолчанию', 'defaultErrorMessage', 'Произошла ошибка. Пожалуйста, проверьте данные, убедитесь, что вы авторизованы и повторите действие.', 'labels');
|
||||
|
||||
ALTER TABLE `orders` ADD `merge_similar_details` TINYINT(1) NOT NULL DEFAULT '1' AFTER `is_rotate_allowed`;
|
||||
|
||||
ALTER TABLE `branches` ADD `is_deleted` TINYINT(1) NOT NULL DEFAULT '0' AFTER `order_notify_manager_sms`;
|
||||
|
||||
INSERT INTO `settings` (`id`, `label`, `key`, `value`, `group`) VALUES (NULL, 'Сообщение об ошибке загрузки данных при построении раскроя', 'dataLoadingError', 'Произошла ошибка при загрузке данных. Пожалуйста, повторите позже.', 'labels');
|
||||
INSERT INTO `settings` (`id`, `label`, `key`, `value`, `group`) VALUES (NULL, 'Сообщение об ошибке при отправке заказа менеджеру', 'orderSendManagerError', 'Произошла ошибка при отправке вашего заказа менеджеру. Пожалуйста, повторите позже.', 'labels');
|
||||
INSERT INTO `settings` (`id`, `label`, `key`, `value`, `group`) VALUES (NULL, 'Сообщение об ошибке при сохранении заказа менеджером', 'orderSaveManagerError', 'Произошла ошибка при сохранении вашего заказа. Пожалуйста, повторите позже.', 'labels');
|
||||
INSERT INTO `settings` (`id`, `label`, `key`, `value`, `group`) VALUES (NULL, 'Сообщение о необходимости дождаться окончания расчета раскроя при попытке отправить заказ', 'orderSendManagerCutIsActive', 'Пожалуйста, дождитесь окончания расчета перед печатью заказа или отправкой менеджеру.', 'labels');
|
||||
|
||||
ALTER TABLE `orders` ADD `order_cut_results` TEXT NULL DEFAULT NULL AFTER `updated_by_manager`;
|
||||
|
||||
ALTER TABLE `orders` DROP `is_rotate_allowed`;
|
||||
ALTER TABLE `orders` ADD INDEX( `order_type`, `created`, `manager_id`);
|
||||
ALTER TABLE `orders` ADD INDEX( `order_type`, `branch_id`, `created`, `manager_id`);
|
||||
|
||||
INSERT INTO `settings` (`id`, `label`, `key`, `value`, `group`) VALUES (NULL, 'НА РАСПИЛ УКАЗЫВАЮТСЯ ГОТОВЫЕ РАЗМЕРЫ ДЕТАЛЕЙ С УЧЕТОМ КРОМКИ', 'detailWithBordersWarning', 'НА РАСПИЛ УКАЗЫВАЮТСЯ ГОТОВЫЕ РАЗМЕРЫ ДЕТАЛЕЙ С УЧЕТОМ КРОМКИ', 'labels');
|
||||
|
||||
-------------------------
|
||||
delete from cut_settings where `group` = 'updates' or `group` = 'users';
|
||||
delete from settings where `group` != 'updates' and `group` != 'users';
|
||||
ALTER TABLE `cut_settings` CHANGE `group` `group` ENUM('prices','borders','common','labels','sheets','sheetDimensions','borderDimensions','branches','groovePrices','cornerPrices','grooveDefaults','cornerDefaults') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
|
||||
ALTER TABLE `settings` CHANGE `group` `group` ENUM('users','updates','cut_updates') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
|
||||
|
||||
ALTER TABLE `users` ADD `available_apps` VARCHAR(256) NOT NULL AFTER `is_active`;
|
||||
UPDATE `users` SET `available_apps` = '[\"cut\",\"calcDoors\"]' WHERE 1;
|
||||
|
||||
ALTER TABLE `settings` CHANGE `group` `group` ENUM('users','updates','cut_updates','common') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
|
||||
|
||||
ALTER TABLE `cut_orders` ADD `address` VARCHAR(256) NULL DEFAULT NULL AFTER `comment`;
|
||||
|
||||
ALTER TABLE `calc_doors_orders` ADD `ready_date` DATETIME NULL AFTER `order_calc_results`;
|
||||
ALTER TABLE `calc_doors_orders` ADD `actual_price` DECIMAL(15,2) NULL DEFAULT NULL AFTER `ready_date`;
|
||||
|
||||
ALTER TABLE `cut_orders` CHANGE `print_url` `view_order_url` VARCHAR(255) CHARACTER SET utf32 COLLATE utf32_unicode_ci NULL DEFAULT NULL;
|
||||
ALTER TABLE `calc_doors_orders` CHANGE `print_url` `view_order_url` VARCHAR(255) CHARACTER SET utf32 COLLATE utf32_unicode_ci NULL DEFAULT NULL;
|
||||
ALTER TABLE `users` ADD `last_active` DATETIME NULL DEFAULT NULL AFTER `available_apps`;
|
||||
ALTER TABLE `users` ADD `logging_attempts` INT NOT NULL DEFAULT '0' AFTER `last_active`;
|
||||
|
||||
ALTER TABLE `sms_subscribes` CHANGE `created_by` `createdBy` INT(11) NULL DEFAULT NULL;
|
||||
ALTER TABLE `sms_subscribes` CHANGE `queued_by` `queuedBy` INT(11) NULL DEFAULT NULL;
|
||||
ALTER TABLE `sms_subscribes` CHANGE `stopped_by` `stoppedBy` INT(11) NULL DEFAULT NULL;
|
||||
|
||||
ALTER TABLE `cut_orders` ADD INDEX( `order_type`, `name`, `created`);
|
||||
|
||||
-- 2019-09-18
|
||||
ALTER TABLE `calc_doors_orders` ADD `price` DECIMAL(15,2) NULL DEFAULT NULL AFTER `ready_date`;
|
||||
ALTER TABLE `cut_orders` ADD `price` DECIMAL(15,2) NULL DEFAULT NULL AFTER `order_cut_results`;
|
||||
ALTER TABLE `calc_doors_orders` ADD INDEX( `order_type`, `name`, `created`);
|
||||
|
||||
-- 2091-09-27
|
||||
ALTER TABLE `sms_subscribe_recipients` CHANGE `smsSubscribeId` `subscribeId` INT(11) NOT NULL;
|
||||
ALTER TABLE `sms_subscribes` CHANGE `sentSmsCount` `sentRecipientsCount` INT(11) NOT NULL DEFAULT '0';
|
||||
ALTER TABLE `sms_subscribes` CHANGE `sentRecipientsCount` `sentCount` INT(11) NOT NULL DEFAULT '0';
|
||||
ALTER TABLE `email_subscribe_attachments` ADD `mime` VARCHAR(64) NULL AFTER `filesize`;
|
||||
|
||||
|
||||
|
||||
-- 2010-01-21
|
||||
ALTER TABLE `users` CHANGE `role` `role` ENUM('admin','manager','head_of_transport','head_of_warehouse') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'manager';
|
||||
|
||||
-- 2010-01-30
|
||||
ALTER TABLE `cut_sheets` ADD `sheetIdFor1C` VARCHAR(36) NULL DEFAULT NULL AFTER `thumb`;
|
||||
ALTER TABLE `cut_sheets` ADD `quantityIn1C` INT NOT NULL DEFAULT '0' AFTER `sheetIdFor1C`
|
||||
|
||||
ALTER TABLE `cut_sheets` CHANGE `quantityIn1C` `quantityIn1C` INT(11) NULL DEFAULT NULL;
|
||||
UPDATE `cut_sheets` SET `quantityIn1C` = NULL WHERE 1;
|
||||
|
||||
ALTER TABLE `sms_orders_ready` CHANGE `sentDate` `sentDate` DATETIME NULL DEFAULT NULL;
|
||||
|
||||
|
||||
-- 2010-04-06
|
||||
ALTER TABLE `calc_doors` ADD `colorNapravlyaushayaVerh` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL AFTER `color`,
|
||||
ADD `colorNapravlyaushayaNiz` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL AFTER `colorNapravlyaushayaVerh`;
|
||||
update calc_doors set colorNapravlyaushayaVerh = color, colorNapravlyaushayaNiz = color where 1;
|
||||
|
||||
ALTER TABLE `calc_doors_settings` CHANGE `group` `group` ENUM('prices','common','labels','prices_aristo', 'limits_aristo') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
|
||||
INSERT INTO `calc_doors_settings` (`label`, `key`, `value`, `group`) VALUES
|
||||
('Минимальная высота проёма, мм', 'minDoorHeight', '740', 'limits_aristo'),
|
||||
('Максимальная высота проёма, мм', 'maxDoorHeight', '2700', 'limits_aristo'),
|
||||
('Минимальная ширина двери, мм', 'minDoorWidth', '450', 'limits_aristo'),
|
||||
('Максимальная ширина двери, мм', 'maxDoorWidth', '900', 'limits_aristo');
|
||||
|
||||
ALTER TABLE `settings` CHANGE `group` `group` ENUM('users','updates','cut_updates','global','common','global_labels','calcDoors_updates','ordersInfo_updates') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
|
||||
|
||||
|
||||
ALTER TABLE `settings` CHANGE `group` `group` ENUM('users','updates','cut_updates','global','common','global_labels','calcDoors_updates','ordersInfo_updates','order_payment') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
|
||||
|
||||
|
||||
INSERT INTO `settings` (`id`, `label`, `key`, `value`, `group`) VALUES (NULL, 'API ключ яндекс карт', 'yandexMapApiKey', '96000e94-bf7a-4e74-9180-068e83944d02', 'global');
|
||||
ALTER TABLE `delivery` ADD `shopShippingId` VARCHAR(32) NULL DEFAULT NULL AFTER `minimalCost`;
|
||||
UPDATE `delivery` SET `shopShippingId` = 'carrier_yalta' WHERE `delivery`.`id` = 7;
|
||||
UPDATE `delivery` SET `shopShippingId` = 'carrier_sev' WHERE `delivery`.`id` = 6;
|
||||
|
||||
ALTER TABLE `delivery` ADD `shopOrderMinTotal` DECIMAL(10,2) NULL DEFAULT NULL AFTER `shopShippingId`;
|
||||
UPDATE `delivery` SET `shopOrderMinTotal` = 500 WHERE `delivery`.`id` = 7;
|
||||
UPDATE `delivery` SET `shopOrderMinTotal` = 500 WHERE `delivery`.`id` = 6;
|
||||
|
||||
-- SELECT * FROM `oc_setting` WHERE `code` = 'carrier_sev' or `code` = 'carrier_yalta'
|
||||
|
||||
ALTER TABLE `sms_orders_ready` ADD `smsType` ENUM('order','other') NOT NULL AFTER `statusTime`;
|
||||
UPDATE `sms_orders_ready` SET `smsType` = 'order' WHERE 1;
|
||||
ALTER TABLE `sms_orders_ready` CHANGE `smsType` `smsType` ENUM('order','other','apps_order','supersam24_order') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
|
||||
|
||||
ALTER TABLE `order_payment` ADD `name` VARCHAR(256) NULL DEFAULT NULL AFTER `order_num`, ADD `summa_order_decimal` DECIMAL(10,2) NULL DEFAULT NULL AFTER `name`;
|
||||
|
||||
|
||||
ALTER TABLE `order_payment` ADD `summa_order_decimal_paid` DECIMAL(10,2) NOT NULL DEFAULT '0' AFTER `payment`;
|
||||
ALTER TABLE `order_payment` ADD `isDeleted` TINYINT(1) NOT NULL DEFAULT '0' AFTER `expiry_date`;
|
||||
ALTER TABLE `orders_info` ADD `created` DATETIME NULL DEFAULT NULL AFTER `isDeleted`;
|
||||
|
||||
|
||||
|
||||
ALTER TABLE `order_payment` ADD `telephone` VARCHAR(20) NULL DEFAULT NULL AFTER `name`;
|
||||
ALTER TABLE `order_payment` ADD `paid_date` DATETIME NULL DEFAULT NULL AFTER `expiry_date`;
|
||||
|
||||
|
||||
|
||||
ALTER TABLE `order_payment` ADD `domain` ENUM('apps.supersamsev.ru','supersam24.ru') NOT NULL DEFAULT 'apps.supersamsev.ru' AFTER `isDeleted`;
|
||||
@@ -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']
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
$config["encrypt"] = Configure::read("encrypt");
|
||||
|
||||
$tmpDelivery = $this->getDeliveryListForJS();
|
||||
$config['delivery'] = [];
|
||||
foreach ($tmpDelivery as $delivery) {
|
||||
$config['delivery'][$delivery['id']] = $delivery->toArray();
|
||||
}
|
||||
|
||||
$config["appsList"] = [
|
||||
"cut" => [
|
||||
"id" => "cut",
|
||||
"label" => "Раскрой ДСП",
|
||||
"label_long" => "Раскрой ДСП",
|
||||
"site_label" => "Online распил ДСП",
|
||||
"url" => "cut",
|
||||
],
|
||||
"fasad" => [
|
||||
"id" => "fasad",
|
||||
"label" => "Распил фасадов",
|
||||
"label_long" => "Распил фасадов",
|
||||
"site_label" => "Online распил фасадов",
|
||||
"url" => "fasad",
|
||||
],
|
||||
/*"calcDoors" => [
|
||||
"id" => "calcDoors",
|
||||
"label" => "Двери",
|
||||
"label_long" => "Расчет стоимости изготовления дверей",
|
||||
"url" => "calc-doors",
|
||||
],*/
|
||||
"ordersInfo" => [
|
||||
"id" => "ordersInfo",
|
||||
"label" => "Информация по счетам",
|
||||
"label_long" => "Информация по счетам",
|
||||
"url" => "orders-info",
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
public function getAppJsConfig($app = "", $isManager = false, $savedOrderData = null, $orderClientId = null) {
|
||||
//$conditions = [];
|
||||
$jsConfig = [
|
||||
"urls" => [],
|
||||
"primarySiteUrl" => "https://supersam24.ru/",
|
||||
"siteDomain" => (!empty(env('HTTP_CUSTOMHOST')) ? str_replace('apps.', '', env('HTTP_CUSTOMHOST')) : "supersam24.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,37 @@
|
||||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
class DeliveryController extends AppController {
|
||||
public function beforeFilter(Event $event)
|
||||
{
|
||||
parent::beforeFilter($event);
|
||||
// $this->Auth->allow(['display']);
|
||||
$this->viewBuilder()->setLayout('delivery');
|
||||
}
|
||||
|
||||
|
||||
public function display($city = null) {
|
||||
$isCityFound = false;
|
||||
if (!empty($city)) {
|
||||
$deliveryTable = TableRegistry::getTableLocator()->get('Delivery');
|
||||
|
||||
$delivery = $deliveryTable->find('all')->where(['slug' => $city, 'is_deleted' => false])->first();
|
||||
if (!empty($delivery)) {
|
||||
$delivery = $delivery->toArray();
|
||||
|
||||
$this->set('apiKey', $this->config['global']['yandexMapApiKey']['value']);
|
||||
$this->set('siteTitle', $delivery['label']);
|
||||
$this->set('delivery', $delivery);
|
||||
$isCityFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($isCityFound)) {
|
||||
$this->redirect('/404');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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,208 @@
|
||||
<div id="result"></div>
|
||||
<div id="map"></div>
|
||||
|
||||
<a tabindex="-1" href="/services" title="{{::config.primarySiteTitle}}" target="_blank" class="delivery-logo-row">
|
||||
<img class="apps-logo" src="/img/logo-<?=$jsConfig['siteDomain'];?>.png" alt="{{::config.primarySiteTitle}}">
|
||||
</a>
|
||||
|
||||
<script type="text/javascript">
|
||||
function resultsClose() {
|
||||
$('#result').removeClass('active');
|
||||
}
|
||||
|
||||
function init() {
|
||||
var myMap = new ymaps.Map('map', {
|
||||
center: [<?=$delivery['location'];?>],
|
||||
zoom: 17,
|
||||
type: 'yandex#map',
|
||||
controls: []
|
||||
}),
|
||||
|
||||
searchFinishPoint = new ymaps.control.SearchControl({
|
||||
options: {
|
||||
useMapBounds: true,
|
||||
noCentering: true,
|
||||
noPopup: true,
|
||||
noPlacemark: true,
|
||||
placeholderContent: 'Адрес доставки',
|
||||
size: 'large',
|
||||
float: 'none',
|
||||
position: { left: 10, top: 44 }
|
||||
}
|
||||
}),
|
||||
|
||||
|
||||
calculator = new DeliveryCalculator(myMap, myMap.getCenter()) ;
|
||||
|
||||
searchFinishPoint.events.add('load', function (event) { $('#result').removeClass('active'); });
|
||||
searchFinishPoint.events.add('clear', function (event) { $('#result').removeClass('active'); });
|
||||
searchFinishPoint.events.add('submit', function (event) { $('#result').removeClass('active'); });
|
||||
|
||||
|
||||
myMap.controls.add(searchFinishPoint);
|
||||
calculator.setStartPoint([<?=$delivery['location'];?>]);
|
||||
|
||||
searchFinishPoint.events.add('resultselect', function (e) {
|
||||
var results = searchFinishPoint.getResultsArray(),
|
||||
selected = e.get('index'),
|
||||
point = results[selected].geometry.getCoordinates();
|
||||
|
||||
calculator.setFinishPoint(point);
|
||||
})
|
||||
.add('load', function (event) {
|
||||
if (!event.get('skip') && searchFinishPoint.getResultsCount()) {
|
||||
searchFinishPoint.showResult(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function DeliveryCalculator(map, finish) {
|
||||
this._map = map;
|
||||
this._start = null;
|
||||
this._route = null;
|
||||
this._startBalloon;
|
||||
this._finishBalloon;
|
||||
|
||||
map.events.add('click', this._onClick, this);
|
||||
}
|
||||
|
||||
var ptp = DeliveryCalculator.prototype;
|
||||
|
||||
ptp._onClick= function (e) {
|
||||
if (this._start) {
|
||||
this.setFinishPoint(e.get('coords'));
|
||||
} else {
|
||||
this.setStartPoint(e.get('coords'));
|
||||
}
|
||||
};
|
||||
|
||||
ptp._onStartDragEnd = function (e) {
|
||||
var coords = this._start.geometry.getCoordinates();
|
||||
this.geocode("start", coords);
|
||||
};
|
||||
|
||||
ptp._onFinishDragEnd = function (e) {
|
||||
var coords = this._finish.geometry.getCoordinates();
|
||||
this.geocode("finish", coords);
|
||||
};
|
||||
|
||||
ptp.getDirection = function () {
|
||||
if(this._route) {
|
||||
this._map.geoObjects.remove(this._route);
|
||||
}
|
||||
|
||||
if (this._start && this._finish) {
|
||||
var self = this,
|
||||
start = this._start.geometry.getCoordinates(),
|
||||
finish = this._finish.geometry.getCoordinates(),
|
||||
startBalloon = this._startBalloon,
|
||||
finishBalloon = this._finishBalloon;
|
||||
|
||||
ymaps.route([
|
||||
finish,
|
||||
start,
|
||||
], {multiRoute: true})
|
||||
.then(function (router) {
|
||||
//self._map.geoObjects.add(router);
|
||||
|
||||
var routes = router.getRoutes(), distanceWithTolls = 0, distanceWithoutTolls = 0, distance = 0,
|
||||
selectedRoute, selectedRouteWithTolls, selectedRouteWithoutTolls;
|
||||
for (var i = 0, l = routes.getLength(); i < l; i++) {
|
||||
var route = routes.get(i);
|
||||
|
||||
if (!route.properties.get('blocked')) {
|
||||
distance = Math.ceil(route.properties.get('distance').value / 1000)
|
||||
if (route.properties.get('hasTolls')) {
|
||||
if ((distanceWithTolls == 0) || (distance < distanceWithTolls)) {
|
||||
selectedRouteWithTolls = route;
|
||||
distanceWithTolls = distance;
|
||||
}
|
||||
} else {
|
||||
if ((distanceWithoutTolls == 0) || (distance < distanceWithoutTolls)) {
|
||||
selectedRouteWithoutTolls = route;
|
||||
distanceWithoutTolls = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (distanceWithoutTolls > 0) { //route without tolls exists
|
||||
selectedRoute = selectedRouteWithoutTolls;
|
||||
distance = distanceWithoutTolls;
|
||||
} else {
|
||||
selectedRoute = selectedRouteWithTolls;
|
||||
distance = distanceWithTolls;
|
||||
}
|
||||
|
||||
|
||||
router.setActiveRoute(selectedRoute);
|
||||
|
||||
var /*distance = Math.round(router.getLength() / 1000),*/
|
||||
distanceLabel = "",
|
||||
message = '<div class="resultInner"><span>Расстояние: ' + (distance < 1 ? 1 : distance) + 'км.</span><br/>' +
|
||||
'<span style="font-weight: bold; font-style: italic; ">Стоимость доставки: %sр.</span><span id="resultsClose" onClick="javascript:resultsClose();">×</span><div>'
|
||||
distanceLabel = self.calculate(distance);
|
||||
self._route = selectedRoute.getPaths();
|
||||
self._route.options.set({ strokeWidth: 5, strokeColor: '0000ffff', opacity: 0.5 });
|
||||
self._map.geoObjects.add(self._route);
|
||||
self._start.properties.set('balloonContentBody', startBalloon + message.replace('%s', distanceLabel));
|
||||
self._finish.properties.set('balloonContentBody', finishBalloon + message.replace('%s', distanceLabel));
|
||||
$('#result').html(finishBalloon + message.replace('%s', distanceLabel)).addClass('active');
|
||||
});
|
||||
|
||||
self._map.setBounds(self._map.geoObjects.getBounds())
|
||||
}
|
||||
};
|
||||
|
||||
ptp.setStartPoint = function (position) {
|
||||
if(this._start) {
|
||||
this._start.geometry.setCoordinates(position);
|
||||
}
|
||||
else {
|
||||
this._start = new ymaps.Placemark(position, { iconContent: 'А', }, { draggable: false });
|
||||
this._start.events.add('dragend', this._onStartDragEnd, this);
|
||||
this._map.geoObjects.add(this._start);
|
||||
}
|
||||
this.geocode("start", position);
|
||||
};
|
||||
|
||||
ptp.setFinishPoint = function (position) {
|
||||
if(this._finish) {
|
||||
this._finish.geometry.setCoordinates(position);
|
||||
}
|
||||
else {
|
||||
this._finish = new ymaps.Placemark(position, { iconContent: 'Б' }, { draggable: true });
|
||||
this._finish.events.add('dragend', this._onFinishDragEnd, this);
|
||||
this._map.geoObjects.add(this._finish);
|
||||
}
|
||||
if (this._start) {
|
||||
this.geocode("finish", position);
|
||||
}
|
||||
};
|
||||
|
||||
ptp.geocode = function (str, point) {
|
||||
ymaps.geocode(point).then(function(geocode) {
|
||||
if (str == "start") {
|
||||
this._startBalloon = "<h3><?=$delivery['address'];?></h3><p>" + geocode.geoObjects.get(0).properties.get('description') + "</p>";
|
||||
this._start.properties.set('balloonContentBody', this._startBalloon);
|
||||
} else {
|
||||
this._finishBalloon = geocode.geoObjects.get(0) &&
|
||||
geocode.geoObjects.get(0).properties.get('balloonContentBody') || '';
|
||||
}
|
||||
this.getDirection();
|
||||
}, this);
|
||||
|
||||
}
|
||||
ptp.calculate = function (len) {
|
||||
// Константы.
|
||||
var DELIVERY_TARIF = <?=$delivery['costPerKm'];?>,
|
||||
MINIMUM_COST = <?=$delivery['minimalCost'];?>;
|
||||
if (len == 1) return (MINIMUM_COST);
|
||||
return Math.max((len - 1) * DELIVERY_TARIF + MINIMUM_COST, MINIMUM_COST);
|
||||
};
|
||||
|
||||
ymaps.ready(init);
|
||||
|
||||
</script>
|
||||
|
||||
<?php $this->Assign('title', $siteTitle);?>
|
||||
@@ -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">
|
||||
supersamApp.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://supersamsev.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,34 @@
|
||||
<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,55 @@
|
||||
<?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><?= $this->fetch('title');?></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 = [
|
||||
"delivery.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;
|
||||
}
|
||||
$scripts[] = "https://api-maps.yandex.ru/2.1/?apikey=".$apiKey."&lang=ru_RU";
|
||||
|
||||
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,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,18 @@
|
||||
<div class="services">
|
||||
<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 src="/img/logo.png"></a><br/><br/>
|
||||
|
||||
<?= $this->element("services");?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<?php $this->Assign('title', $siteTitle);?>
|
||||
@@ -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);
|
||||
}
|
||||
Loaded 100 of 6566 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user