Spade
Mini Shell
| Directory:~$ /home/lmsyaran/public_html/joomla4/ |
| [Home] [System Details] [Kill Me] |
PK���[���Admin/Controller/Html/About.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html;
use Gantry\Admin\ThemeList;
use Gantry\Component\Admin\HtmlController;
class About extends HtmlController
{
public function index()
{
// TODO: Find better way:
$this->params['info'] = (new
ThemeList)->getTheme($this->container['theme.name']);
return
$this->render('@gantry-admin/pages/about/about.html.twig',
$this->params);
}
}
PK���[$�_EYYAdmin/Controller/Html/Cache.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html;
use Gantry\Component\Admin\HtmlController;
use Gantry\Component\Response\JsonResponse;
use Gantry\Component\Filesystem\Folder;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Cache extends HtmlController
{
public function index()
{
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
Folder::delete($locator('gantry-cache://theme'), false);
Folder::delete($locator('gantry-cache://admin'), false);
// Make sure that PHP has the latest data of the files.
clearstatcache();
return new JsonResponse(['html' => 'Cache was
successfully cleared', 'title' => 'Cache
Cleared']);
}
}
PK���[��x� 4Admin/Controller/Html/Configurations/Assignments.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html\Configurations;
use Gantry\Component\Admin\HtmlController;
use Gantry\Framework\Assignments as AssignmentsObject;
use RocketTheme\Toolbox\Event\Event;
class Assignments extends HtmlController
{
public function index()
{
$outline = $this->params['outline'];
if ($this->hasAssignments($outline)) {
$assignments = new AssignmentsObject($outline);
$this->params['assignments'] =
$assignments->get();
$this->params['options'] =
$assignments->assignmentOptions();
$this->params['assignment'] =
$assignments->getAssignment();
}
return
$this->render('@gantry-admin/pages/configurations/assignments/assignments.html.twig',
$this->params);
}
public function store()
{
// Authorization.
if (!$this->authorize('outline.assign')) {
$this->forbidden();
}
$outline = $this->params['outline'];
if (!$this->hasAssignments($outline)) {
$this->undefined();
}
if (!$this->request->post->get('_end')) {
throw new \OverflowException("Incomplete data received.
Please increase the value of 'max_input_vars' variable (in
php.ini or .htaccess)", 400);
}
// Save assignments.
$assignments = new AssignmentsObject($outline);
$assignments->save($this->request->post->getArray('assignments'));
// Fire save event.
$event = new Event;
$event->gantry = $this->container;
$event->theme = $this->container['theme'];
$event->controller = $this;
$event->assignments = $assignments;
$this->container->fireEvent('admin.assignments.save',
$event);
return '';
}
protected function hasAssignments($outline)
{
// Default outline and system outlines cannot have assignments.
return $outline !== 'default' && $outline[0] !==
'_';
}
}
PK���[�}mFmF/Admin/Controller/Html/Configurations/Layout.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html\Configurations;
use Gantry\Component\Admin\HtmlController;
use Gantry\Component\Config\BlueprintSchema;
use Gantry\Component\Config\BlueprintForm;
use Gantry\Component\Config\Config;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Component\Layout\Layout as LayoutObject;
use Gantry\Component\Response\JsonResponse;
use Gantry\Framework\Outlines;
use RocketTheme\Toolbox\Event\Event;
class Layout extends HtmlController
{
protected $httpVerbs = [
'GET' => [
'/' => 'index',
'/create' => 'create',
'/create/*' => 'create',
'/*' => 'undefined',
'/switch' => 'listSwitches',
'/switch/*' => 'switchLayout',
'/preset' => 'undefined',
'/preset/*' => 'preset'
],
'POST' => [
'/' => 'save',
'/*' => 'undefined',
'/*/*' => 'particle',
'/switch' => 'undefined',
'/switch/*' =>
'switchLayout',
'/preset' => 'undefined',
'/preset/*' => 'preset',
'/particles' => 'undefined',
'/particles/*' => 'undefined',
'/particles/*/validate' => 'validate'
],
'PUT' => [
'/*' => 'replace'
],
'PATCH' => [
'/*' => 'update'
],
'DELETE' => [
'/*' => 'destroy'
]
];
public function create($id = null)
{
if (!$id) {
// TODO: we might want to display list of options here
throw new \RuntimeException('Not Implemented', 404);
}
$layout = $this->getLayout("presets/{$id}");
if (!$layout) {
throw new \RuntimeException('Preset not found', 404);
}
$this->params['page_id'] = $id;
$this->params['layout'] =
$layout->prepareWidths()->toArray();
return
$this->render('@gantry-admin/pages/configurations/layouts/create.html.twig',
$this->params);
}
public function index()
{
$outline = $this->params['outline'];
$layout = $this->getLayout($outline);
if (!$layout) {
throw new \RuntimeException('Layout not found', 404);
}
$groups = [
'Positions' => ['position' => [],
'spacer' => [], 'system' => []],
'Particles' => ['particle' => []]
];
$particles = [
'position' => [],
'spacer' => [],
'system' => [],
'particle' => []
];
$particles = array_replace($particles, $this->getParticles());
foreach ($particles as &$group) {
asort($group);
}
unset($group);
foreach ($groups as $section => $children) {
foreach ($children as $key => $child) {
$groups[$section][$key] = $particles[$key];
}
}
$this->params['page_id'] = $outline;
$this->params['layout'] =
$layout->prepareWidths()->toArray();
$this->params['preset'] = $layout->preset;
$this->params['preset_title'] =
ucwords(trim(str_replace('_', ' ',
$layout->preset['name'])));
$this->params['id'] =
ucwords(str_replace('_', ' ', ltrim($outline,
'_')));
$this->params['particles'] = $groups;
$this->params['switcher_url'] =
str_replace('.', '/',
"configurations.{$outline}.layout.switch");
return
$this->render('@gantry-admin/pages/configurations/layouts/edit.html.twig',
$this->params);
}
public function save()
{
$layout = $this->request->post->get('layout');
$layout = json_decode($layout);
if (!isset($layout)) {
throw new \RuntimeException('Error while saving layout:
Structure missing', 400);
}
$outline = $this->params['outline'];
$preset =
$this->request->post->getJsonArray('preset');
// Create layout from the data.
$layout = new LayoutObject($outline, $layout, $preset);
$layout->init(false, false);
/** @var Outlines $outlines */
$outlines = $this->container['outlines'];
// Update layouts from all inheriting outlines.
$elements = $layout->sections() + $layout->particles(false);
foreach ($outlines->getInheritingOutlines($outline) as
$inheritedId => $inheritedName) {
LayoutObject::instance($inheritedId)->updateInheritance($outline,
$outline, $elements)->save()->saveIndex();
}
// Save layout and its index.
$layout->save()->saveIndex();
// Fire save event.
$event = new Event;
$event->gantry = $this->container;
$event->theme = $this->container['theme'];
$event->controller = $this;
$event->layout = $layout;
$this->container->fireEvent('admin.layout.save',
$event);
}
public function particle($type, $id)
{
if ($type === 'atom') { return ''; }
$outline = $this->params['outline'];
$layout = $this->getLayout($outline);
if (!$layout) {
throw new \RuntimeException('Layout not found', 404);
}
$item = $layout->find($id);
$item->type = $this->request->post['type'] ?:
$type;
$item->subtype = $this->request->post['subtype']
?: $type;
$item->title = $this->request->post['title']
?: ucfirst($type);
$parent = $this->request->post['parent'] ?:
$layout->getParentId($id);
if (!isset($item->attributes)) {
$item->attributes = new \stdClass;
}
if (!isset($item->inherit)) {
$item->inherit = new \stdClass;
}
$block =
$this->request->post->getArray('block');
if (!empty($block)) {
$item->block = (object) $block;
}
$attributes =
$this->request->post->getArray('options');
$inherit =
$this->request->post->getArray('inherit');
$particle = !$layout->isLayoutType($type);
if (!$particle) {
$name = $type;
$section = ($type === 'section');
$hasBlock = $section && !empty($block);
$prefix = "particles.{$type}";
$defaults = [];
$attributes += (array) $item->attributes;
$blueprints =
BlueprintForm::instance("layout/{$type}.yaml",
'gantry-admin://blueprints');
} else {
$name = $item->subtype;
$hasBlock = true;
$prefix = "particles.{$name}";
$defaults = (array)
$this->container['config']->get($prefix);
$blueprints =
$this->container['particles']->getBlueprintForm($name);
$blueprints->set('form/fields/_inherit',
['type' => 'gantry.inherit']);
}
if ($hasBlock) {
$blockBlueprints =
BlueprintForm::instance('layout/block.yaml',
'gantry-admin://blueprints');
} else {
$blockBlueprints = null;
}
$file =
"gantry-admin://blueprints/layout/inheritance/{$type}.yaml";
if (file_exists($file)) {
$inheritType = $particle ? 'particle' :
'section';
/** @var Outlines $outlines */
$outlines = $this->container['outlines'];
if ($outline !== 'default') {
if ($particle) {
$list =
$outlines->getOutlinesWithParticle($item->subtype, false);
} else {
$list =
$outlines->getOutlinesWithSection($item->id, false);
}
unset($list[$outline]);
} else {
$list = [];
}
if (!empty($inherit['outline']) || (!($inheriting =
$outlines->getInheritingOutlines($outline, [$id, $parent])) &&
$list)) {
$inheritable = true;
$inheritance = BlueprintForm::instance($file,
'gantry-admin://blueprints');
$inheritance->set('form/fields/outline/filter',
array_keys($list));
if (!$hasBlock) {
$inheritance->undef('form/fields/include/options/block');
}
if ($particle) {
$inheritance->set('form/fields/particle/particle', $name);
}
} elseif (!empty($inheriting)) {
// Already inherited by other outlines.
$inheritance =
BlueprintForm::instance('layout/inheritance/messages/inherited.yaml',
'gantry-admin://blueprints');
$inheritance->set(
'form/fields/_note/content',
sprintf($inheritance->get('form/fields/_note/content'),
$inheritType, ' <ul><li>' . implode('</li>
<li>', $inheriting) . '</li></ul>')
);
} elseif ($outline === 'default') {
// Base outline.
$inheritance =
BlueprintForm::instance('layout/inheritance/messages/default.yaml',
'gantry-admin://blueprints');
} else {
// Nothing to inherit from.
$inheritance =
BlueprintForm::instance('layout/inheritance/messages/empty.yaml',
'gantry-admin://blueprints');
}
}
$item->attributes = (object) $attributes;
$item->inherit = (object) $inherit;
$this->params['id'] = $name;
$this->params += [
'extra' => $blockBlueprints,
'inherit' =>
!empty($inherit['outline']) ? $inherit['outline'] :
null,
'inheritance' => isset($inheritance) ?
$inheritance : null,
'inheritable' => !empty($inheritable),
'item' => $item,
'data' => ['particles' =>
[$name => $item->attributes]],
'defaults' => ['particles' =>
[$name => $defaults]],
'prefix' => "particles.{$name}.",
'particle' => $blueprints,
'parent' => 'settings',
'route' =>
"configurations.{$outline}.settings",
'action' => str_replace('.',
'/', 'configurations.' . $outline .
'.layout.' . $prefix . '.validate'),
'skip' => ['enabled'],
'editable' => $particle,
'overrideable' => $particle,
];
if ($particle) {
$result =
$this->render('@gantry-admin/pages/configurations/layouts/particle.html.twig',
$this->params);
} else {
$typeLayout = $type === 'container' ?
'container' : 'section';
$result =
$this->render('@gantry-admin/pages/configurations/layouts/' .
$typeLayout . '.html.twig', $this->params);
}
return $result;
}
public function listSwitches()
{
$this->params['presets'] = LayoutObject::presets();
$result =
$this->render('@gantry-admin/layouts/switcher.html.twig',
$this->params);
return new JsonResponse(['html' => $result]);
}
public function switchLayout($id)
{
// Validate only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
$outline = $this->params['outline'];
$layout = $this->getLayout($id);
if (!$layout->toArray()) {
// Layout hasn't been defined, return default layout
instead.
$layout = $this->getLayout('default');
}
$input =
$this->request->post->getJson('layout');
$deleted = isset($input) ?
$layout->clearSections()->copySections($input): [];
if ($outline === 'default') {
$layout->inheritNothing();
} elseif (!$input &&
$this->request->post['inherit'] === '1') {
$layout->inheritAll();
}
$message = $deleted
?
$this->render('@gantry-admin/ajax/particles-loss.html.twig',
['particles' => $deleted])
: null;
return new JsonResponse([
'title' => ucwords(trim(str_replace('_',
' ', $layout->preset['name']))),
'preset' => json_encode($layout->preset),
'data' =>
$layout->prepareWidths()->toJson(),
'deleted' => $deleted,
'message' => $message
]);
}
public function preset($id)
{
// Validate only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
$preset = LayoutObject::preset($id);
if (!$preset) {
throw new \RuntimeException('Preset not found', 404);
}
$layout = new LayoutObject($id, $preset);
$input =
$this->request->post->getJson('layout');
$deleted = isset($input) ?
$layout->clearSections()->copySections($input): [];
$message = $deleted
?
$this->render('@gantry-admin/ajax/particles-loss.html.twig',
['particles' => $deleted])
: null;
return new JsonResponse([
'title' => ucwords(trim(str_replace('_',
' ', $id))),
'preset' => json_encode($layout->preset),
'data' =>
$layout->prepareWidths()->toJson(),
'deleted' => $deleted,
'message' => $message
]);
}
public function validate($particle)
{
// Validate only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
// Load particle blueprints and default settings.
$validator = new BlueprintSchema;
$name = $particle;
if (in_array($particle, ['wrapper', 'section',
'container', 'grid', 'offcanvas'], true)) {
$type = $particle;
$particle = null;
$file =
CompiledYamlFile::instance("gantry-admin://blueprints/layout/{$type}.yaml");
$validator->embed('options',
(array)$file->content());
$file->free();
} else {
$type = in_array($particle, ['spacer',
'system', 'position'], true) ? $particle :
'particle';
$validator->embed('options',
$this->container['particles']->get($particle));
}
// Create configuration from the defaults.
$data = new Config(
[
'type' => $type,
],
function () use ($validator) {
return $validator;
}
);
// Join POST data.
$data->join('options',
$this->request->post->getArray("particles." . $name));
if ($particle) {
$data->set('options.enabled', (int)
$data->get('options.enabled', 1));
}
if ($particle) {
if ($type !== $particle) {
$data->set('subtype', $particle);
}
$data->join('title',
$this->request->post['title'] ?: ucfirst($particle));
}
$block =
$this->request->post->getArray('block');
if ($block) {
// TODO: remove empty items in some other way:
foreach ($block as $key => $param) {
if ($param === '') {
unset($block[$key]);
continue;
}
if ($key === 'size') {
$param = round($param, 4);
if ($param < 5) {
$param = 5;
} elseif ($param > 100) {
$param = 100;
}
$block[$key] = $param;
}
}
$data->join('block', $block);
}
$inherit =
$this->request->post->getArray('inherit');
$clone = !empty($inherit['mode']) &&
$inherit['mode'] === 'clone';
$inherit['include'] =
!empty($inherit['include']) ? explode(',',
$inherit['include']) : [];
if (!$clone && !empty($inherit['outline'])
&& count($inherit['include'])) {
// Clean up inherit and add it to the data.
if (!$block) {
$inherit['include'] =
array_values(array_diff($inherit['include'],
['block']));
}
unset($inherit['mode']);
$data->join('inherit', $inherit);
}
// Optionally send children of the object.
if (in_array('children', $inherit['include'],
true)) {
$layout = LayoutObject::instance($inherit['outline']
?: $this->params['outline']);
if ($clone) {
$item = $layout->find($inherit['section']);
} else {
$item =
$layout->inheritAll()->find($inherit['section']);
}
$data->join('children', !empty($item->children)
? $item->children : []);
}
// TODO: validate
return new JsonResponse(['data' =>
$data->toArray()]);
}
/**
* @param string $name
* @return LayoutObject
*/
protected function getLayout($name)
{
return LayoutObject::instance($name);
}
protected function getParticles($onlyEnabled = false)
{
/** @var Config $config */
$config = $this->container['config'];
$particles = $this->container['particles']->all();
$list = [];
foreach ($particles as $name => $particle) {
$type = isset($particle['type']) ?
$particle['type'] : 'particle';
$particleName = isset($particle['name']) ?
$particle['name'] : $name;
$particleIcon = isset($particle['icon']) ?
$particle['icon'] : null;
if (!$onlyEnabled ||
$config->get("particles.{$name}.enabled", true)) {
$list[$type][$name] = ['name' =>
$particleName, 'icon' => $particleIcon];
}
}
return $list;
}
}
PK���['��L-L--Admin/Controller/Html/Configurations/Page.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html\Configurations;
use Gantry\Component\Admin\HtmlController;
use Gantry\Component\Config\BlueprintSchema;
use Gantry\Component\Config\Config;
use Gantry\Component\Layout\Layout;
use Gantry\Component\Response\JsonResponse;
use Gantry\Framework\Atoms;
use Gantry\Framework\Services\ConfigServiceProvider;
use RocketTheme\Toolbox\Event\Event;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Page extends HtmlController
{
protected $httpVerbs = [
'GET' => [
'/' => 'index'
],
'POST' => [
'/' => 'save',
'/*' => 'save',
'/*/**' => 'formfield',
'/atoms' => 'undefined',
'/atoms/*' => 'atom',
'/atoms/*/validate' => 'atomValidate'
],
'PUT' => [
'/' => 'save'
],
'PATCH' => [
'/' => 'save'
],
'DELETE' => [
'/' => 'forbidden'
]
];
public function index()
{
$outline = $this->params['outline'];
if ($outline == 'default') {
$this->params['overrideable'] = false;
$data = $this->container['config'];
} else {
$this->params['overrideable'] = true;
$this->params['defaults'] = $defaults =
$this->container['defaults'];
$data = ConfigServiceProvider::load($this->container,
$outline, false, false);
}
$deprecated = $this->getDeprecatedAtoms();
if ($deprecated) {
$data->set('page.head.atoms', $deprecated);
}
if (isset($defaults)) {
$currentAtoms = $data->get('page.head.atoms');
if (!$currentAtoms) {
// Make atoms to appear to be inherited in they are loaded
from defaults.
$defaultAtoms = (array)
$defaults->get('page.head.atoms');
$atoms = (new
Atoms($defaultAtoms))->inheritAll('default')->toArray();
$defaults->set('page.head.atoms', $atoms);
}
}
$this->params += [
'data' => $data,
'page' =>
$this->container['page']->group(),
'route' => "configurations.{$outline}",
'page_id' => $outline,
'atoms' => $this->getAtoms(),
'atoms_deprecated' => $deprecated
];
return
$this->render('@gantry-admin/pages/configurations/page/page.html.twig',
$this->params);
}
public function save($id = null)
{
$data = $id ? [$id => $this->request->post->getArray()]
: $this->request->post->getArray('page');
foreach ($data as $name => $values) {
$this->saveItem($name, $values);
}
// Fire save event.
$event = new Event;
$event->gantry = $this->container;
$event->theme = $this->container['theme'];
$event->controller = $this;
$event->data = $data;
$this->container->fireEvent('admin.page.save',
$event);
return $id ? $this->display($id) : $this->index();
}
public function formfield($id)
{
$path = func_get_args();
$end = end($path);
if ($end === '') {
array_pop($path);
}
if (end($path) == 'validate') {
return call_user_func_array([$this, 'validate'],
$path);
}
// Load blueprints.
$blueprints =
$this->container['page']->getBlueprintForm($id);
list($fields, $path, $value) =
$blueprints->resolve(array_slice($path, 1), '/');
if (!$fields) {
throw new \RuntimeException('Page Not Found', 404);
}
$data =
$this->request->post->getJsonArray('data');
$offset = "page.{$id}." . implode('.', $path);
if ($value !== null) {
$parent = $fields;
$fields = ['fields' =>
$fields['fields']];
$offset .= '.' . $value;
$data = $data ?:
$this->container['config']->get($offset);
$data = ['data' => $data];
$scope = 'data.';
} else {
$data = $data ?:
$this->container['config']->get($offset);
$scope = 'data';
}
$fields['is_current'] = true;
array_pop($path);
$outline = $this->params['outline'];
$configuration = "configurations/{$outline}";
$this->params = [
'configuration' => $configuration,
'blueprints' => $fields,
'data' => $data,
'prefix' => '',
'scope' => $scope,
'parent' => $path
? "$configuration/settings/particles/{$id}/"
. implode('/', $path)
: "$configuration/settings/particles/{$id}",
'route' =>
"configurations.{$outline}.{$offset}",
] + $this->params;
if (isset($parent['key'])) {
$this->params['key'] = $parent['key'];
}
if (isset($parent['value'])) {
$this->params['title'] =
$parent['value'];
}
return
$this->render('@gantry-admin/pages/configurations/settings/field.html.twig',
$this->params);
}
public function validate($particle)
{
$path = implode('.', array_slice(func_get_args(), 1,
-1));
// Validate only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
// Load particle blueprints.
$validator =
$this->container['particles']->get($particle);
// Create configuration from the defaults.
$data = new Config(
[],
function () use ($validator) {
return $validator;
}
);
$data->join($path,
$this->request->post->getArray('data'));
// TODO: validate
return new JsonResponse(['data' =>
$data->get($path)]);
}
public function atom($name)
{
$outline = $this->params['outline'];
$atoms = Atoms::instance($outline);
$data = $this->request->post['data'];
if ($data) {
$data = json_decode($data, true);
} else {
$data = $this->request->post->getArray();
}
// Create atom and get its blueprint.
$item = $atoms->createAtom($name, $data);
$blueprint = $item->blueprint();
// Load inheritance blueprint.
$inheritance = $atoms->getInheritanceBlueprint($name,
$item->id);
$inheritable = $inheritance &&
$inheritance->get('form/fields/outline/filter', []);
$this->params += [
'inherit' =>
!empty($inherit['outline']) ? $inherit['outline'] :
null,
'inheritance' => $inheritance,
'inheritable' => $inheritable,
'item' => $item,
'data' => ['particles' =>
[$name => $item->attributes]],
'blueprints' => $blueprint,
'parent' => 'settings',
'prefix' => "particles.{$name}.",
'route' =>
"configurations.default.settings",
'action' =>
"configurations/{$outline}/page/atoms/{$name}/validate",
'skip' => ['enabled']
];
return new JsonResponse(['html' =>
$this->render('@gantry-admin/modals/atom.html.twig',
$this->params)]);
}
/**
* Validate data for the atom.
*
* @param string $name
* @return JsonResponse
*/
public function atomValidate($name)
{
// Load particle blueprints and default settings.
$validator = new BlueprintSchema;
$validator->embed('options',
$this->container['particles']->get($name));
$blueprints =
$this->container['particles']->getBlueprintForm($name);
// Create configuration from the defaults.
$data = new Config([],
function () use ($validator) {
return $validator;
}
);
$data->set('id',
$this->request->post['id']);
$data->set('type', $name);
$data->set('title',
$this->request->post['title'] ?:
$blueprints->get('name'));
$data->set('attributes',
$this->request->post->getArray("particles.{$name}"));
$data->def('attributes.enabled', 1);
$block =
$this->request->post->getArray('block');
foreach ($block as $key => $param) {
if ($param === '') {
unset($block[$key]);
}
}
$inherit =
$this->request->post->getArray('inherit');
$clone = !empty($inherit['mode']) &&
$inherit['mode'] === 'clone';
$inherit['include'] =
!empty($inherit['include']) ? explode(',',
$inherit['include']) : [];
if (!$clone && !empty($inherit['outline'])
&& count($inherit['include'])) {
unset($inherit['mode']);
$data->join('inherit', $inherit);
}
// TODO: validate
// Fill parameters to be passed to the template file.
$this->params['item'] = (object) $data->toArray();
return new JsonResponse(['item' =>
$data->toArray()]);
}
protected function saveItem($id, $data)
{
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
// Save layout into custom directory for the current theme.
$outline = $this->params['outline'];
// Move atoms out of layout.
if ($id === 'head') {
$layout = Layout::instance($outline);
if (is_array($layout->atoms())) {
$layout->save(false);
}
if (isset($data['atoms'])) {
$atoms = new Atoms($data['atoms']);
$data['atoms'] =
$atoms->update()->toArray();
}
}
$save_dir =
$locator->findResource("gantry-config://{$outline}/page",
true, true);
$filename = "{$save_dir}/{$id}.yaml";
$file = YamlFile::instance($filename);
if (!is_array($data)) {
if ($file->exists()) {
$file->delete();
}
} else {
$blueprints =
$this->container['page']->getBlueprintForm($id);
$config = new Config($data, function () use ($blueprints) {
return $blueprints; });
$file->save($config->toArray());
}
$file->free();
}
protected function getDeprecatedAtoms()
{
$id = $this->params['outline'];
$layout = Layout::instance($id);
return $layout->atoms();
}
protected function getAtoms($onlyEnabled = false)
{
$config = $this->container['config'];
$atoms = $this->container['particles']->all();
$list = [];
foreach ($atoms as $name => $atom) {
$type = isset($atom['type']) ?
$atom['type'] : 'atom';
$atomName = isset($atom['name']) ?
$atom['name'] : $name;
if (!$onlyEnabled ||
$config->get("particles.{$name}.enabled", true)) {
$list[$type][$name] = $atomName;
}
}
return $list['atom'];
}
}
PK���[�Qޙ""1Admin/Controller/Html/Configurations/Settings.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html\Configurations;
use Gantry\Admin\Particles;
use Gantry\Component\Admin\HtmlController;
use Gantry\Component\Config\Config;
use Gantry\Component\Response\JsonResponse;
use Gantry\Framework\Services\ConfigServiceProvider;
use RocketTheme\Toolbox\Event\Event;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Settings extends HtmlController
{
protected $httpVerbs = [
'GET' => [
'/' => 'index',
'/particles' => 'undefined',
'/particles/*' => 'display',
'/particles/*/**' => 'formfield',
],
'POST' => [
'/' => 'save',
'/particles' => 'forbidden',
'/particles/*' => 'save',
'/particles/*/**' => 'formfield'
],
'PUT' => [
'/' => 'save',
'/particles' => 'forbidden',
'/particles/*' => 'save'
],
'PATCH' => [
'/' => 'save',
'/particles' => 'forbidden',
'/particles/*' => 'save'
],
'DELETE' => [
'/' => 'forbidden',
'/particles' => 'forbidden',
'/particles/*' => 'reset'
]
];
public function index()
{
$outline = $this->params['outline'];
if ($outline === 'default') {
$this->params['overrideable'] = false;
$data = $this->container['config'];
} else {
$this->params['overrideable'] = true;
$this->params['defaults'] =
$this->container['defaults'];
$data = ConfigServiceProvider::load($this->container,
$outline, false, false);
}
/** @var Particles $particles */
$particles = $this->container['particles'];
$this->params += [
'data' => $data,
'particles' =>
$particles->group(['atom']),
'route' =>
"configurations.{$outline}.settings",
'page_id' => $outline
];
return
$this->render('@gantry-admin/pages/configurations/settings/settings.html.twig',
$this->params);
}
public function display($id)
{
$outline = $this->params['outline'];
/** @var Particles $particles */
$particles = $this->container['particles'];
$blueprints = $particles->getBlueprintForm($id);
$prefix = 'particles.' . $id;
if($outline === 'default') {
$this->params['overrideable'] = false;
$data = $this->container['config'];
} else {
$this->params['overrideable'] = true;
$this->params['defaults'] =
$this->container['defaults']->get($prefix);
$data = ConfigServiceProvider::load($this->container,
$outline, false, false);
}
$this->params += [
'scope' => 'particle.',
'particle' => $blueprints,
'data' => ['particle' =>
$data->get($prefix)],
'id' => $id,
'parent' =>
"configurations/{$outline}/settings",
'route' =>
"configurations.{$outline}.settings.{$prefix}",
'skip' => ['enabled']
];
return
$this->render('@gantry-admin/pages/configurations/settings/item.html.twig',
$this->params);
}
public function formfield($id)
{
$path = func_get_args();
$end = end($path);
if ($end === '') {
array_pop($path);
}
if (end($path) === 'validate') {
return call_user_func_array([$this, 'validate'],
$path);
}
/** @var Particles $particles */
$particles = $this->container['particles'];
// Load blueprints.
$blueprints = $particles->getBlueprintForm($id);
list($fields, $path, $value) =
$blueprints->resolve(array_slice($path, 1), '/');
if (!$fields) {
throw new \RuntimeException('Page Not Found', 404);
}
$data =
$this->request->post->getJsonArray('data');
/** @var Config $config */
$config = $this->container['config'];
$offset = "particles.{$id}." . implode('.',
$path);
if ($value !== null) {
$parent = $fields;
$fields = ['fields' =>
$fields['fields']];
$offset .= '.' . $value;
$data = $data ?: $config->get($offset);
$data = ['data' => $data];
$scope = 'data.';
} else {
$data = $data ?: $config->get($offset);
$scope = 'data';
}
$fields['is_current'] = true;
array_pop($path);
$outline = $this->params['outline'];
$configuration = "configurations/{$outline}";
$this->params = [
'configuration' => $configuration,
'blueprints' => $fields,
'data' => $data,
'scope' => $scope,
'parent' => $path
?
"{$configuration}/settings/particles/{$id}/" .
implode('/', $path)
:
"{$configuration}/settings/particles/{$id}",
'route' =>
"configurations.{$outline}.settings.{$offset}",
] + $this->params;
if (isset($parent['key'])) {
$this->params['key'] = $parent['key'];
}
if (isset($parent['value'])) {
$this->params['title'] =
$parent['value'];
}
return
$this->render('@gantry-admin/pages/configurations/settings/field.html.twig',
$this->params);
}
public function validate($particle)
{
$path = implode('.', array_slice(func_get_args(), 1,
-1));
// Validate only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
/** @var Particles $particles */
$particles = $this->container['particles'];
// Load particle blueprints.
$validator = $particles->get($particle);
// Create configuration from the defaults.
$data = new Config(
[],
function () use ($validator) {
return $validator;
}
);
$data->join($path,
$this->request->post->getArray('data'));
// TODO: validate
return new JsonResponse(['data' =>
$data->get($path)]);
}
public function save($id = null)
{
if (!$this->request->post->get('_end')) {
throw new \OverflowException("Incomplete data received.
Please increase the value of 'max_input_vars' variable (in
php.ini or .htaccess)", 400);
}
$data = $id ? [$id =>
$this->request->post->getArray('particle')] :
$this->request->post->getArray('particles');
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
// Save layout into custom directory for the current theme.
$outline = $this->params['outline'];
$save_dir =
$locator->findResource("gantry-config://{$outline}/particles",
true, true);
foreach ($data as $name => $values) {
$this->saveItem($name, $values, $save_dir);
}
@rmdir($save_dir);
// Fire save event.
$event = new Event;
$event->gantry = $this->container;
$event->theme = $this->container['theme'];
$event->controller = $this;
$event->data = $data;
$this->container->fireEvent('admin.settings.save',
$event);
return $id ? $this->display($id) : $this->index();
}
protected function saveItem($id, $data, $save_dir)
{
$filename = "{$save_dir}/{$id}.yaml";
$file = YamlFile::instance($filename);
if (!is_array($data)) {
if ($file->exists()) {
$file->delete();
}
} else {
/** @var Particles $particles */
$particles = $this->container['particles'];
$blueprints = $particles->getBlueprintForm($id);
$config = new Config($data, function() use ($blueprints) {
return $blueprints; });
$file->save($config->toArray());
}
$file->free();
}
public function reset($id)
{
$this->params += [
'data' => [],
];
return $this->display($id);
}
}
PK���[�[T�
/Admin/Controller/Html/Configurations/Styles.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html\Configurations;
use Gantry\Component\Admin\HtmlController;
use Gantry\Component\Config\Config;
use Gantry\Component\Response\JsonResponse;
use Gantry\Framework\Services\ConfigServiceProvider;
use Gantry\Framework\Theme;
use RocketTheme\Toolbox\Event\Event;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Styles extends HtmlController
{
protected $httpVerbs = [
'GET' => [
'/' => 'index',
'/blocks' => 'undefined',
'/blocks/*' => 'display',
'/blocks/*/**' => 'formfield'
],
'POST' => [
'/' => 'save',
'/blocks' => 'forbidden',
'/blocks/*' => 'save',
'/compile' => 'compile'
],
'PUT' => [
'/' => 'save',
'/blocks' => 'forbidden',
'/blocks/*' => 'save'
],
'PATCH' => [
'/' => 'save',
'/blocks' => 'forbidden',
'/blocks/*' => 'save'
],
'DELETE' => [
'/' => 'forbidden',
'/blocks' => 'forbidden',
'/blocks/*' => 'reset'
]
];
public function index()
{
$outline = $this->params['outline'];
if($outline == 'default') {
$this->params['overrideable'] = false;
$this->params['data'] =
$this->container['config'];
} else {
$this->params['overrideable'] = true;
$this->params['defaults'] =
$this->container['defaults'];
$this->params['data'] =
ConfigServiceProvider::load($this->container, $outline, false, false);
}
$this->params['blocks'] =
$this->container['styles']->group();
$this->params['route'] =
"configurations.{$outline}.styles";
return
$this->render('@gantry-admin/pages/configurations/styles/styles.html.twig',
$this->params);
}
public function display($id)
{
$outline = $this->params['outline'];
$blueprints =
$this->container['styles']->getBlueprintForm($id);
$prefix = 'styles.' . $id;
if($outline == 'default') {
$this->params['overrideable'] = false;
$this->params['data'] =
$this->container['config']->get($prefix);
} else {
$this->params['overrideable'] = true;
$this->params['defaults'] =
$this->container['defaults']->get($prefix);
$this->params['data'] =
ConfigServiceProvider::load($this->container, $outline, false,
false)->get($prefix);
}
$this->params += [
'block' => $blueprints,
'id' => $id,
'parent' =>
"configurations/{$outline}/styles",
'route' =>
"configurations.{$outline}.styles.{$prefix}",
'skip' => ['enabled']
];
return
$this->render('@gantry-admin/pages/configurations/styles/item.html.twig',
$this->params);
}
public function formfield($id)
{
$path = func_get_args();
$outline = $this->params['outline'];
// Load blueprints.
$blueprints =
$this->container['styles']->getBlueprintForm($id);
list($fields, $path, $value) =
$blueprints->resolve(array_slice($path, 1), '/');
if (!$fields) {
throw new \RuntimeException('Page Not Found', 404);
}
$fields['is_current'] = true;
// Get the prefix.
$prefix = "styles.{$id}." . implode('.',
$path);
if ($value !== null) {
$parent = $fields;
$fields = ['fields' =>
$fields['fields']];
$prefix .= '.' . $value;
}
array_pop($path);
if($outline == 'default') {
$this->params['overrideable'] = false;
$this->params['data'] =
$this->container['config']->get($prefix);
} else {
$this->params['overrideable'] = true;
$this->params['defaults'] =
$this->container['defaults']->get($prefix);
$this->params['data'] =
ConfigServiceProvider::load($this->container, $outline, false,
false)->get($prefix);
}
$this->params = [
'blueprints' => $fields,
'parent' => $path
?
"configurations/{$outline}/styles/blocks/{$id}/" .
implode('/', $path)
:
"configurations/{$outline}/styles/blocks/{$id}",
'route' => 'styles.' . $prefix
] + $this->params;
if (isset($parent['key'])) {
$this->params['key'] = $parent['key'];
}
return
$this->render('@gantry-admin/pages/configurations/styles/field.html.twig',
$this->params);
}
public function reset($id)
{
$this->params += [
'data' => [],
];
return $this->display($id);
}
public function compile()
{
// Validate only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
$warnings = $this->compileSettings();
if ($warnings) {
$this->params += ['warnings' => $warnings];
return new JsonResponse(
[
'html' =>
$this->render('@gantry-admin/layouts/css-warnings.html.twig',
$this->params),
'warning' => true,
'title' => 'CSS Compiled With
Warnings',
]
);
} else {
return new JsonResponse(['html' => 'The CSS
was successfully compiled', 'title' => 'CSS
Compiled']);
}
}
public function save($id = null)
{
/** @var Config $config */
$config = $this->container['config'];
if ($id) {
$data = (array) $config->get('styles');
$data[$id] = $this->request->post->getArray();
} else {
$data =
$this->request->post->getArray('styles');
}
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
// Save layout into custom directory for the current theme.
$outline = $this->params['outline'];
$save_dir =
$locator->findResource("gantry-config://{$outline}", true,
true);
$filename = "{$save_dir}/styles.yaml";
$file = YamlFile::instance($filename);
$file->save($data);
$file->free();
// Fire save event.
$event = new Event;
$event->gantry = $this->container;
$event->theme = $this->container['theme'];
$event->controller = $this;
$event->data = $data;
$this->container->fireEvent('admin.styles.save',
$event);
// Compile CSS.
$warnings = $this->compileSettings();
if (empty($this->params['ajax'])) {
// FIXME: HTML request: Output compiler warnings!!
return $id ? $this->display($id) : $this->index();
}
if ($warnings) {
$this->params += ['warnings' => $warnings];
return new JsonResponse(
[
'html' =>
$this->render('@gantry-admin/layouts/css-warnings.html.twig',
$this->params),
'warning' => true,
'title' => 'CSS Compiled With
Warnings',
]
);
} else {
return new JsonResponse(['html' => 'The CSS
was successfully compiled', 'title' => 'CSS
Compiled']);
}
}
/**
* @returns array
*/
protected function compileSettings()
{
/** @var Theme $theme */
$theme = $this->container['theme'];
$outline = $this->params['outline'];
return $theme->updateCss($outline !== 'default' ?
[$outline => ucfirst($outline)] : null);
}
}
PK���[���7VV(Admin/Controller/Html/Configurations.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html;
use Gantry\Component\Admin\HtmlController;
use Gantry\Component\Response\HtmlResponse;
use Gantry\Component\Response\JsonResponse;
use Gantry\Component\Response\RedirectResponse;
use Gantry\Component\Response\Response;
use Gantry\Component\Layout\Layout as LayoutObject;
use Gantry\Framework\Outlines as OutlinesObject;
class Configurations extends HtmlController
{
protected $httpVerbs = [
'GET' => [
'/' => 'index',
'/*' => 'forward',
'/*/delete' =>
'confirmDeletion',
'/*/**' => 'forward',
],
'POST' => [
'/' => 'undefined',
'/*' => 'undefined',
'/create' => 'createForm',
'/create/new' => 'create',
'/*/rename' => 'rename',
'/*/duplicate' => 'duplicateForm',
'/*/duplicate/new' => 'duplicate',
'/*/delete' => 'undefined',
'/*/delete/confirm' => 'delete',
'/*/**' => 'forward',
],
'PUT' => [
'/' => 'undefined',
'/**' => 'forward'
],
'PATCH' => [
'/' => 'undefined',
'/**' => 'forward'
]
];
public function index()
{
return
$this->render('@gantry-admin/pages/configurations/configurations.html.twig',
$this->params);
}
public function createForm()
{
if (!$this->authorize('outline.create')) {
$this->forbidden();
}
$params = [
'presets' => LayoutObject::presets(),
'outlines' =>
$this->container['outlines']
];
$response = ['html' =>
$this->render('@gantry-admin/ajax/outline-new.html.twig',
$params)];
return new JsonResponse($response);
}
public function create()
{
// Check if we want to duplicate outline instead.
if ($this->request->post['from'] ===
'outline') {
return
$this->duplicate($this->request->post['outline']);
}
if (!$this->authorize('outline.create')) {
$this->forbidden();
}
/** @var OutlinesObject $outlines */
$outlines = $this->container['outlines'];
$title = $this->request->post['title'];
$preset = $this->request->post['preset'];
$id = $outlines->create(null, $title, $preset);
$html =
$this->render('@gantry-admin/layouts/outline.html.twig',
['name' => $id, 'title' => $outlines[$id]]);
return new JsonResponse(['html' => 'Outline
created.', 'id' => "outline-{$id}",
'outline' => $html]);
}
public function rename($outline)
{
if (!$this->authorize('outline.rename')) {
$this->forbidden();
}
/** @var OutlinesObject $outlines */
$outlines = $this->container['outlines'];
$title = $this->request->post['title'];
$id = $outlines->rename($outline, $title);
$html =
$this->render('@gantry-admin/layouts/outline.html.twig',
['name' => $id, 'title' => $outlines[$id]]);
return new JsonResponse(['html' => 'Outline
renamed.', 'id' => "outline-{$outline}",
'outline' => $html]);
}
public function duplicateForm($outline)
{
if (!$this->authorize('outline.create')) {
$this->forbidden();
}
$params = [
'outlines' =>
$this->container['outlines'],
'outline' => $outline,
'duplicate' => true
];
$response = ['html' =>
$this->render('@gantry-admin/ajax/outline-new.html.twig',
$params)];
return new JsonResponse($response);
}
public function duplicate($outline)
{
if (!$this->authorize('outline.create')) {
$this->forbidden();
}
/** @var OutlinesObject $outlines */
$outlines = $this->container['outlines'];
$title = $this->request->post['title'];
$inherit =
in_array($this->request->post['inherit'], ['1',
'true']);
$id = $outlines->duplicate($outline, $title, $inherit);
$html =
$this->render('@gantry-admin/layouts/outline.html.twig',
['name' => $id, 'title' => $outlines[$id]]);
return new JsonResponse(['html' => 'Outline
duplicated.', 'id' => $id, 'outline' =>
$html]);
}
public function delete($outline)
{
if (!$this->authorize('outline.delete')) {
$this->forbidden();
}
/** @var OutlinesObject $outlines */
$outlines = $this->container['outlines'];
$list = $outlines->user();
if (!isset($list[$outline])) {
$this->forbidden();
}
$outlines->delete($outline);
return new JsonResponse(['html' => 'Outline
deleted.', 'outline' => $outline]);
}
/**
* @return JsonResponse
*/
public function confirmDeletion($id)
{
/** @var OutlinesObject $outlines */
$outlines = $this->container['outlines'];
$params = [
'id' => $id,
'page_type' => 'OUTLINE',
'outline' => $outlines->title($id),
'inherited' =>
$outlines->getInheritingOutlines($id)
];
$html =
$this->render('@gantry-admin/pages/configurations/confirm-deletion.html.twig',
$params);
return new JsonResponse(['html' => $html]);
}
/**
* @return HtmlResponse|RedirectResponse|JsonResponse
*/
public function forward()
{
$path = func_get_args();
$outline = array_shift($path);
$page = array_shift($path);
$method = $this->params['method'];
if ((!isset($outline) || !isset($page)) &&
$this->params['format'] !== 'json') {
// Redirect path to the styles page of the selected outline.
return new
RedirectResponse($this->container->route('configurations',
is_string($outline) ? $outline : 'default', 'styles'));
}
$outlines = $this->container['outlines'];
if (!isset($outlines[$outline])) {
throw new \RuntimeException('Outline not found.',
404);
}
$this->container['outline'] = $outline;
$this->container['configuration'] = $outline;
$resource = $this->params['location'] . '/'.
$page;
$this->params['outline'] = $outline;
$this->params['configuration'] = $outline;
$this->params['location'] = $resource;
$this->params['configuration_page'] = $page;
$this->params['navbar'] =
!empty($this->request->get['navbar']);
return $this->executeForward($resource, $method, $path,
$this->params);
}
protected function executeForward($resource, $method = 'GET',
$path, $params = [])
{
$class = '\\Gantry\\Admin\\Controller\\Html\\' .
strtr(ucwords(strtr($resource, '/', ' ')), '
', '\\');
if (!class_exists($class)) {
throw new \RuntimeException('Page not found', 404);
}
/** @var HtmlController $controller */
$controller = new $class($this->container);
// Execute action.
$response = $controller->execute($method, $path, $params);
if (!$response instanceof Response) {
$response = new HtmlResponse($response);
}
return $response;
}
}
PK���[��_iEE
Admin/Controller/Html/Export.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html;
use Gantry\Component\Admin\HtmlController;
use Gantry\Framework\Exporter;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use Symfony\Component\Yaml\Yaml;
class Export extends HtmlController
{
public function index()
{
if (!class_exists('Gantry\Framework\Exporter')) {
$this->forbidden();
}
if (!class_exists('ZipArchive')) {
throw new \RuntimeException('Please enable PHP ZIP
extension to use this feature.');
}
$exporter = new Exporter;
$exported = $exporter->all();
$zipname =
$exported['export']['theme']['name'] .
'-export.zip';
$tmpname = tempnam(sys_get_temp_dir(), 'zip');
$zip = new \ZipArchive();
$zip->open($tmpname, \ZipArchive::CREATE);
$zip->addFromString("export.yaml",
Yaml::dump($exported['export'], 10, 2));
unset($exported['export']);
foreach ($exported['positions'] as $key => $position)
{
foreach ($position['items'] as $module => $data) {
$zip->addFromString("positions/{$key}/{$module}.yaml",
Yaml::dump($data, 10, 2));
}
$position['ordering'] =
array_keys($position['items']);
unset($position['items']);
$zip->addFromString("positions/{$key}.yaml",
Yaml::dump($position, 10, 2));
}
foreach ($exported['outlines'] as $outline =>
&$data) {
if (!empty($data['config'])) {
foreach ($data['config'] as $name => $config)
{
if (in_array($name, ['particles',
'page'])) {
foreach ($config as $sub => $subconfig) {
$zip->addFromString("outlines/{$outline}/{$name}/{$sub}.yaml",
Yaml::dump($subconfig, 10, 2));
}
} else {
$zip->addFromString("outlines/{$outline}/{$name}.yaml",
Yaml::dump($config, 10, 2));
}
}
}
unset($data['config']);
}
$zip->addFromString("outlines/outlines.yaml",
Yaml::dump($exported['outlines'], 10, 2));
foreach ($exported['menus'] as $menu => $data) {
$zip->addFromString("menus/{$menu}.yaml",
Yaml::dump($data, 10, 2));
}
foreach ($exported['content'] as $id => $data) {
$zip->addFromString("content/{$id}.yaml",
Yaml::dump($data, 10, 2));
}
if (!empty($exported['categories'])) {
$zip->addFromString("content/categories.yaml",
Yaml::dump($exported['categories'], 10, 2));
}
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
foreach ($exported['files'] as $stream => $files) {
foreach ($files as $path => $uri) {
$filename = $locator->findResource($uri);
if (file_exists($filename)) {
$zip->addFile($filename,
"files/{$stream}/{$path}");
}
}
}
$zip->close();
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename=' .
$zipname);
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($tmpname));
@ob_end_clean();
flush();
readfile($tmpname);
unlink($tmpname);
exit;
}
}
PK���[�?�C}
}
Admin/Controller/Html/Import.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html;
use Gantry\Component\Admin\HtmlController;
use Gantry\Component\Filesystem\Folder;
use Gantry\Framework\Importer;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use Symfony\Component\Yaml\Yaml;
class Import extends HtmlController
{
protected $httpVerbs = [
'GET' => [
'/' => 'index',
],
'POST' => [
'/' => 'import',
]
];
public function index()
{
return
$this->render('@gantry-admin/pages/import/import.html.twig',
$this->params);
}
public function import()
{
if (!isset($_FILES['file']['error']) ||
is_array($_FILES['file']['error'])) {
throw new \RuntimeException('No file sent', 400);
}
// Check $_FILES['file']['error'] value.
switch ($_FILES['file']['error']) {
case UPLOAD_ERR_OK:
break;
case UPLOAD_ERR_NO_FILE:
throw new \RuntimeException('No file sent', 400);
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
throw new \RuntimeException('Exceeded filesize
limit.', 400);
default:
throw new \RuntimeException('Unkown errors',
400);
}
$filename = $_FILES['file']['tmp_name'];
if (!is_uploaded_file($filename)) {
throw new \RuntimeException('No file sent', 400);
}
$zip = new \ZipArchive;
if ($zip->open($filename) !== true || !($export =
Yaml::parse($zip->getFromName('export.yaml'))) ||
!isset($export['gantry'])) {
throw new \RuntimeException('Uploaded file is not Gantry 5
export file', 400);
}
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
$folder =
$locator->findResource('gantry-cache://import', true, true);
if (is_dir($folder)) Folder::delete($folder);
$zip->extractTo($folder);
$zip->close();
$importer = new Importer($folder);
$importer->all();
if (is_dir($folder)) Folder::delete($folder);
$this->params['success'] = true;
return
$this->render('@gantry-admin/pages/import/import.html.twig',
$this->params);
}
}
PK���[�^�ww!Admin/Controller/Html/Install.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html;
use Gantry\Component\Admin\HtmlController;
use Gantry\Framework\ThemeInstaller;
class Install extends HtmlController
{
public function index()
{
if (!$this->authorize('updates.manage') ||
!class_exists('\Gantry\Framework\ThemeInstaller')) {
$this->forbidden();
}
$installer = new ThemeInstaller();
$installer->initialized = true;
$installer->loadExtension($this->container['theme.name']);
$installer->installDefaults();
$installer->installSampleData();
$installer->finalize();
$this->params['actions'] = $installer->actions;
return
$this->render('@gantry-admin/pages/install/install.html.twig',
$this->params);
}
}
PK���[
����F�FAdmin/Controller/Html/Menu.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html;
use Gantry\Component\Admin\HtmlController;
use Gantry\Component\Config\BlueprintSchema;
use Gantry\Component\Config\BlueprintForm;
use Gantry\Component\Config\Config;
use Gantry\Component\Menu\Item;
use Gantry\Component\Request\Input;
use Gantry\Component\Response\HtmlResponse;
use Gantry\Component\Response\JsonResponse;
use Gantry\Component\Response\Response;
use Gantry\Framework\Menu as MenuObject;
use RocketTheme\Toolbox\Event\Event;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Menu extends HtmlController
{
protected $httpVerbs = [
'GET' => [
'/' => 'item',
'/*' => 'item',
'/*/**' => 'item',
'/particle' => 'particle',
'/particle/*' =>
'validateParticle',
'/select' => 'undefined',
'/select/particle' =>
'selectParticle',
'/select/module' => 'selectModule',
'/select/widget' => 'selectWidget',
'/edit' => 'undefined',
'/edit/*' => 'edit',
'/edit/*/**' => 'editItem',
],
'POST' => [
'/' => 'save',
'/*' => 'save',
'/*/**' => 'item',
'/particle' => 'particle',
'/particle/*' =>
'validateParticle',
'/select' => 'undefined',
'/select/particle' =>
'selectParticle',
'/select/module' => 'selectModule',
'/select/widget' => 'selectWidget',
'/widget' => 'widget',
'/edit' => 'undefined',
'/edit/*' => 'edit',
'/edit/*/**' => 'editItem',
'/edit/*/validate' => 'validate',
],
'PUT' => [
'/*' => 'replace'
],
'PATCH' => [
'/*' => 'update'
],
'DELETE' => [
'/*' => 'destroy'
]
];
public function execute($method, array $path, array $params)
{
if (!$this->authorize('menu.manage')) {
$this->forbidden();
}
return parent::execute($method, $path, $params);
}
public function item($id = null)
{
// Load the menu.
try {
$resource = $this->loadResource($id,
$this->build($this->request->post));
} catch (\Exception $e) {
return
$this->render('@gantry-admin/pages/menu/menu.html.twig',
$this->params);
}
// All extra arguments become the path.
$path = array_slice(func_get_args(), 1);
// Get menu item and make sure it exists.
$item = $resource[implode('/', $path)];
if (!$item) {
throw new \RuntimeException('Menu item not found',
404);
}
// Fill parameters to be passed to the template file.
$this->params['id'] = $resource->name();
$this->params['menus'] = $resource->getMenus();
$this->params['default_menu'] =
$resource->hasDefaultMenu() ? $resource->getDefaultMenuName() :
false;
$this->params['menu'] = $resource;
$this->params['path'] = implode('/', $path);
// Detect special case to fetch only single column group.
$group = $this->request->get['group'];
if (empty($this->params['ajax']) ||
empty($this->request->get['inline'])) {
// Handle special case to fetch only one column group.
if (count($path) > 0) {
$this->params['columns'] =
$resource[$path[0]];
}
if (count($path) > 1) {
$this->params['column'] = isset($group) ?
(int) $group : $resource[implode('/', array_slice($path, 0,
2))]->group;
$this->params['override'] = $item;
}
return
$this->render('@gantry-admin/pages/menu/menu.html.twig',
$this->params);
} else {
// Get layout name.
$layout = $this->layoutName(count($path) + (int)
isset($group));
$this->params['item'] = $item;
$this->params['group'] = isset($group) ? (int)
$group : $resource[implode('/', array_slice($path, 0,
2))]->group;
return $this->render('@gantry-admin/menu/' .
$layout . '.html.twig', $this->params) ?:
' ';
}
}
public function edit($id)
{
$resource = $this->loadResource($id);
$input = $this->build($this->request->post);
if ($input) {
$resource->config()->merge(['settings' =>
$input['settings']]);
}
// Fill parameters to be passed to the template file.
$this->params['id'] = $resource->name();
$this->params['blueprints'] =
$this->loadBlueprints();
$this->params['data'] = ['settings' =>
$resource->settings()];
return
$this->render('@gantry-admin/pages/menu/edit.html.twig',
$this->params);
}
public function save($id = null)
{
$resource = $this->loadResource($id);
$data = $this->build($this->request->post);
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
$filename =
$locator->findResource("gantry-config://menu/{$resource->name()}.yaml",
true, true);
// Fire save event.
$event = new Event;
$event->gantry = $this->container;
$event->theme = $this->container['theme'];
$event->controller = $this;
$event->resource = $id;
$event->menu = $data;
$this->container->fireEvent('admin.menus.save',
$event);
$file = YamlFile::instance($filename);
$file->settings(['inline' => 99]);
$file->save($data->toArray());
$file->free();
}
public function editItem($id)
{
// All extra arguments become the path.
$path = array_slice(func_get_args(), 1);
$keyword = end($path);
// Special case: validate instead of fetching menu item.
if ($this->method == 'POST' && $keyword ==
'validate') {
$params = array_slice(func_get_args(), 0, -1);
return call_user_func_array([$this, 'validateitem'],
$params);
}
$path = html_entity_decode(implode('/', $path),
ENT_COMPAT | ENT_HTML5, 'UTF-8');
// Load the menu.
$resource = $this->loadResource($id);
// Get menu item and make sure it exists.
/** @var Item $item */
$item = $resource[$path];
if (!$item) {
throw new \RuntimeException('Menu item not found',
404);
}
$data =
$this->request->post->getJsonArray('item');
if ($data) {
$item->update($data);
}
// Load blueprints for the menu item.
$blueprints = $this->loadBlueprints('menuitem');
$this->params = [
'id' => $resource->name(),
'path' => $path,
'blueprints' => ['fields' =>
$blueprints['form/fields/items/fields']],
'data' => $item->toArray() +
['path' => $path],
] + $this->params;
return
$this->render('@gantry-admin/pages/menu/menuitem.html.twig',
$this->params);
}
public function particle()
{
$data = $this->request->post['item'];
if ($data) {
$data = json_decode($data, true);
} else {
$data = $this->request->post->getArray();
}
$name = isset($data['particle']) ?
$data['particle'] : null;
$block = BlueprintForm::instance('menu/block.yaml',
'gantry-admin://blueprints');
$blueprints =
$this->container['particles']->getBlueprintForm($name);
// Load particle blueprints and default settings.
$validator = $this->loadBlueprints('menu');
$callable = function () use ($validator) {
return $validator;
};
// Create configuration from the defaults.
$item = new Config($data, $callable);
$item->def('type', 'particle');
$item->def('title',
$blueprints->get('name'));
$item->def('options.type',
$blueprints->get('type', 'particle'));
$item->def('options.particle', []);
$item->def('options.block', []);
$this->params += [
'item' => $item,
'block' => $block,
'data' => ['particles' =>
[$name => $item->options['particle']]],
'particle' => $blueprints,
'parent' => 'settings',
'prefix' => "particles.{$name}.",
'route' =>
"configurations.default.settings",
'action' =>
"menu/particle/{$name}"
];
return
$this->render('@gantry-admin/pages/menu/particle.html.twig',
$this->params);
}
public function validateParticle($name)
{
// Validate only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
// Load particle blueprints and default settings.
$validator = new BlueprintSchema;
$validator->embed('options',
$this->container['particles']->get($name));
$blueprints =
$this->container['particles']->getBlueprintForm($name);
// Create configuration from the defaults.
$data = new Config([],
function () use ($validator) {
return $validator;
}
);
$data->set('type', 'particle');
$data->set('particle', $name);
$data->set('title',
$this->request->post['title'] ?:
$blueprints->post['name']);
$data->set('options.particle',
$this->request->post->getArray("particles.{$name}"));
$data->def('options.particle.enabled', 1);
$data->set('enabled',
$data->get('options.particle.enabled'));
$block =
$this->request->post->getArray('block');
foreach ($block as $key => $param) {
if ($param === '') {
unset($block[$key]);
}
}
$data->join('options.block', $block);
// TODO: validate
// Fill parameters to be passed to the template file.
$this->params['item'] = (object) $data->toArray();
$html =
$this->render('@gantry-admin/menu/item.html.twig',
$this->params);
return new JsonResponse(['item' =>
$data->toArray(), 'html' => $html]);
}
public function selectModule()
{
return
$this->render('@gantry-admin/modals/module-picker.html.twig',
$this->params);
}
public function selectWidget()
{
$this->params['next'] = 'menu/widget';
return
$this->render('@gantry-admin/modals/widget-picker.html.twig',
$this->params);
}
public function widget()
{
$data = $this->request->post->getJson('item');
$path = [$data->widget];
$this->params['scope'] = 'menu';
return $this->executeForward('widget',
'POST', $path, $this->params);
}
public function selectParticle()
{
$groups = [
'Particles' => ['particle' => []],
];
$particles = [
'position' => [],
'spacer' => [],
'system' => [],
'particle' => [],
];
$particles = array_replace($particles, $this->getParticles());
unset($particles['atom'],
$particles['position']);
foreach ($particles as &$group) {
asort($group);
}
foreach ($groups as $section => $children) {
foreach ($children as $key => $child) {
$groups[$section][$key] = $particles[$key];
}
}
$this->params += [
'particles' => $groups,
'route' => 'menu/particle',
];
return
$this->render('@gantry-admin/modals/particle-picker.html.twig',
$this->params);
}
public function validate($id)
{
// Validate only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
// Load particle blueprints and default settings.
$validator = $this->loadBlueprints('menu');
$callable = function () use ($validator) {
return $validator;
};
// Create configuration from the defaults.
$data = new Config($this->request->post->getArray(),
$callable);
// TODO: validate
return new JsonResponse(['settings' => (array)
$data->get('settings')]);
}
public function validateitem($id)
{
// All extra arguments become the path.
$path = array_slice(func_get_args(), 1);
// Validate only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
// Load the menu.
$resource = $this->loadResource($id);
// Load particle blueprints and default settings.
$validator = $this->loadBlueprints('menuitem');
$callable = function () use ($validator) {
return $validator;
};
// Create configuration from the defaults.
$data = new Config($this->request->post->getArray(),
$callable);
// TODO: validate
$item = $resource[implode('/', $path)];
$item->update($data->toArray());
// Fill parameters to be passed to the template file.
$this->params['id'] = $resource->name();
$this->params['item'] = $item;
$this->params['group'] = isset($group) ? $group :
$resource[implode('/', array_slice($path, 0, 2))]->group;
if (!$item->title) {
throw new \RuntimeException('Title from the Menu Item
should not be empty', 400);
}
$html =
$this->render('@gantry-admin/menu/item.html.twig',
$this->params);
return new JsonResponse(['path' =>
implode('/', $path), 'item' => $data->toArray(),
'html' => $html]);
}
protected function layoutName($level)
{
switch ($level) {
case 0:
return 'base';
case 1:
return 'columns';
default:
return 'list';
}
}
/**
* Load resource.
*
* @param string $id
* @param Config $config
*
* @return \Gantry\Component\Menu\AbstractMenu
* @throws \RuntimeException
*/
protected function loadResource($id, Config $config = null)
{
/** @var MenuObject $menus */
$menus = $this->container['menu'];
return $menus->instance(['menu' => $id,
'admin' => true], $config);
}
/**
* Load blueprints.
*
* @param string $name
*
* @return BlueprintForm
*/
protected function loadBlueprints($name = 'menu')
{
return BlueprintForm::instance("menu/{$name}.yaml",
'gantry-admin://blueprints');
}
public function build(Input $input)
{
try {
$items = $input->get('items');
if ($items && $items[0] !== '{' &&
$items[0] !== '[') {
$items = urldecode((string)base64_decode($items));
}
$items = json_decode($items, true);
$settings = $input->getJsonArray('settings');
$order = $input->getJsonArray('ordering');
} catch (\Exception $e) {
throw new \RuntimeException('Invalid menu structure',
400);
}
if (!$items && !$settings && !$order) {
return null;
}
krsort($order);
$ordering = ['' => []];
foreach ($order as $path => $columns) {
foreach ($columns as $column => $colitems) {
$list = [];
foreach ($colitems as $item) {
$name = trim(substr($item, strlen($path)),
'/');
if (isset($ordering[$item])) {
$list[$name] = $ordering[$item];
unset($ordering[$item]);
} else {
$list[$name] = '';
}
}
if (count($columns) > 1) {
$ordering[$path][$column] = $list;
} else {
$ordering[$path] = $list;
}
}
}
$data = new Config([]);
$data->set('settings', $settings);
$data->set('ordering', $ordering['']);
$data->set('items', $items);
return $data;
}
protected function getParticles()
{
$particles = $this->container['particles']->all();
$list = [];
foreach ($particles as $name => $particle) {
$type = isset($particle['type']) ?
$particle['type'] : 'particle';
$particleName = isset($particle['name']) ?
$particle['name'] : $name;
$particleIcon = isset($particle['icon']) ?
$particle['icon'] : null;
$list[$type][$name] = ['name' => $particleName,
'icon' => $particleIcon];
}
return $list;
}
protected function executeForward($resource, $method = 'GET',
$path, $params = [])
{
$class = '\\Gantry\\Admin\\Controller\\Json\\' .
strtr(ucwords(strtr($resource, '/', ' ')), '
', '\\');
if (!class_exists($class)) {
throw new \RuntimeException('Page not found', 404);
}
/** @var HtmlController $controller */
$controller = new $class($this->container);
// Execute action.
$response = $controller->execute($method, $path, $params);
if (!$response instanceof Response) {
$response = new HtmlResponse($response);
}
return $response;
}
}
PK���[�,�ȵ*�*#Admin/Controller/Html/Positions.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html;
use Gantry\Component\Admin\HtmlController;
use Gantry\Component\Config\BlueprintSchema;
use Gantry\Component\Config\BlueprintForm;
use Gantry\Component\Config\Config;
use Gantry\Component\Position\Module;
use Gantry\Component\Position\Position;
use Gantry\Component\Response\JsonResponse;
use Gantry\Framework\Assignments;
use Gantry\Framework\Positions as PositionsObject;
class Positions extends HtmlController
{
protected $httpVerbs = [
'GET' => [
'/' => 'index',
'/*' => 'undefined',
'/*/add' =>
'selectParticle',
],
'POST' => [
'/' => 'save',
'/create' => 'create',
'/*' => 'undefined',
'/*/rename' => 'rename',
'/*/duplicate' => 'duplicate',
'/*/delete' => 'delete',
'/*/edit' => 'undefined',
'/*/edit/particle' => 'particle',
'/*/edit/particle/*' =>
'validateParticle',
'/edit' => 'undefined',
'/edit/particle' => 'particle',
]
];
public function index()
{
$this->params['positions'] =
$this->container['positions'];
return
$this->render('@gantry-admin/pages/positions/positions.html.twig',
$this->params);
}
public function create()
{
// Create only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
/** @var PositionsObject $position */
$positions = $this->container['positions'];
$title = (string)
$this->request->post->get('title',
'Untitled');
$key = (string) $this->request->post['key'];
$id = $positions->create($title, $key);
$html =
$this->render('@gantry-admin/layouts/position.html.twig',
['position' => ['name' => $id, 'title'
=> $title]]);
return new JsonResponse(['html' =>
sprintf("Position '%s' created.", $id), 'id'
=> "position-{$id}", 'key' => $id,
'position' => $html]);
}
public function rename($old)
{
// Rename only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
$title = (string) $this->request->post['title'];
$key = (string) $this->request->post['key'];
$data = (string) $this->request->post['data'];
/** @var PositionsObject $positions */
$positions = $this->container['positions'];
$position = $positions[$old];
$exists = isset($position);
if (!$exists) {
if (!$data) {
throw new \RuntimeException(sprintf("Position
'%s' not found", $old), 404);
}
$position = new Position($key ?: $old);
}
if (strlen($title)) {
$position->title = (string) $title;
}
if ($exists && strlen($key)) {
$position = $position->rename($key);
} else {
$position->save();
}
if ($data) {
$data = ['title' => $position->title] +
json_decode($data, true);
$position = new Position($position->name, $data);
}
$html =
$this->render('@gantry-admin/layouts/position.html.twig',
['position' => $position]);
return new JsonResponse(['html' =>
sprintf("Position saved"), 'id' =>
"position-{$position->name}", 'key' =>
$position->name, 'position' => $html]);
}
public function duplicate($position)
{
// Duplicate only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
/** @var PositionsObject $positions */
$positions = $this->container['positions'];
$id = $positions->duplicate($position);
return new JsonResponse(['html' =>
sprintf("Position duplicated as '%s'.", $id)]);
}
public function delete($position)
{
// Delete only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
/** @var PositionsObject $positions */
$positions = $this->container['positions'];
$positions->delete($position);
return new JsonResponse(['html' =>
sprintf("Position '%s' deleted.", $position),
'position' => $position]);
}
public function save()
{
// Save only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
$data =
$this->request->post->getJsonArray('positions');
/** @var PositionsObject $position */
$positions = $this->container['positions'];
$positions->import($data);
return new JsonResponse(['html' =>
sprintf("Positions saved.")]);
}
public function particle($position = null)
{
if (!$position) {
$position = $this->request->post['position'];
}
$data = $this->request->post['item'];
if ($data) {
$data = json_decode($data, true);
} else {
$data = $this->request->post->getArray();
}
$name = isset($data['options']['type']) ?
$data['options']['type'] :
(isset($data['particle']) ? $data['particle'] : null);
$blueprints =
$this->container['particles']->getBlueprintForm($name);
$chromeBlueprints =
BlueprintForm::instance('position/chrome.yaml',
'gantry-admin://blueprints');
$data['title'] = isset($data['title']) ?
$data['title'] : $blueprints['name'];
$data['chrome'] = isset($data['chrome']) ?
$data['chrome'] : [];
$data['options'] = isset($data['options']) ?
$data['options'] : [];
$data['options']['type'] = $name;
$attributes =
isset($data['options']['attributes']) ?
$data['options']['attributes'] : [];
$assignments = new Assignments();
$this->params += [
'item' => $data,
'data' => [
'particles' => [$name => $attributes],
'chrome' => $data['chrome'],
'assignments' =>
isset($data['assignments']) ? $data['assignments'] :
'all'
],
'particle' => $blueprints,
'chrome' => $chromeBlueprints,
'assignments' => $assignments->get(),
'parent' => 'settings',
'prefix' => "particles.{$name}.",
'route' =>
"configurations.default.settings",
'action' =>
"positions/{$position}/edit/particle/{$name}"
];
return
$this->render('@gantry-admin/pages/positions/particle.html.twig',
$this->params);
}
public function validateParticle($position, $name)
{
// Validate only exists for JSON.
if (empty($this->params['ajax'])) {
$this->undefined();
}
if (!$this->request->post->get('_end')) {
throw new \OverflowException("Incomplete data received.
Please increase the value of 'max_input_vars' variable (in
php.ini or .htaccess)", 400);
}
// Load particle blueprints and default settings.
$validator = new BlueprintSchema;
$validator->embed('options',
$this->container['particles']->get($name));
$blueprints =
$this->container['particles']->getBlueprintForm($name);
// Create configuration from the defaults.
$data = new Config([],
function () use ($validator) {
return $validator;
}
);
$data->set('position', $position);
$data->set('id', $id =
$this->request->post['id']);
$data->set('type', 'particle');
$data->set('title',
$this->request->post['title'] ?:
$blueprints->post['name']);
$data->set('chrome',
$this->request->post->getArray('chrome'));
$data->set('options.type', $name);
$data->set('options.attributes',
$this->request->post->getArray("particles.{$name}"));
$data->def('options.attributes.enabled', 1);
$assignments = (new
Assignments())->filter($this->request->post->getArray('assignments'),
true);
if (!$assignments) {
// Use special syntax for no assignments.
$assignments = 'none';
} elseif ($assignments === ['page' => [true]]) {
// Use special syntax for assigned to all pages. This is a
special case and hardcoded for now.
$assignments = 'all';
}
$data->set('assignments', $assignments);
// TODO: validate
// Fill parameters to be passed to the template file.
$this->params['position'] = $position;
$this->params['item'] = (object) $data->toArray();
$this->params['module'] = new Module($id, $position,
$data->toArray());
$html =
$this->render('@gantry-admin/pages/positions/item.html.twig',
$this->params);
return new JsonResponse(['item' =>
$data->toArray(), 'html' => $html, 'position'
=> $position]);
}
public function selectParticle($position)
{
$groups = [
'Particles' => ['particle' => []],
];
$particles = [
'position' => [],
'spacer' => [],
'system' => [],
'particle' => [],
];
$particles = array_replace($particles, $this->getParticles());
unset($particles['atom'],
$particles['position']);
foreach ($particles as &$group) {
asort($group);
}
foreach ($groups as $section => $children) {
foreach ($children as $key => $child) {
$groups[$section][$key] = $particles[$key];
}
}
$this->params += [
'particles' => $groups,
'route' =>
"positions/{$position}/edit/particle",
];
return
$this->render('@gantry-admin/modals/particle-picker.html.twig',
$this->params);
}
protected function getParticles()
{
$particles = $this->container['particles']->all();
$list = [];
foreach ($particles as $name => $particle) {
$type = isset($particle['type']) ?
$particle['type'] : 'particle';
$particleName = isset($particle['name']) ?
$particle['name'] : $name;
$particleIcon = isset($particle['icon']) ?
$particle['icon'] : null;
$list[$type][$name] = ['name' => $particleName,
'icon' => $particleIcon];
}
return $list;
}
}
PK���[�����
Admin/Controller/Html/Themes.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Html;
use Gantry\Admin\ThemeList;
use Gantry\Component\Admin\HtmlController;
class Themes extends HtmlController
{
public function index()
{
$this->params['themes'] = (new
ThemeList)->getThemes();
return
$this->render('@gantry-admin/pages/themes/themes.html.twig',
$this->params);
}
}
PK���[��z66Admin/Controller/Json/Atoms.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Json;
use Gantry\Component\Admin\JsonController;
use Gantry\Component\Response\JsonResponse;
/**
* Class Atoms
* @package Gantry\Admin\Controller\Json
*/
class Atoms extends JsonController
{
protected $httpVerbs = [
'GET' => [
'/' => 'index',
'/*' => 'index',
'/instance' => 'atom'
],
'POST' => [
'/' => 'index',
'/*' => 'index',
'/instance' => 'atom'
]
];
public function index()
{
$path = implode('/', func_get_args());
$post = $this->request->request;
$outline = $post['outline'];
$type = $post['subtype'];
$inherit = $post['inherit'];
$id = $post['id'];
if (!$outline) {
throw new \RuntimeException('Outline not given',
400);
}
$this->container['outline'] = $outline;
$this->container['configuration'] = $outline;
$atoms = new \Gantry\Framework\Atoms((array)
$this->container['config']->get('page.head.atoms'));
if ($inherit) {
$atoms->inheritAll($outline);
}
$item = (object) $atoms->id($id);
if ($path === 'list') {
$list = $atoms->type($type);
if (empty($item->id)) {
$item = (object)reset($list);
}
}
$selected = !empty($item->id) ? $item->id : null;
$type = isset($item->type) ? $item->type : $type;
$item->attributes = isset($item->attributes) ? (array)
$item->attributes : [];
$blueprints =
$this->container['particles']->getBlueprintForm($type);
$blueprints->set('form/fields/_inherit',
['type' => 'gantry.inherit']);
$params = [
'gantry' => $this->container,
'parent' => 'settings',
'route' =>
"configurations.{$outline}.settings",
'inherit' => $inherit ? $outline : null,
'title' => isset($item->title) ?
$item->title : '',
'blueprints' =>
$blueprints->get('form'),
'item' => $item,
'data' => ['particles' =>
[$type => $item->attributes]],
'prefix' => "particles.{$type}.",
'editable' => true,
'overrideable' => false,
'skip' => ['enabled']
];
$html['g-settings-atom'] =
$this->render('@gantry-admin/pages/configurations/layouts/particle-card.html.twig',
$params);
if (isset($list)) {
$html['g-inherit-atom'] =
$this->renderAtomsInput($inherit ? $outline : null, $type, $selected,
$list);
}
return new JsonResponse(['json' => $item,
'html' => $html]);
}
public function atom()
{
$post = $this->request->request;
$outline = $post['outline'];
$id = $post['id'];
if (!$outline) {
throw new \RuntimeException('Outline not given',
400);
}
$this->container['outline'] = $outline;
$this->container['configuration'] = $outline;
$atoms = new \Gantry\Framework\Atoms((array)
$this->container['config']->get('page.head.atoms'));
$item = (object) $atoms->id($id);
if (empty($item->id)) {
throw new \RuntimeException('Atom was not found from the
outline', 404);
}
$name = $item->type;
$prefix = "particles.{$name}";
$blueprints =
$this->container['particles']->getBlueprintForm($name);
$blueprints->set('form/fields/_inherit',
['type' => 'gantry.inherit']);
$item->attributes = isset($item->attributes) ? (array)
$item->attributes : [];
$this->params['id'] = $name;
$this->params += [
'item' => $item,
'data' => ['particles' =>
[$name => $item->attributes]],
'prefix' => "particles.{$name}.",
'particle' => $blueprints,
'parent' => 'settings',
'route' =>
"configurations.{$outline}.settings",
'action' => str_replace('.',
'/', 'configurations.' . $outline .
'.layout.' . $prefix . '.validate'),
'skip' => ['enabled'],
'editable' => false,
'overrideable' => false,
];
$html =
$this->render('@gantry-admin/modals/atom-preview.html.twig',
$this->params);
return new JsonResponse(['html' => $html]);
}
/**
* Render input field for particle picker.
*
* @param string $outline
* @param string $type
* @param string $selected
* @param array $instances
* @return string
*/
protected function renderAtomsInput($outline, $type, $selected, array
$instances)
{
$params = [
'layout' => 'input',
'scope' => 'inherit.',
'field' => [
'name' => 'atom',
'type' => 'gantry.atoms',
'id' => 'g-inherit-atom',
'outline' => $outline,
'atoms' => $instances,
'atom' => $type
],
'value' => $selected
];
return
$this->render('@gantry-admin/forms/fields/gantry/atoms.html.twig',
$params);
}
}
PK���[7��]��#Admin/Controller/Json/Changelog.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Json;
use Gantry\Component\Admin\JsonController;
use Gantry\Component\Remote\Response as RemoteResponse;
use Gantry\Component\Response\JsonResponse;
class Changelog extends JsonController
{
protected $url =
'https://raw.githubusercontent.com/gantry/gantry5';
protected $fullurl =
'https://github.com/gantry/gantry5/blob/develop';
protected $issues =
'https://github.com/gantry/gantry5/issues';
protected $contrib = 'https://github.com';
protected $file = 'CHANGELOG.md';
protected $platforms = ['common' => 'share-alt',
'joomla' => '', 'wordpress' =>
'', 'grav' => ''];
protected $httpVerbs = [
'POST' => [
'/' => 'index'
]
];
public function index()
{
$version = $this->request->post['version'];
$lookup = $version;
if ($version == '@version@') {
$version = 'develop';
$lookup = '';
}
if (substr($version, 0, 4) == 'dev-') {
$version = preg_replace('/^dev-/i', '',
$version);
$lookup = '';
}
$url = $this->url . '/' . $version .
'/' . $this->file;
$changelog = RemoteResponse::get($url);
if ($changelog) {
$found = preg_match("/(#\\s" . $lookup .
".+?\\n.*?)(?=\\n{1,}#|$)/uis", $changelog, $changelog);
if ($found) {
$changelog =
\Parsedown::instance()->parse($changelog[0]);
// auto-link issues
$changelog = preg_replace("/#(\\d{1,})/uis",
'<a target="_blank" rel="noopener"
href="' . $this->issues .
'/$1">#$1</a>', $changelog);
// auto-link contributors
$changelog = preg_replace("/@([\\w]+)[^\\w]/uis",
'<a target="_blank" rel="noopener"
href="' . $this->contrib . '/$1">@$1</a>
', $changelog);
// add icons for platforms
foreach($this->platforms as $platform => $icon) {
$changelog = preg_replace('/(<a
href="\#' . $platform . '">)/uis',
'$1<i class="fa fa-' . ($icon ?: $platform) .
'" aria-hidden="true"></i> ',
$changelog);
}
} else {
$changelog = 'No changelog for version
<strong>' . $version . '</strong> was found.';
}
}
$response = [
'html' =>
$this->render('@gantry-admin/ajax/changelog.html.twig', [
'changelog' => $changelog,
'version' => $version,
'url' => $url,
'fullurl' => $this->fullurl .
'/' . $this->file
])
];
return new JsonResponse($response);
}
}
PK���[�)����)Admin/Controller/Json/Confirmdeletion.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Json;
use Gantry\Component\Admin\JsonController;
use Gantry\Component\Response\JsonResponse;
class Confirmdeletion extends JsonController
{
protected $httpVerbs = [
'GET' => [
'/' => 'index'
]
];
public function index()
{
$pageType =
$this->request->get->get('page_type',
'OUTLINE');
$response = ['html' =>
$this->render('@gantry-admin/ajax/confirm-deletion.html.twig',
['page_type' => $pageType])];
return new JsonResponse($response);
}
}
PK���[�����!Admin/Controller/Json/Devprod.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Json;
use Gantry\Component\Admin\JsonController;
use Gantry\Component\Response\JsonResponse;
use RocketTheme\Toolbox\Event\Event;
class Devprod extends JsonController
{
public function store()
{
$production =
intval((bool)$this->request->post['mode']);
// Fire save event.
$event = new Event;
$event->gantry = $this->container;
$event->controller = $this;
$event->data = ['production' => $production];
$this->container->fireEvent('admin.global.save',
$event);
$response = [
'mode' => $production,
'title' => $production ? 'Production' :
'Development',
'html' => $production ? 'Production mode
enabled' : 'Development mode enabled',
];
return new JsonResponse($response);
}
}
PK���[
PQ�>�>$Admin/Controller/Json/Filepicker.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Json;
use Gantry\Component\Admin\JsonController;
use Gantry\Component\Filesystem\Folder;
use Gantry\Component\Response\JsonResponse;
use RocketTheme\Toolbox\File\File;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceIterator;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Filepicker extends JsonController
{
protected $base = false;
protected $value = false;
protected $filter = false;
protected $httpVerbs = [
'GET' => [
'/' => 'index',
'/*' => 'index',
'/display' => 'undefined',
'/display/**' => 'displayFile',
'/download' => 'undefined',
'/download/**' => 'downloadFile',
],
'POST' => [
'/' => 'index',
'/*' => 'index',
'/subfolder' => 'subfolder',
'/subfolder/*' => 'subfolder',
'/upload' => 'undefined',
'/upload/**' => 'upload'
],
'DELETE' => [
'/' => 'undefined',
'/**' => 'delete'
]
];
public function index()
{
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
$bookmarks = [];
$drives = ['/'];
$subfolder = false;
$this->base = $locator->base;
if ($this->method == 'POST') {
$root = $this->request->post['root'];
$drives = isset($root) ? ($root !== 'false' ?
(array) $root : ['/']) : ['/'];
$subfolder =
$this->request->post['subfolder'] ? true : false;
$filter = $this->request->post['filter'];
$this->filter = isset($filter) ? ($filter !==
'false' ? $filter : false) : false;
$this->value =
$this->request->post['value'] ?: '';
}
foreach ($drives as $drive) {
// cleanup of the path so it's chrooted.
$drive = str_replace('..', '', $drive);
$isStream = $locator->isStream($drive);
$path = rtrim($this->base, '/') .
'/' . ltrim($drive, '/');
// It's a stream but the scheme doesn't exist. we
skip it.
if (!$isStream && (strpos($drive, '://') ||
!file_exists($path))) {
continue;
}
if ($isStream && !$locator->findResources($drive)) {
continue;
}
$key = $isStream ? $drive : preg_replace('#/{2,}+#',
'/', $drive);
if (!array_key_exists($key, $bookmarks)) {
$bookmarks[$key] = $isStream
? [$locator->getIterator($drive)]
: [rtrim(Folder::getRelativePath($path), '/')
. '/'];
}
}
if (!count($bookmarks)) {
throw new \RuntimeException(sprintf('%s "%s" not
found', count($drives) > 1 ? 'directories' :
'directory', implode('", "', $drives)), 404);
}
$folders = [];
$active = [];
$index = 0;
$activeFallback = '';
// iterating the folder and collecting subfolders and files
foreach ($bookmarks as $key => $bookmark) {
$folders[$key] = [];
if (!$index) {
$activeFallback = $key;
}
foreach ($bookmark as $folder) {
$isStream = $this->isStream($folder);
if ($isStream) {
unset($bookmarks[$key]);
$iterator = new \IteratorIterator($folder);
$folder = $key;
} else {
$iterator = new \DirectoryIterator($this->base .
'/' . ltrim($folder, '/'));
}
$folders[$key][$folder] = new \ArrayObject();
if (!$index && !$this->value) {
$active[] = $folder;
}
/** @var \SplFileInfo $info */
foreach ($iterator as $info) {
// no dot files nor files beginning with dot
if ($info->isDot() ||
substr($info->getFilename(), 0, 1) == '.') {
continue;
}
$file = new \stdClass();
$this->attachData($file, $info, $folder);
if ($file->dir) {
if ($file->pathname == dirname($this->value))
{
$active[] = $file->pathname;
}
$folders[$key][$folder]->append($file);
} else {
/*if ($filter && !preg_match("/"
. $filter . "/i", $file->filename)) {
continue;
}
if ((!$index && !$this->value) ||
(in_array(dirname($file->pathname), $active))) {
$files->append($file);
}*/
}
}
if ($isStream) {
$bookmarks[$key][] = $key;
}
$index++;
}
}
if (!count($active)) {
$active[] = $activeFallback;
}
$lastItem = end($active);
$files = $this->listFiles($lastItem);
$response = [];
reset($active);
if (!$subfolder) {
$response['html'] = $this->render(
'@gantry-admin/ajax/filepicker.html.twig', [
'active' => $active,
'base' => $this->base,
'bookmarks' => $bookmarks,
'folders' => $folders,
'files' => $files,
'filter' => $this->filter,
'value' => $this->value
]
);
} else {
$response['subfolder'] =
!$folders[$key][$folder]->count()
? false
: $this->render(
'@gantry-admin/ajax/filepicker/subfolders.html.twig',
['folder' => $folders[$key][$folder]]
);
$response['files'] = $this->render(
'@gantry-admin/ajax/filepicker/files.html.twig',
['files' => $files, 'value' =>
$this->value]
);
}
return new JsonResponse($response);
}
protected function attachData(&$node, $iteration, $folder)
{
foreach (
['getFilename', 'getExtension',
'getPerms', 'getMTime', 'getBasename',
'getPathname', 'getSize', 'getType',
'isReadable', 'isWritable',
'isDir', 'isFile'] as $method
) {
$keyMethod =
strtolower(preg_replace("/^(is|get)/", '', $method));
$node->{$keyMethod} = $iteration->{$method}();
if ($method == 'getPathname') {
$node->{$keyMethod} = $this->isStream($folder) ?
$iteration->getUrl() : Folder::getRelativePath($node->{$keyMethod});
} else {
if ($method == 'getExtension') {
$node->isImage =
in_array(strtolower($node->{$keyMethod}), ['jpg',
'jpeg', 'png', 'gif', 'ico',
'svg', 'bmp', 'webp']);
}
}
}
}
protected function listFiles($folder)
{
$isStream = $this->isStream($folder);
$locator = $this->container['locator'];
$iterator = $isStream ? new
\IteratorIterator($locator->getIterator($folder)) : new
\DirectoryIterator($this->base . '/' . ltrim($folder,
'/'));
$files = new \ArrayObject();
/** @var \SplFileInfo $info */
foreach ($iterator as $info) {
// no dot files nor files beginning with dot
if ($info->isDot() || substr($info->getFilename(), 0, 1)
== '.') {
continue;
}
$file = new \stdClass();
$this->attachData($file, $info, $folder);
if (!$file->dir) {
if ($this->filter && !preg_match("/" .
$this->filter . "/i", $file->filename)) {
continue;
}
$file->isInCustom = false;
if ($isStream) {
$stream = explode('://', $folder);
$stream = array_shift($stream) .
'://';
$customLocation = $locator->findResource($stream,
true, true);
if (substr($info->getPathname(), 0,
strlen($customLocation)) === $customLocation) {
$file->isInCustom = true;
}
}
$files->append($file);
}
}
$files->asort();
return $files;
}
public function subfolder()
{
$response = [];
$response['html'] = 'subfolder';
return new JsonResponse($response);
}
public function displayFile()
{
$path = implode('/', func_get_args());
$this->doDownload($path, false);
}
protected function doDownload($path, $download)
{
if (!$path) {
throw new \RuntimeException('No file specified',
400);
}
// TODO: handle streams
$targetPath = GANTRY5_ROOT . '/' . $path;
if (!file_exists($targetPath)) {
throw new \RuntimeException(sprintf('File not found:
%s', $path), 404);
}
$hash = md5_file($path);
// Handle 304 Not Modified
if
(isset($this->request->server['HTTP_IF_NONE_MATCH'])) {
$etag =
stripslashes($this->request->server['HTTP_IF_NONE_MATCH']);
if ($etag == $hash) {
header('Last-Modified: ' . gmdate('D, d M Y
H:i:s', filemtime($path)) . ' GMT', true, 304);
// Give fast response.
flush();
exit();
}
}
// Set file headers.
header('ETag: ' . $hash);
header('Pragma: public');
header('Last-Modified: ' . gmdate('D, d M Y
H:i:s', filemtime($path)) . ' GMT');
// Get the image file information.
$info = getimagesize($path);
$isImage = (bool)$info;
if (!$download && $isImage) {
$fileType = $info['mime'];
// Force re-validate.
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0,
pre-check=0');
header('Content-type: ' . $fileType);
header('Content-Disposition: inline; filename="'
. basename($path) . '"');
} else {
// Force file download.
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0,
pre-check=0');
header('Content-Description: File Transfer');
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream');
header('Content-Type: application/download');
header('Content-Disposition: attachment;
filename="' . basename($path) . '"');
}
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($path));
flush();
// Output the file contents.
@readfile($path);
flush();
exit();
}
public function downloadFile()
{
$path = implode('/', func_get_args());
$this->doDownload($path, true);
}
public function upload()
{
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
$path = implode('/', func_get_args());
if (base64_decode($path, true) !== false) {
$path = urldecode(base64_decode($path));
}
$stream = explode('://', $path);
$scheme = $stream[0];
$isStream = $locator->schemeExists($scheme);
if ($isStream) {
$targetPath = dirname($locator->findResource($path, true,
true));
} else {
$targetPath = dirname(GANTRY5_ROOT . '/' . $path);
}
if (!isset($_FILES['file']['error']) ||
is_array($_FILES['file']['error'])) {
throw new \RuntimeException('No file sent', 400);
}
// Check $_FILES['file']['error'] value.
switch ($_FILES['file']['error']) {
case UPLOAD_ERR_OK:
break;
case UPLOAD_ERR_NO_FILE:
throw new \RuntimeException('No file sent', 400);
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
throw new \RuntimeException('Exceeded filesize
limit.', 400);
default:
throw new \RuntimeException('Unkown errors',
400);
}
$maxSize =
$this->returnBytes(min(ini_get('post_max_size'),
ini_get('upload_max_filesize')));
if ($_FILES['file']['size'] > $maxSize) {
throw new \RuntimeException('Exceeded filesize limit. File
is ' . $_FILES['file']['size'] . ', maximum
allowed is ' . $maxSize, 400);
}
// Check extension
$fileParts = pathinfo($_FILES['file']['name']);
$fileExt = strtolower($fileParts['extension']);
// TODO: check if download is of supported type.
// Upload it
$destination = sprintf('%s/%s', $targetPath,
$_FILES['file']['name']);
$destination = preg_replace('#//#', '/',
$destination);
Folder::create($targetPath);
if
(!move_uploaded_file($_FILES['file']['tmp_name'],
$destination)) {
throw new \RuntimeException('Failed to move uploaded
file.', 500);
}
$finfo = new \stdClass();
$this->attachData($finfo, new \SplFileInfo($destination),
$targetPath);
return new JsonResponse(['success' => 'File
uploaded successfully', 'finfo' => $finfo,
'url' => $path]);
}
protected function returnBytes($size_str)
{
switch (strtolower(substr($size_str, -1))) {
case 'm':
case 'mb':
return (int)$size_str * 1048576;
case 'k':
case 'kb':
return (int)$size_str * 1024;
case 'g':
case 'gb':
return (int)$size_str * 1073741824;
default:
return $size_str;
}
}
public function delete()
{
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
$path = implode('/', func_get_args());
if (base64_decode($path, true) !== false) {
$path = urldecode(base64_decode($path));
}
$stream = explode('://', $path);
$scheme = $stream[0];
if (!$path) {
throw new \RuntimeException('No file specified for
delete', 400);
}
$isStream = $locator->schemeExists($scheme);
if ($isStream) {
$targetPath = $locator->findResource($path, true, true);
} else {
$targetPath = GANTRY5_ROOT . '/' . $path;
}
$file = File::instance($targetPath);
if (!$file->exists()) {
throw new \RuntimeException(sprintf('File not found:
%s', $targetPath), 404);
}
try {
$file->delete();
} catch (\Exception $e) {
throw new \RuntimeException(sprintf('File could not be
deleted: %s', $targetPath), 500);
}
$file->free();
return new JsonResponse(['success', 'File deleted:
' . $targetPath]);
}
private function isStream($folder)
{
return $folder instanceof UniformResourceIterator ||
strpos($folder, '://');
}
}
PK���[��l�
�
$Admin/Controller/Json/Fontpicker.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Json;
use Gantry\Component\Admin\JsonController;
use Gantry\Component\Response\JsonResponse;
use RocketTheme\Toolbox\File\JsonFile;
class Fontpicker extends JsonController
{
protected $google_fonts =
'gantry-admin://js/google-fonts.json';
protected $httpVerbs = [
'GET' => [
'/' => 'index'
]
];
public function index()
{
$this->params['fonts'] = $this->loadGoogleFonts();
$this->params['variantsMap'] =
$this->variantsMap();
$response = [
'html' =>
$this->render('@gantry-admin/ajax/fontpicker.html.twig',
$this->params)
];
return new JsonResponse($response);
}
public function loadGoogleFonts()
{
$data = new \stdClass();
$file = JsonFile::instance($this->google_fonts);
$fonts = $file->content()['items'];
$file->free();
$data->categories = [];
$data->subsets = [];
// create list of unique categories and subsets
array_walk($fonts, function (&$item) use ($data) {
if (!in_array($item->category, $data->categories)) {
$data->categories[] = $item->category;
}
$data->subsets = array_unique(array_merge($data->subsets,
$item->subsets));
});
asort($data->categories);
asort($data->subsets);
$data->families = $fonts;
$data->local_families = $this->loadLocalFonts();
if (count($data->local_families)) {
array_unshift($data->categories, 'local-fonts');
}
$data->count = count($data->families);
return $data;
}
public function loadLocalFonts()
{
$local_fonts =
$this->container['theme']->details()->get('configuration.fonts',
[]);
$map = [];
foreach ($local_fonts as $name => $variants) {
if (is_array($variants)) {
$list = array_keys($variants);
} else {
$list = ['regular'];
}
$map[] = ['family' => $name, 'variants'
=> $list, 'category' => 'local-fonts'];
}
return $map;
}
protected function variantsMap()
{
return [
'100' => 'Thin 100',
'100italic' => 'Thin 100 Italic',
'200' => 'Extra-Light 200',
'200italic' => 'Extra-Light 200 Italic',
'300' => 'Light 300',
'300italic' => 'Light 300 Italic',
'400' => 'Normal 400',
'regular' => 'Normal 400',
'400italic' => 'Normal 400 Italic',
'italic' => 'Normal 400 Italic',
'500' => 'Medium 500',
'500italic' => 'Medium 500 Italic',
'600' => 'Semi-Bold 600',
'600italic' => 'Semi-Bold 600 Italic',
'700' => 'Bold 700',
'700italic' => 'Bold 700 Italic',
'800' => 'Extra-Bold 800',
'800italic' => 'Extra-Bold 800 Italic',
'900' => 'Ultra-Bold 900',
'900italic' => 'Ultra-Bold 900 Italic'
];
}
}
PK���[�u#S�F�FAdmin/Controller/Json/Icons.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Json;
use Gantry\Component\Admin\JsonController;
use Gantry\Component\Response\JsonResponse;
class Icons extends JsonController
{
public function index()
{
$response = [];
// Font Awesome Icons list [v4.7.0 - 730 icons]
// NOTE: To get an updated list of icons:
// 1. Go to: http://fontawesome.io/icons/
// 2. Open Console in Deveveloper Tools
// 3. Type this JS snippet: var list = [];
document.querySelectorAll('.fontawesome-icon-list
i').forEach(function(icon, index){ var name =
icon.className.replace(/^fa\s/, ''); list.push(name); }); var
output = '$list = ["' + list.join('",
"') + '"];'; console.log(output); copy(output);
console.info('The output has been copied to the clipboard, you can now
CMD + V / CTRL + V to update the icons variable');
// 4. Press Enter and replace the line below
$list = ["fa-address-book",
"fa-address-book-o", "fa-address-card",
"fa-address-card-o", "fa-bandcamp",
"fa-bath", "fa-bathtub",
"fa-drivers-license", "fa-drivers-license-o",
"fa-eercast", "fa-envelope-open",
"fa-envelope-open-o", "fa-etsy",
"fa-free-code-camp", "fa-grav",
"fa-handshake-o", "fa-id-badge",
"fa-id-card", "fa-id-card-o", "fa-imdb",
"fa-linode", "fa-meetup", "fa-microchip",
"fa-podcast", "fa-quora", "fa-ravelry",
"fa-s15", "fa-shower", "fa-snowflake-o",
"fa-superpowers", "fa-telegram",
"fa-thermometer", "fa-thermometer-0",
"fa-thermometer-1", "fa-thermometer-2",
"fa-thermometer-3", "fa-thermometer-4",
"fa-thermometer-empty", "fa-thermometer-full",
"fa-thermometer-half", "fa-thermometer-quarter",
"fa-thermometer-three-quarters", "fa-times-rectangle",
"fa-times-rectangle-o", "fa-user-circle",
"fa-user-circle-o", "fa-user-o", "fa-vcard",
"fa-vcard-o", "fa-window-close",
"fa-window-close-o", "fa-window-maximize",
"fa-window-minimize", "fa-window-restore",
"fa-wpexplorer", "fa-address-book",
"fa-address-book-o", "fa-address-card",
"fa-address-card-o", "fa-adjust",
"fa-american-sign-language-interpreting", "fa-anchor",
"fa-archive", "fa-area-chart", "fa-arrows",
"fa-arrows-h", "fa-arrows-v",
"fa-asl-interpreting",
"fa-assistive-listening-systems", "fa-asterisk",
"fa-at", "fa-audio-description",
"fa-automobile", "fa-balance-scale",
"fa-ban", "fa-bank", "fa-bar-chart",
"fa-bar-chart-o", "fa-barcode", "fa-bars",
"fa-bath", "fa-bathtub", "fa-battery",
"fa-battery-0", "fa-battery-1",
"fa-battery-2", "fa-battery-3",
"fa-battery-4", "fa-battery-empty",
"fa-battery-full", "fa-battery-half",
"fa-battery-quarter", "fa-battery-three-quarters",
"fa-bed", "fa-beer", "fa-bell",
"fa-bell-o", "fa-bell-slash",
"fa-bell-slash-o", "fa-bicycle",
"fa-binoculars", "fa-birthday-cake",
"fa-blind", "fa-bluetooth", "fa-bluetooth-b",
"fa-bolt", "fa-bomb", "fa-book",
"fa-bookmark", "fa-bookmark-o", "fa-braille",
"fa-briefcase", "fa-bug", "fa-building",
"fa-building-o", "fa-bullhorn",
"fa-bullseye", "fa-bus", "fa-cab",
"fa-calculator", "fa-calendar",
"fa-calendar-check-o", "fa-calendar-minus-o",
"fa-calendar-o", "fa-calendar-plus-o",
"fa-calendar-times-o", "fa-camera",
"fa-camera-retro", "fa-car",
"fa-caret-square-o-down", "fa-caret-square-o-left",
"fa-caret-square-o-right", "fa-caret-square-o-up",
"fa-cart-arrow-down", "fa-cart-plus",
"fa-cc", "fa-certificate", "fa-check",
"fa-check-circle", "fa-check-circle-o",
"fa-check-square", "fa-check-square-o",
"fa-child", "fa-circle", "fa-circle-o",
"fa-circle-o-notch", "fa-circle-thin",
"fa-clock-o", "fa-clone", "fa-close",
"fa-cloud", "fa-cloud-download",
"fa-cloud-upload", "fa-code", "fa-code-fork",
"fa-coffee", "fa-cog", "fa-cogs",
"fa-comment", "fa-comment-o",
"fa-commenting", "fa-commenting-o",
"fa-comments", "fa-comments-o", "fa-compass",
"fa-copyright", "fa-creative-commons",
"fa-credit-card", "fa-credit-card-alt",
"fa-crop", "fa-crosshairs", "fa-cube",
"fa-cubes", "fa-cutlery", "fa-dashboard",
"fa-database", "fa-deaf", "fa-deafness",
"fa-desktop", "fa-diamond",
"fa-dot-circle-o", "fa-download",
"fa-drivers-license", "fa-drivers-license-o",
"fa-edit", "fa-ellipsis-h", "fa-ellipsis-v",
"fa-envelope", "fa-envelope-o",
"fa-envelope-open", "fa-envelope-open-o",
"fa-envelope-square", "fa-eraser",
"fa-exchange", "fa-exclamation",
"fa-exclamation-circle", "fa-exclamation-triangle",
"fa-external-link", "fa-external-link-square",
"fa-eye", "fa-eye-slash", "fa-eyedropper",
"fa-fax", "fa-feed", "fa-female",
"fa-fighter-jet", "fa-file-archive-o",
"fa-file-audio-o", "fa-file-code-o",
"fa-file-excel-o", "fa-file-image-o",
"fa-file-movie-o", "fa-file-pdf-o",
"fa-file-photo-o", "fa-file-picture-o",
"fa-file-powerpoint-o", "fa-file-sound-o",
"fa-file-video-o", "fa-file-word-o",
"fa-file-zip-o", "fa-film", "fa-filter",
"fa-fire", "fa-fire-extinguisher", "fa-flag",
"fa-flag-checkered", "fa-flag-o", "fa-flash",
"fa-flask", "fa-folder", "fa-folder-o",
"fa-folder-open", "fa-folder-open-o",
"fa-frown-o", "fa-futbol-o", "fa-gamepad",
"fa-gavel", "fa-gear", "fa-gears",
"fa-gift", "fa-glass", "fa-globe",
"fa-graduation-cap", "fa-group",
"fa-hand-grab-o", "fa-hand-lizard-o",
"fa-hand-paper-o", "fa-hand-peace-o",
"fa-hand-pointer-o", "fa-hand-rock-o",
"fa-hand-scissors-o", "fa-hand-spock-o",
"fa-hand-stop-o", "fa-handshake-o",
"fa-hard-of-hearing", "fa-hashtag",
"fa-hdd-o", "fa-headphones", "fa-heart",
"fa-heart-o", "fa-heartbeat", "fa-history",
"fa-home", "fa-hotel", "fa-hourglass",
"fa-hourglass-1", "fa-hourglass-2",
"fa-hourglass-3", "fa-hourglass-end",
"fa-hourglass-half", "fa-hourglass-o",
"fa-hourglass-start", "fa-i-cursor",
"fa-id-badge", "fa-id-card", "fa-id-card-o",
"fa-image", "fa-inbox", "fa-industry",
"fa-info", "fa-info-circle",
"fa-institution", "fa-key", "fa-keyboard-o",
"fa-language", "fa-laptop", "fa-leaf",
"fa-legal", "fa-lemon-o", "fa-level-down",
"fa-level-up", "fa-life-bouy",
"fa-life-buoy", "fa-life-ring",
"fa-life-saver", "fa-lightbulb-o",
"fa-line-chart", "fa-location-arrow",
"fa-lock", "fa-low-vision", "fa-magic",
"fa-magnet", "fa-mail-forward",
"fa-mail-reply", "fa-mail-reply-all",
"fa-male", "fa-map", "fa-map-marker",
"fa-map-o", "fa-map-pin", "fa-map-signs",
"fa-meh-o", "fa-microchip", "fa-microphone",
"fa-microphone-slash", "fa-minus",
"fa-minus-circle", "fa-minus-square",
"fa-minus-square-o", "fa-mobile",
"fa-mobile-phone", "fa-money", "fa-moon-o",
"fa-mortar-board", "fa-motorcycle",
"fa-mouse-pointer", "fa-music", "fa-navicon",
"fa-newspaper-o", "fa-object-group",
"fa-object-ungroup", "fa-paint-brush",
"fa-paper-plane", "fa-paper-plane-o",
"fa-paw", "fa-pencil", "fa-pencil-square",
"fa-pencil-square-o", "fa-percent",
"fa-phone", "fa-phone-square", "fa-photo",
"fa-picture-o", "fa-pie-chart", "fa-plane",
"fa-plug", "fa-plus", "fa-plus-circle",
"fa-plus-square", "fa-plus-square-o",
"fa-podcast", "fa-power-off", "fa-print",
"fa-puzzle-piece", "fa-qrcode",
"fa-question", "fa-question-circle",
"fa-question-circle-o", "fa-quote-left",
"fa-quote-right", "fa-random", "fa-recycle",
"fa-refresh", "fa-registered", "fa-remove",
"fa-reorder", "fa-reply", "fa-reply-all",
"fa-retweet", "fa-road", "fa-rocket",
"fa-rss", "fa-rss-square", "fa-s15",
"fa-search", "fa-search-minus",
"fa-search-plus", "fa-send", "fa-send-o",
"fa-server", "fa-share", "fa-share-alt",
"fa-share-alt-square", "fa-share-square",
"fa-share-square-o", "fa-shield", "fa-ship",
"fa-shopping-bag", "fa-shopping-basket",
"fa-shopping-cart", "fa-shower",
"fa-sign-in", "fa-sign-language",
"fa-sign-out", "fa-signal", "fa-signing",
"fa-sitemap", "fa-sliders", "fa-smile-o",
"fa-snowflake-o", "fa-soccer-ball-o",
"fa-sort", "fa-sort-alpha-asc",
"fa-sort-alpha-desc", "fa-sort-amount-asc",
"fa-sort-amount-desc", "fa-sort-asc",
"fa-sort-desc", "fa-sort-down",
"fa-sort-numeric-asc", "fa-sort-numeric-desc",
"fa-sort-up", "fa-space-shuttle",
"fa-spinner", "fa-spoon", "fa-square",
"fa-square-o", "fa-star", "fa-star-half",
"fa-star-half-empty", "fa-star-half-full",
"fa-star-half-o", "fa-star-o",
"fa-sticky-note", "fa-sticky-note-o",
"fa-street-view", "fa-suitcase", "fa-sun-o",
"fa-support", "fa-tablet", "fa-tachometer",
"fa-tag", "fa-tags", "fa-tasks",
"fa-taxi", "fa-television", "fa-terminal",
"fa-thermometer", "fa-thermometer-0",
"fa-thermometer-1", "fa-thermometer-2",
"fa-thermometer-3", "fa-thermometer-4",
"fa-thermometer-empty", "fa-thermometer-full",
"fa-thermometer-half", "fa-thermometer-quarter",
"fa-thermometer-three-quarters", "fa-thumb-tack",
"fa-thumbs-down", "fa-thumbs-o-down",
"fa-thumbs-o-up", "fa-thumbs-up",
"fa-ticket", "fa-times", "fa-times-circle",
"fa-times-circle-o", "fa-times-rectangle",
"fa-times-rectangle-o", "fa-tint",
"fa-toggle-down", "fa-toggle-left",
"fa-toggle-off", "fa-toggle-on",
"fa-toggle-right", "fa-toggle-up",
"fa-trademark", "fa-trash", "fa-trash-o",
"fa-tree", "fa-trophy", "fa-truck",
"fa-tty", "fa-tv", "fa-umbrella",
"fa-universal-access", "fa-university",
"fa-unlock", "fa-unlock-alt", "fa-unsorted",
"fa-upload", "fa-user", "fa-user-circle",
"fa-user-circle-o", "fa-user-o",
"fa-user-plus", "fa-user-secret",
"fa-user-times", "fa-users", "fa-vcard",
"fa-vcard-o", "fa-video-camera",
"fa-volume-control-phone", "fa-volume-down",
"fa-volume-off", "fa-volume-up",
"fa-warning", "fa-wheelchair",
"fa-wheelchair-alt", "fa-wifi",
"fa-window-close", "fa-window-close-o",
"fa-window-maximize", "fa-window-minimize",
"fa-window-restore", "fa-wrench",
"fa-american-sign-language-interpreting",
"fa-asl-interpreting",
"fa-assistive-listening-systems",
"fa-audio-description", "fa-blind",
"fa-braille", "fa-cc", "fa-deaf",
"fa-deafness", "fa-hard-of-hearing",
"fa-low-vision", "fa-question-circle-o",
"fa-sign-language", "fa-signing", "fa-tty",
"fa-universal-access", "fa-volume-control-phone",
"fa-wheelchair", "fa-wheelchair-alt",
"fa-hand-grab-o", "fa-hand-lizard-o",
"fa-hand-o-down", "fa-hand-o-left",
"fa-hand-o-right", "fa-hand-o-up",
"fa-hand-paper-o", "fa-hand-peace-o",
"fa-hand-pointer-o", "fa-hand-rock-o",
"fa-hand-scissors-o", "fa-hand-spock-o",
"fa-hand-stop-o", "fa-thumbs-down",
"fa-thumbs-o-down", "fa-thumbs-o-up",
"fa-thumbs-up", "fa-ambulance",
"fa-automobile", "fa-bicycle", "fa-bus",
"fa-cab", "fa-car", "fa-fighter-jet",
"fa-motorcycle", "fa-plane", "fa-rocket",
"fa-ship", "fa-space-shuttle", "fa-subway",
"fa-taxi", "fa-train", "fa-truck",
"fa-wheelchair", "fa-wheelchair-alt",
"fa-genderless", "fa-intersex", "fa-mars",
"fa-mars-double", "fa-mars-stroke",
"fa-mars-stroke-h", "fa-mars-stroke-v",
"fa-mercury", "fa-neuter", "fa-transgender",
"fa-transgender-alt", "fa-venus",
"fa-venus-double", "fa-venus-mars",
"fa-file", "fa-file-archive-o",
"fa-file-audio-o", "fa-file-code-o",
"fa-file-excel-o", "fa-file-image-o",
"fa-file-movie-o", "fa-file-o",
"fa-file-pdf-o", "fa-file-photo-o",
"fa-file-picture-o", "fa-file-powerpoint-o",
"fa-file-sound-o", "fa-file-text",
"fa-file-text-o", "fa-file-video-o",
"fa-file-word-o", "fa-file-zip-o",
"fa-circle-o-notch", "fa-cog", "fa-gear",
"fa-refresh", "fa-spinner",
"fa-check-square", "fa-check-square-o",
"fa-circle", "fa-circle-o",
"fa-dot-circle-o", "fa-minus-square",
"fa-minus-square-o", "fa-plus-square",
"fa-plus-square-o", "fa-square",
"fa-square-o", "fa-cc-amex",
"fa-cc-diners-club", "fa-cc-discover",
"fa-cc-jcb", "fa-cc-mastercard",
"fa-cc-paypal", "fa-cc-stripe", "fa-cc-visa",
"fa-credit-card", "fa-credit-card-alt",
"fa-google-wallet", "fa-paypal",
"fa-area-chart", "fa-bar-chart",
"fa-bar-chart-o", "fa-line-chart",
"fa-pie-chart", "fa-bitcoin", "fa-btc",
"fa-cny", "fa-dollar", "fa-eur",
"fa-euro", "fa-gbp", "fa-gg",
"fa-gg-circle", "fa-ils", "fa-inr",
"fa-jpy", "fa-krw", "fa-money",
"fa-rmb", "fa-rouble", "fa-rub",
"fa-ruble", "fa-rupee", "fa-shekel",
"fa-sheqel", "fa-try", "fa-turkish-lira",
"fa-usd", "fa-won", "fa-yen",
"fa-align-center", "fa-align-justify",
"fa-align-left", "fa-align-right", "fa-bold",
"fa-chain", "fa-chain-broken",
"fa-clipboard", "fa-columns", "fa-copy",
"fa-cut", "fa-dedent", "fa-eraser",
"fa-file", "fa-file-o", "fa-file-text",
"fa-file-text-o", "fa-files-o",
"fa-floppy-o", "fa-font", "fa-header",
"fa-indent", "fa-italic", "fa-link",
"fa-list", "fa-list-alt", "fa-list-ol",
"fa-list-ul", "fa-outdent", "fa-paperclip",
"fa-paragraph", "fa-paste", "fa-repeat",
"fa-rotate-left", "fa-rotate-right",
"fa-save", "fa-scissors", "fa-strikethrough",
"fa-subscript", "fa-superscript", "fa-table",
"fa-text-height", "fa-text-width", "fa-th",
"fa-th-large", "fa-th-list", "fa-underline",
"fa-undo", "fa-unlink",
"fa-angle-double-down", "fa-angle-double-left",
"fa-angle-double-right", "fa-angle-double-up",
"fa-angle-down", "fa-angle-left",
"fa-angle-right", "fa-angle-up",
"fa-arrow-circle-down", "fa-arrow-circle-left",
"fa-arrow-circle-o-down", "fa-arrow-circle-o-left",
"fa-arrow-circle-o-right", "fa-arrow-circle-o-up",
"fa-arrow-circle-right", "fa-arrow-circle-up",
"fa-arrow-down", "fa-arrow-left",
"fa-arrow-right", "fa-arrow-up", "fa-arrows",
"fa-arrows-alt", "fa-arrows-h",
"fa-arrows-v", "fa-caret-down",
"fa-caret-left", "fa-caret-right",
"fa-caret-square-o-down", "fa-caret-square-o-left",
"fa-caret-square-o-right", "fa-caret-square-o-up",
"fa-caret-up", "fa-chevron-circle-down",
"fa-chevron-circle-left", "fa-chevron-circle-right",
"fa-chevron-circle-up", "fa-chevron-down",
"fa-chevron-left", "fa-chevron-right",
"fa-chevron-up", "fa-exchange",
"fa-hand-o-down", "fa-hand-o-left",
"fa-hand-o-right", "fa-hand-o-up",
"fa-long-arrow-down", "fa-long-arrow-left",
"fa-long-arrow-right", "fa-long-arrow-up",
"fa-toggle-down", "fa-toggle-left",
"fa-toggle-right", "fa-toggle-up",
"fa-arrows-alt", "fa-backward",
"fa-compress", "fa-eject", "fa-expand",
"fa-fast-backward", "fa-fast-forward",
"fa-forward", "fa-pause", "fa-pause-circle",
"fa-pause-circle-o", "fa-play",
"fa-play-circle", "fa-play-circle-o",
"fa-random", "fa-step-backward",
"fa-step-forward", "fa-stop",
"fa-stop-circle", "fa-stop-circle-o",
"fa-youtube-play", "fa-500px", "fa-adn",
"fa-amazon", "fa-android", "fa-angellist",
"fa-apple", "fa-bandcamp", "fa-behance",
"fa-behance-square", "fa-bitbucket",
"fa-bitbucket-square", "fa-bitcoin",
"fa-black-tie", "fa-bluetooth",
"fa-bluetooth-b", "fa-btc", "fa-buysellads",
"fa-cc-amex", "fa-cc-diners-club",
"fa-cc-discover", "fa-cc-jcb",
"fa-cc-mastercard", "fa-cc-paypal",
"fa-cc-stripe", "fa-cc-visa", "fa-chrome",
"fa-codepen", "fa-codiepie",
"fa-connectdevelop", "fa-contao", "fa-css3",
"fa-dashcube", "fa-delicious",
"fa-deviantart", "fa-digg", "fa-dribbble",
"fa-dropbox", "fa-drupal", "fa-edge",
"fa-eercast", "fa-empire", "fa-envira",
"fa-etsy", "fa-expeditedssl", "fa-fa",
"fa-facebook", "fa-facebook-f",
"fa-facebook-official", "fa-facebook-square",
"fa-firefox", "fa-first-order", "fa-flickr",
"fa-font-awesome", "fa-fonticons",
"fa-fort-awesome", "fa-forumbee",
"fa-foursquare", "fa-free-code-camp",
"fa-ge", "fa-get-pocket", "fa-gg",
"fa-gg-circle", "fa-git", "fa-git-square",
"fa-github", "fa-github-alt",
"fa-github-square", "fa-gitlab", "fa-gittip",
"fa-glide", "fa-glide-g", "fa-google",
"fa-google-plus", "fa-google-plus-circle",
"fa-google-plus-official", "fa-google-plus-square",
"fa-google-wallet", "fa-gratipay", "fa-grav",
"fa-hacker-news", "fa-houzz", "fa-html5",
"fa-imdb", "fa-instagram",
"fa-internet-explorer", "fa-ioxhost",
"fa-joomla", "fa-jsfiddle", "fa-lastfm",
"fa-lastfm-square", "fa-leanpub",
"fa-linkedin", "fa-linkedin-square",
"fa-linode", "fa-linux", "fa-maxcdn",
"fa-meanpath", "fa-medium", "fa-meetup",
"fa-mixcloud", "fa-modx", "fa-odnoklassniki",
"fa-odnoklassniki-square", "fa-opencart",
"fa-openid", "fa-opera", "fa-optin-monster",
"fa-pagelines", "fa-paypal", "fa-pied-piper",
"fa-pied-piper-alt", "fa-pied-piper-pp",
"fa-pinterest", "fa-pinterest-p",
"fa-pinterest-square", "fa-product-hunt",
"fa-qq", "fa-quora", "fa-ra",
"fa-ravelry", "fa-rebel", "fa-reddit",
"fa-reddit-alien", "fa-reddit-square",
"fa-renren", "fa-resistance", "fa-safari",
"fa-scribd", "fa-sellsy", "fa-share-alt",
"fa-share-alt-square", "fa-shirtsinbulk",
"fa-simplybuilt", "fa-skyatlas", "fa-skype",
"fa-slack", "fa-slideshare", "fa-snapchat",
"fa-snapchat-ghost", "fa-snapchat-square",
"fa-soundcloud", "fa-spotify",
"fa-stack-exchange", "fa-stack-overflow",
"fa-steam", "fa-steam-square",
"fa-stumbleupon", "fa-stumbleupon-circle",
"fa-superpowers", "fa-telegram",
"fa-tencent-weibo", "fa-themeisle",
"fa-trello", "fa-tripadvisor", "fa-tumblr",
"fa-tumblr-square", "fa-twitch",
"fa-twitter", "fa-twitter-square", "fa-usb",
"fa-viacoin", "fa-viadeo",
"fa-viadeo-square", "fa-vimeo",
"fa-vimeo-square", "fa-vine", "fa-vk",
"fa-wechat", "fa-weibo", "fa-weixin",
"fa-whatsapp", "fa-wikipedia-w",
"fa-windows", "fa-wordpress",
"fa-wpbeginner", "fa-wpexplorer",
"fa-wpforms", "fa-xing", "fa-xing-square",
"fa-y-combinator", "fa-y-combinator-square",
"fa-yahoo", "fa-yc", "fa-yc-square",
"fa-yelp", "fa-yoast", "fa-youtube",
"fa-youtube-play", "fa-youtube-square",
"fa-ambulance", "fa-h-square", "fa-heart",
"fa-heart-o", "fa-heartbeat",
"fa-hospital-o", "fa-medkit",
"fa-plus-square", "fa-stethoscope",
"fa-user-md", "fa-wheelchair",
"fa-wheelchair-alt"];
$options = [
'fw' => 'Fixed Width',
'spin' => 'Spinning',
'larger' => ['' => '- Size -
', 'lg' => 'Large', '2x' =>
'2x', '3x' => '3x', '4x' =>
'4x', '5x' => '5x'],
'rotation' => ['' => '- Rotation
-', 'flip-horizontal' => 'Horizontal Flip',
'flip-vertical' => 'Vertical Flip',
'rotate-90' => 'Rotate 90°', 'rotate-180'
=> 'Rotate 180°', 'rotate-270' => 'Rotate
270°']
];
$list = array_unique($list);
sort($list);
$response['html'] =
$this->render('@gantry-admin/ajax/icons.html.twig',
['icons' => $list, 'options' => $options,
'total' => count($list)]);
return new JsonResponse($response);
}
}
PK���[�DEL L
!Admin/Controller/Json/Layouts.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Json;
use Gantry\Component\Admin\JsonController;
use Gantry\Component\Config\BlueprintForm;
use Gantry\Component\Layout\Layout;
use Gantry\Component\Response\JsonResponse;
/**
* Class Layouts
* @package Gantry\Admin\Controller\Json
*/
class Layouts extends JsonController
{
protected $httpVerbs = [
'GET' => [
'/' => 'index',
'/*' => 'index',
'/particle' => 'particle'
],
'POST' => [
'/' => 'index',
'/*' => 'index',
'/particle' => 'particle'
]
];
public function index()
{
$path = implode('/', func_get_args());
$post = $this->request->request;
$outline = $post['outline'];
$type = $post['type'];
$subtype = $post['subtype'];
$inherit = $post['inherit'];
$clone = $post['mode'] === 'clone';
$id = $post['id'];
$this->container['outline'] = $outline;
$this->container['configuration'] = $outline;
$layout = Layout::instance($outline);
if ($inherit) {
$layout->inheritAll();
}
if ($path == 'list' &&
!$layout->isLayoutType($type)) {
$instance = $this->getParticleInstances($outline, $subtype,
null);
$id = $instance['selected'];
}
$item = $layout->find($id);
$type = isset($item->type) ? $item->type : $type;
$subtype = isset($item->subtype) ? $item->subtype : $subtype;
$item->attributes = isset($item->attributes) ? (array)
$item->attributes : [];
$block = $layout->block($id);
$block = isset($block->attributes) ? (array)
$block->attributes : [];
$params = [
'gantry' => $this->container,
'parent' => 'settings',
'route' =>
"configurations.{$outline}.settings",
'inherit' => $inherit ? $outline : null,
];
if ($layout->isLayoutType($type)) {
$name = $type;
$particle = false;
$defaults = [];
$blueprints =
BlueprintForm::instance("layout/{$name}.yaml",
'gantry-admin://blueprints');
} else {
$name = $subtype;
$particle = true;
$defaults =
$this->container['config']->get("particles.{$name}");
$item->attributes = $item->attributes + $defaults;
$blueprints =
$this->container['particles']->getBlueprintForm($name);
$blueprints->set('form/fields/_inherit',
['type' => 'gantry.inherit']);
}
$paramsParticle = [
'title' => isset($item->title) ?
$item->title : '',
'blueprints' =>
$blueprints->get('form'),
'item' => $item,
'data' => ['particles' =>
[$name => $item->attributes]],
'defaults' => ['particles' =>
[$name => $defaults]],
'prefix' => "particles.{$name}.",
'editable' => $particle,
'overrideable' => $particle,
'skip' => ['enabled']
] + $params;
$html['g-settings-particle'] =
$this->render('@gantry-admin/pages/configurations/layouts/particle-card.html.twig',
$paramsParticle);
$html['g-settings-block-attributes'] =
$this->renderBlockFields($block, $params);
if ($path == 'list') {
$html['g-inherit-particle'] =
$this->renderParticlesInput($inherit || $clone ? $outline : null,
$subtype, $post['selected']);
}
return new JsonResponse(['json' => $item,
'html' => $html]);
}
public function particle()
{
$post = $this->request->request;
$outline = $post['outline'];
$id = $post['id'];
$this->container['outline'] = $outline;
$this->container['configuration'] = $outline;
$layout = Layout::instance($outline);
$particle = clone $layout->find($id);
if (!isset($particle->type)) {
throw new \RuntimeException('Particle was not found from
the outline', 404);
}
$particle->block = $layout->block($id);
$name = $particle->subtype;
$prefix = "particles.{$name}";
$defaults = (array)
$this->container['config']->get($prefix);
$attributes = (array) $particle->attributes + $defaults;
$particleBlueprints =
$this->container['particles']->getBlueprintForm($name);
$particleBlueprints->set('form/fields/_inherit',
['type' => 'gantry.inherit']);
$blockBlueprints =
BlueprintForm::instance('layout/block.yaml',
'gantry-admin://blueprints');
// TODO: Use blueprints to merge configuration.
$particle->attributes = (object) $attributes;
$this->params['id'] = $name;
$this->params += [
'extra' => $blockBlueprints,
'item' => $particle,
'data' => ['particles' =>
[$name => $attributes]],
'defaults' => ['particles' =>
[$name => $defaults]],
'prefix' => "particles.{$name}.",
'particle' => $particleBlueprints,
'parent' => 'settings',
'route' =>
"configurations.{$outline}.settings",
'action' => str_replace('.',
'/', 'configurations.' . $outline .
'.layout.' . $prefix . '.validate'),
'skip' => ['enabled'],
'editable' => false,
'overrideable' => true,
];
$html =
$this->render('@gantry-admin/pages/configurations/layouts/particle-preview.html.twig',
$this->params);
return new JsonResponse(['html' => $html]);
}
/**
* Render block settings.
*
* @param array $block
* @param array $params
* @return string
*/
protected function renderBlockFields(array $block, array $params)
{
$blockBlueprints =
BlueprintForm::instance('layout/block.yaml',
'gantry-admin://blueprints');
$paramsBlock = [
'title' =>
$this->container['translator']->translate('GANTRY5_PLATFORM_BLOCK'),
'blueprints' => ['fields' =>
$blockBlueprints->get('form/fields/block_container/fields')],
'data' => ['block' => $block],
'prefix' => 'block.',
] + $params;
return
$this->render('@gantry-admin/forms/fields.html.twig',
$paramsBlock);
}
/**
* Gets the list of available particle instances for an outline
*
* @param string $outline
* @param string $particle
* @param string $selected
* @return string
*/
protected function getParticleInstances($outline, $particle, $selected)
{
$list = $outline ?
$this->container['outlines']->getParticleInstances($outline,
$particle, false) : [];
$selected = isset($list[$selected]) ? $selected : key($list);
return ['list' => $list, 'selected' =>
$selected];
}
/**
* Render input field for particle picker.
*
* @param string $outline
* @param string $particle
* @param string $selected
* @return string
*/
protected function renderParticlesInput($outline, $particle, $selected)
{
$instances = $this->getParticleInstances($outline, $particle,
$selected);
$params = [
'layout' => 'input',
'scope' => 'inherit.',
'field' => [
'name' => 'particle',
'type' => 'gantry.particles',
'id' => 'g-inherit-particle',
'outline' => $outline,
'particles' => $instances['list'],
'particle' => $particle
],
'value' => $instances['selected']
];
return
$this->render('@gantry-admin/forms/fields/gantry/particles.html.twig',
$params);
}
}
PK���[�e��))"Admin/Controller/Json/Particle.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Json;
use Gantry\Component\Admin\JsonController;
use Gantry\Component\Config\BlueprintSchema;
use Gantry\Component\Config\BlueprintForm;
use Gantry\Component\Config\Config;
use Gantry\Component\Response\JsonResponse;
class Particle extends JsonController
{
protected $httpVerbs = [
'GET' => [
'/' =>
'selectParticle',
'/module' => 'selectModule'
],
'POST' => [
'/' => 'undefined',
'/*' => 'particle',
'/*/validate' => 'validate',
],
'PUT' => [
'/*' => 'replace'
],
'PATCH' => [
'/*' => 'update'
],
'DELETE' => [
'/*' => 'destroy'
]
];
/**
* Return a modal for selecting a particle.
*
* @return string
*/
public function selectParticle()
{
$groups = [
'Particles' => ['particle' => []],
];
$particles = [
'position' => [],
'spacer' => [],
'system' => [],
'particle' => [],
];
$particles = array_replace($particles, $this->getParticles());
unset($particles['atom'],
$particles['position']);
foreach ($particles as &$group) {
asort($group);
}
foreach ($groups as $section => $children) {
foreach ($children as $key => $child) {
$groups[$section][$key] = $particles[$key];
}
}
$this->params['particles'] = $groups;
return new JsonResponse(['html' =>
$this->render('@gantry-admin/modals/particle-picker.html.twig',
$this->params)]);
}
/**
* Return a modal content for selecting module.
*
* @return mixed
*/
public function selectModule()
{
return new JsonResponse(['html' =>
$this->render('@gantry-admin/modals/module-picker.html.twig',
$this->params)]);
}
/**
* Return form for the particle (filled with data coming from POST).
*
* @param string $name
* @return mixed
*/
public function particle($name)
{
$data = $this->request->post['item'];
if ($data) {
$data = json_decode($data, true);
} else {
$data = $this->request->post->getArray();
}
// TODO: add support for other block types as well, like menu.
// $block = BlueprintForm::instance('layout/block.yaml',
'gantry-admin://blueprints');
$blueprints =
$this->container['particles']->getBlueprintForm($name);
// Load particle blueprints and default settings.
$validator = $this->loadBlueprints('menu');
$callable = function () use ($validator) {
return $validator;
};
// Create configuration from the defaults.
$item = new Config($data, $callable);
$item->def('type', 'particle');
$item->def('title',
$blueprints->get('name'));
$item->def('options.type',
$blueprints->get('type', 'particle'));
$item->def('options.particle', []);
$item->def('options.block', []);
$this->params += [
'item' => $item,
// 'block' => $block,
'data' => ['particles' =>
[$name => $item->options['particle']]],
'particle' => $blueprints,
'parent' => 'settings',
'prefix' => "particles.{$name}.",
'route' =>
"configurations.default.settings",
'action' =>
"particle/{$name}/validate"
];
return new JsonResponse(['html' =>
$this->render('@gantry-admin/modals/particle.html.twig',
$this->params)]);
}
/**
* Validate data for the particle.
*
* @param string $name
* @return JsonResponse
*/
public function validate($name)
{
// Load particle blueprints and default settings.
$validator = new BlueprintSchema;
$validator->embed('options',
$this->container['particles']->get($name));
$blueprints =
$this->container['particles']->getBlueprintForm($name);
// Create configuration from the defaults.
$data = new Config([],
function () use ($validator) {
return $validator;
}
);
$data->set('type', 'particle');
$data->set('particle', $name);
$data->set('title',
$this->request->post['title'] ?:
$blueprints->get('name'));
$data->set('options.particle',
$this->request->post->getArray("particles.{$name}"));
$data->def('options.particle.enabled', 1);
$block =
$this->request->post->getArray('block');
foreach ($block as $key => $param) {
if ($param === '') {
unset($block[$key]);
}
}
if ($block) {
$data->join('options.block', $block);
}
// TODO: validate
// Fill parameters to be passed to the template file.
$this->params['item'] = (object) $data->toArray();
return new JsonResponse(['item' =>
$data->toArray()]);
}
protected function getParticles()
{
$particles = $this->container['particles']->all();
$list = [];
foreach ($particles as $name => $particle) {
$type = isset($particle['type']) ?
$particle['type'] : 'particle';
$particleName = isset($particle['name']) ?
$particle['name'] : $name;
$particleIcon = isset($particle['icon']) ?
$particle['icon'] : null;
$list[$type][$name] = ['name' => $particleName,
'icon' => $particleIcon];
}
return $list;
}
/**
* Load blueprints.
*
* @param string $name
*
* @return BlueprintForm
*/
protected function loadBlueprints($name = 'menu')
{
return BlueprintForm::instance("menu/{$name}.yaml",
'gantry-admin://blueprints');
}
}
PK���[�P_�%%!Admin/Controller/Json/Unsaved.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin\Controller\Json;
use Gantry\Component\Admin\JsonController;
use Gantry\Component\Response\JsonResponse;
class Unsaved extends JsonController
{
protected $httpVerbs = [
'GET' => [
'/' => 'index'
]
];
public function index()
{
$response = ['html' =>
$this->render('@gantry-admin/ajax/unsaved.html.twig')];
return new JsonResponse($response);
}
}
PK���[譤��Admin/EventListener.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Admin;
use Gantry\Component\Layout\Layout;
use Gantry\Joomla\CacheHelper;
use Gantry\Joomla\Manifest;
use Gantry\Joomla\StyleHelper;
use Joomla\Registry\Registry;
use RocketTheme\Toolbox\Event\Event;
use RocketTheme\Toolbox\Event\EventSubscriberInterface;
use RocketTheme\Toolbox\File\IniFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class EventListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
'admin.init.theme' =>
['onAdminThemeInit', 0],
'admin.global.save' => ['onGlobalSave',
0],
'admin.styles.save' => ['onStylesSave',
0],
'admin.settings.save' =>
['onSettingsSave', 0],
'admin.layout.save' => ['onLayoutSave',
0],
'admin.assignments.save' =>
['onAssignmentsSave', 0],
'admin.menus.save' => ['onMenusSave', 0]
];
}
public function onAdminThemeInit(Event $event)
{
\JPluginHelper::importPlugin('gantry5');
// Trigger the onGantryThemeInit event.
$dispatcher = \JEventDispatcher::getInstance();
$dispatcher->trigger('onGantry5AdminInit',
['theme' => $event->theme]);
}
public function onGlobalSave(Event $event)
{
\JPluginHelper::importPlugin('gantry5');
// Trigger the onGantryThemeUpdateCss event.
$dispatcher = \JEventDispatcher::getInstance();
$dispatcher->trigger('onGantry5SaveConfig',
[$event->data]);
}
public function onStylesSave(Event $event)
{
\JPluginHelper::importPlugin('gantry5');
// Trigger the onGantryThemeUpdateCss event.
$dispatcher = \JEventDispatcher::getInstance();
$dispatcher->trigger('onGantry5UpdateCss',
['theme' => $event->theme]);
}
public function onSettingsSave(Event $event)
{
}
public function onLayoutSave(Event $event)
{
/** @var Layout $layout */
$layout = $event->layout;
if ($layout->name[0] !== '_' &&
$layout->name !== 'default') {
$preset = isset($layout->preset['name']) ?
$layout->preset['name'] : 'default';
// Update Joomla template style.
StyleHelper::update($layout->name, $preset);
}
$theme = $event->gantry['theme.name'];
$positions =
$event->gantry['outlines']->positions();
$positions['debug'] = 'Debug';
$manifest = new Manifest($theme);
$manifest->setPositions(array_keys($positions));
$manifest->save();
$translations = [];
foreach ($positions as $key => $translation) {
// Encode translation key in Joomla way.
$key = preg_replace('/[^A-Z0-9_\-]/', '_',
strtoupper("TPL_{$theme}_POSITION_{$key}"));
$translations[$key] = $translation;
}
/** @var UniformResourceLocator $locator */
$locator = $event->gantry['locator'];
$filename =
"gantry-theme://language/en-GB/en-GB.tpl_{$theme}_positions.ini";
$ini = IniFile::instance($locator->findResource($filename, true,
true));
$ini->save($translations);
$ini->free();
}
public function onAssignmentsSave(Event $event)
{
}
public function onMenusSave(Event $event)
{
$defaults = [
'id' => 0,
'layout' => 'list',
'target' => '_self',
'dropdown' => '',
'icon' => '',
'image' => '',
'subtitle' => '',
'icon_only' => false,
'visible' => true,
'group' => 0,
'columns' => [],
'link_title' => '',
'hash' => '',
'class' => ''
];
$gantry = $event->gantry;
$menu = $event->menu;
// Save global menu settings into Joomla.
/** @var \JTableMenuType $table */
$menuType = \JTable::getInstance('MenuType');
if (!$menuType->load(['menutype' =>
$event->resource])) {
throw new \RuntimeException("Saving menu failed: Menu type
{$event->resource} not found.", 400);
}
$options = [
'title' => $menu['settings.title'],
'description' =>
$menu['settings.description']
];
if ($gantry->authorize('menu.edit') &&
!$menuType->save($options)) {
throw new \RuntimeException('Saving menu failed: '.
$menuType->getError(), 400);
}
unset($menu['settings']);
/** @var \JTableMenu $table */
$table = \JTable::getInstance('menu');
foreach ($menu['items'] as $key => $item) {
$id = !empty($item['id']) ? (int)
$item['id'] : 0;
if ($id && $table->load($item['id'])) {
$params = new Registry($table->params);
// Menu item exists in Joomla, let's update it
instead.
unset($item['type'], $item['link']);
$item['id'] = (int) $id;
$title = $menu["items.{$key}.title"];
$browserNav = intval($menu["items.{$key}.target"]
=== '_blank');
$options = [
// Disabled as the option has different meaning in
Joomla than in Gantry, see issue #1656.
// 'menu-anchor_css' =>
$menu["items.{$key}.class"],
'menu_image' =>
$menu["items.{$key}.image"],
'menu_text' =>
intval(!$menu["items.{$key}.icon_only"]),
'menu_show' =>
intval($menu["items.{$key}.enabled"]),
];
$modified = false;
if ($table->title != $title) {
$table->title = $title;
$modified = true;
}
if ($table->browserNav != $browserNav) {
$table->browserNav = $browserNav;
$modified = true;
}
foreach ($options as $var => $value) {
if ($params->get($var) !== $value) {
$params->set($var, $value);
$modified = true;
}
}
if ($modified &&
$gantry->authorize('menu.edit')) {
$table->params = (string) $params;
if (!$table->check() || !$table->store()) {
throw new \RuntimeException("Failed to save
/{$key}: {$table->getError()}", 400);
}
}
// Avoid saving values which are also stored in Joomla.
unset($item['title'],
$item['anchor_class'], $item['image'],
$item['icon_only'], $item['target']);
if (version_compare(JVERSION, '3.5.1',
'>=')) {
unset($item['enabled']);
}
}
// Do not save default values.
foreach ($defaults as $var => $value) {
if (isset($item[$var]) && $item[$var] == $value) {
unset($item[$var]);
}
}
// Do not save derived values.
unset($item['path'], $item['alias'],
$item['parent_id'], $item['level'],
$item['group']);
// Particles have no link.
if (isset($item['type']) &&
$item['type'] === 'particle') {
unset($item['link']);
}
// Because of ordering we need to save all menu items,
including those from Joomla which have no data except id.
$event->menu["items.{$key}"] = $item;
}
// Clean the cache.
CacheHelper::cleanMenu();
}
}
PK���[uTQ'Admin/Page.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin;
use Gantry\Component\Config\BlueprintForm;
use Gantry\Component\Config\ConfigFileFinder;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Framework\Theme as SiteTheme;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Page
{
protected $container;
protected $files;
protected $blocks;
public function __construct($container)
{
$this->container = $container;
}
public function all()
{
if (!$this->blocks)
{
$files = $this->locateBlocks();
$this->blocks = [];
foreach ($files as $key => $fileArray) {
$filename = key($fileArray);
$file = CompiledYamlFile::instance(GANTRY5_ROOT .
'/' . $filename);
$this->blocks[$key] = $file->content();
$file->free();
}
}
return $this->blocks;
}
public function group()
{
$blocks = $this->all();
$list = [];
foreach ($blocks as $name => $setting) {
$type = isset($setting['type']) ?
$setting['type'] : '';
$list[$type][$name] = $setting;
}
return $this->sort($list);
}
public function get($id)
{
if ($this->blocks[$id]) {
return $this->blocks[$id];
}
$files = $this->locateBlocks();
if (empty($files[$id])) {
throw new \RuntimeException(sprintf("Settings for
'%s' not found.", $id), 404);
}
$filename = key($files[$id]);
$file = CompiledYamlFile::instance(GANTRY5_ROOT . '/' .
$filename);
$setting = $file->content();
$file->free();
return $setting;
}
/**
* @param string $id
* @return BlueprintForm
*/
public function getBlueprintForm($id)
{
return BlueprintForm::instance($id,
'gantry-blueprints://page');
}
protected function sort(array $blocks)
{
$list = [];
/** @var SiteTheme $theme */
$theme = $this->container['theme'];
$ordering = (array) $theme->details()['admin.page'];
if (!count($ordering)) {
$ordering = ['global' => ['head',
'assets', 'body', 'generics']];
}
ksort($blocks);
foreach ($ordering as $name => $order) {
if (isset($blocks[$name])) {
$list[$name] = $this->sortItems($blocks[$name], (array)
$order);
}
}
$list += $blocks;
return $list;
}
protected function sortItems(array $items, array $ordering)
{
$list = [];
ksort($items);
foreach ($ordering as $name) {
if (isset($items[$name])) {
$list[$name] = $items[$name];
}
}
$list += $items;
return $list;
}
protected function locateBlocks()
{
if (!$this->files) {
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
$paths =
$locator->findResources('gantry-blueprints://page');
$this->files = (new ConfigFileFinder)->listFiles($paths);
}
return $this->files;
}
}
PK���[�Ht���Admin/Particles.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin;
use Gantry\Component\Config\BlueprintForm;
use Gantry\Component\Config\ConfigFileFinder;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Framework\Theme as SiteTheme;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Particles
{
protected $container;
protected $files;
protected $particles;
public function __construct($container)
{
$this->container = $container;
}
public function overrides($outline, $particle = null)
{
if ($outline === 'default') {
return true;
}
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
if ($particle) {
// PHP 5.4
$resource =
$locator->findResources("gantry-theme://config/{$outline}/particles/{$particle}.yaml");
return !empty($resource);
}
// PHP 5.4
$resource =
$locator->findResources("gantry-theme://config/{$outline}/particles");
return !empty($resource);
}
public function all()
{
if (null === $this->particles) {
$platform = $this->container['platform'];
$files = $this->locateParticles();
$this->particles = [];
foreach ($files as $key => $fileArray) {
$filename = key($fileArray);
$file = CompiledYamlFile::instance(GANTRY5_ROOT .
'/' . $filename);
$particle = $file->content();
$file->free();
if (!isset($particle['dependencies']) ||
$platform->checkDependencies($particle['dependencies'])) {
$this->particles[$key] = $particle;
}
}
}
return $this->particles;
}
public function group($exclude = [])
{
$particles = $this->all();
$list = [];
foreach ($particles as $name => $particle) {
$type = isset($particle['type']) ?
$particle['type'] : 'particle';
if (in_array($type, $exclude)) {
continue;
}
if (in_array($type, ['spacer', 'system']))
{
$type = 'position';
}
$list[$type][$name] = $particle;
}
return $this->sort($list);
}
public function get($id)
{
if (isset($this->particles[$id])) {
return $this->particles[$id];
}
$files = $this->locateParticles();
if (empty($files[$id])) {
throw new \RuntimeException(sprintf("Settings for
'%s' not found.", $id), 404);
}
$filename = key($files[$id]);
$file = CompiledYamlFile::instance(GANTRY5_ROOT . '/' .
$filename);
$particle = $file->content();
$particle['subtype'] = $id; // TODO: can this be done
better or is it fine like that?
$file->free();
return $particle;
}
/**
* @param string $id
* @return BlueprintForm
*/
public function getBlueprintForm($id)
{
return BlueprintForm::instance($id,
'gantry-blueprints://particles');
}
protected function sort(array $blocks)
{
$list = [];
/** @var SiteTheme $theme */
$theme = $this->container['theme'];
$ordering = (array)
$theme->details()['admin.settings'] ?: [
'particle' => [],
'position' => ['position',
'spacer', 'messages', 'content'],
'atom' => []
];
ksort($blocks);
foreach ($ordering as $name => $order) {
if (isset($blocks[$name])) {
$list[$name] = $this->sortItems($blocks[$name], (array)
$order);
}
}
$list += $blocks;
return $list;
}
protected function sortItems(array $items, array $ordering)
{
$list = [];
ksort($items);
foreach ($ordering as $name) {
if (isset($items[$name])) {
$list[$name] = $items[$name];
}
}
$list += $items;
return $list;
}
protected function locateParticles()
{
if (!$this->files) {
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
$paths =
$locator->findResources('gantry-blueprints://particles');
$this->files = (new ConfigFileFinder)->listFiles($paths);
}
return $this->files;
}
}
PK���[�w�22Admin/Router.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Admin;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Component\Request\Request;
use Gantry\Component\Response\JsonResponse;
use Gantry\Component\Response\Response;
use Gantry\Component\Router\Router as BaseRouter;
use Gantry\Joomla\StyleHelper;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* Gantry administration router for Joomla.
*/
class Router extends BaseRouter
{
public function boot()
{
\JHtml::_('behavior.keepalive');
$app = \JFactory::getApplication();
$input = $app->input;
// TODO: Remove style variable.
$style = $input->getInt('style');
$theme = $input->getCmd('theme');
$path = array_filter(explode('/',
$input->getString('view', '')), function($var) {
return $var !== ''; });
$this->setTheme($theme, $style);
/** @var Request $request */
$request = $this->container['request'];
$this->method = $request->getMethod();
$this->path = $path ?:
(isset($this->container['theme.name']) ?
['configurations', true] : ['themes']);
$this->resource = array_shift($this->path);
$this->format = $input->getCmd('format',
'html');
$ajax = ($this->format == 'json');
$this->params = [
'user' => \JFactory::getUser(),
'ajax' => $ajax,
'location' => $this->resource,
'method' => $this->method,
'format' => $this->format,
'params' =>
$request->post->getJsonArray('params')
];
return $this;
}
public function setTheme($theme, $style)
{
if ($style) {
\JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_templates/tables');
$table = \JTable::getInstance('Style',
'TemplatesTable');
$table->load(['id' => $style,
'client_id' => 0]);
$theme = $table->template;
}
if (!$theme) {
$theme = StyleHelper::getDefaultStyle()->template;
}
$path = JPATH_SITE . '/templates/' . $theme;
if (!is_file("{$path}/gantry/theme.yaml")) {
$theme = null;
$this->container['streams']->register();
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
CompiledYamlFile::$defaultCachePath =
$locator->findResource('gantry-cache://theme/compiled/yaml',
true, true);
CompiledYamlFile::$defaultCaching =
$this->container['global']->get('compile_yaml',
1);
}
$this->container['base_url'] = \JUri::base(true) .
'/index.php?option=com_gantry5';
$this->container['ajax_suffix'] =
'&format=json';
$token = \JSession::getFormToken();
$this->container['routes'] = [
'1' =>
"&view=%s&theme={$theme}&{$token}=1",
'themes' => '&view=themes',
'picker/layouts' =>
"&view=layouts&theme={$theme}&{$token}=1",
];
if (!$theme) {
return $this;
}
$this->container['theme.path'] = $path;
$this->container['theme.name'] = $theme;
// Load language file for the template.
$languageFile = 'tpl_' . $theme;
$lang = \JFactory::getLanguage();
$lang->load($languageFile, JPATH_SITE)
|| $lang->load($languageFile, $path)
|| $lang->load($languageFile, $path, 'en-GB');
return $this;
}
protected function checkSecurityToken()
{
return \JSession::checkToken('get');
}
/**
* Send response to the client.
*
* @param Response $response
* @return string
*/
protected function send(Response $response)
{
$app = \JFactory::getApplication();
$document = \JFactory::getDocument();
$document->setCharset($response->charset);
$document->setMimeEncoding($response->mimeType);
// Output HTTP header.
$app->setHeader('Status', $response->getStatus());
$app->setHeader('Content-Type', $response->mimeType
. '; charset=' . $response->charset);
foreach ($response->getHeaders() as $key => $values) {
$replace = true;
foreach ($values as $value) {
$app->setHeader($key, $value, $replace);
$replace = false;
}
}
if ($response instanceof JsonResponse) {
$app->setHeader('Expires', 'Wed, 17 Aug 2005
00:00:00 GMT', true);
$app->setHeader('Last-Modified', gmdate('D, d
M Y H:i:s') . ' GMT', true);
$app->setHeader('Cache-Control', 'no-store,
no-cache, must-revalidate, post-check=0, pre-check=0', false);
$app->setHeader('Pragma', 'no-cache');
$app->sendHeaders();
}
// Output Gantry response.
echo $response;
if ($response instanceof JsonResponse) {
$app->close();
}
}
}
PK���[\��Ɵ
�
Admin/Styles.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin;
use Gantry\Component\Config\BlueprintForm;
use Gantry\Component\Config\ConfigFileFinder;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Framework\Theme as SiteTheme;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Styles
{
protected $container;
protected $files;
protected $blocks;
public function __construct($container)
{
$this->container = $container;
}
public function all()
{
if (!$this->blocks)
{
$files = $this->locateBlocks();
$this->blocks = [];
foreach ($files as $key => $fileArray) {
$filename = key($fileArray);
$file = CompiledYamlFile::instance(GANTRY5_ROOT .
'/' . $filename);
$this->blocks[$key] = $file->content();
$file->free();
}
}
return $this->blocks;
}
public function group()
{
$blocks = $this->all();
$list = [];
foreach ($blocks as $name => $style) {
$type = isset($style['type']) ?
$style['type'] : 'block';
$list[$type][$name] = $style;
}
return $this->sort($list);
}
public function get($id)
{
if ($this->blocks[$id]) {
return $this->blocks[$id];
}
$files = $this->locateBlocks();
if (empty($files[$id])) {
throw new \RuntimeException(sprintf("Settings for
'%s' not found.", $id), 404);
}
$filename = key($files[$id]);
$file = CompiledYamlFile::instance(GANTRY5_ROOT . '/' .
$filename);
$particle = $file->content();
$file->free();
return $particle;
}
/**
* @param string $id
* @return BlueprintForm
*/
public function getBlueprintForm($id)
{
return BlueprintForm::instance($id,
'gantry-blueprints://styles');
}
protected function sort(array $blocks)
{
$list = [];
/** @var SiteTheme $theme */
$theme = $this->container['theme'];
$ordering = (array) $theme->details()['admin.styles'];
ksort($blocks);
foreach ($ordering as $name => $order) {
if (isset($blocks[$name])) {
$list[$name] = $this->sortItems($blocks[$name], (array)
$order);
}
}
$list += $blocks;
return $list;
}
protected function sortItems(array $items, array $ordering)
{
$list = [];
ksort($items);
foreach ($ordering as $name) {
if (isset($items[$name])) {
$list[$name] = $items[$name];
}
}
$list += $items;
return $list;
}
protected function locateBlocks()
{
if (!$this->files) {
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
$paths =
$locator->findResources('gantry-blueprints://styles');
$this->files = (new ConfigFileFinder)->listFiles($paths);
}
return $this->files;
}
}
PK���[�Y�zppAdmin/Theme.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Admin;
use Gantry\Component\Config\CompiledConfig;
use Gantry\Component\Config\ConfigFileFinder;
use Gantry\Component\Filesystem\Folder;
use Gantry\Component\Theme\AbstractTheme;
use Gantry\Framework\Platform;
use RocketTheme\Toolbox\Event\Event;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Theme extends AbstractTheme
{
/**
* @see AbstractTheme::init()
*/
protected function init()
{
$gantry = static::gantry();
// Add particles, styles and defaults into DI.
$gantry['particles'] = function ($c) {
return new Particles($c);
};
$gantry['styles'] = function ($c) {
return new Styles($c);
};
$gantry['page'] = function ($c) {
return new Page($c);
};
$gantry['defaults'] = function($c) {
/** @var UniformResourceLocator $locator */
$locator = $c['locator'];
$cache =
$locator->findResource('gantry-cache://theme/compiled/config',
true, true);
$paths =
$locator->findResources('gantry-config://default');
$files = (new ConfigFileFinder)->locateFiles($paths);
$config = new CompiledConfig($cache, $files, GANTRY5_ROOT);
$config->setBlueprints(function() use ($c) {
return $c['blueprints'];
});
return $config->load(true);
};
// Initialize admin streams.
/** @var Platform $patform */
$patform = $gantry['platform'];
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$nucleus =
$patform->getEnginePaths('nucleus')[''];
if (strpos($this->path, '://')) {
$relpath = $this->path;
} else {
$relpath = Folder::getRelativePath($this->path);
}
$patform->set(
'streams.gantry-admin.prefixes', [
'' =>
['gantry-theme://admin', $relpath, $relpath .
'/common', 'gantry-engine://admin'],
'assets/' => array_merge([$relpath, $relpath .
'/common'], $nucleus, ['gantry-assets://'])
]
);
// Add admin paths.
foreach
($patform->get('streams.gantry-admin.prefixes') as $prefix
=> $paths) {
$locator->addPath('gantry-admin', $prefix,
$paths);
}
// Fire admin init event.
$event = new Event;
$event->gantry = $gantry;
$event->theme = $this;
$gantry->fireEvent('admin.init.theme', $event);
}
/**
* @see AbstractTheme::getCachePath()
*
* @param string $path
* @return string
*/
protected function getCachePath($path = '')
{
$gantry = static::gantry();
/** @var Platform $patform */
$patform = $gantry['platform'];
// Initialize theme cache stream.
return $patform->getCachePath() . '/admin' . ($path ?
'/' . $path : '');
}
/**
* @see AbstractTheme::setTwigLoaderPaths()
*
* @param \Twig_LoaderInterface $loader
*/
protected function setTwigLoaderPaths(\Twig_LoaderInterface $loader)
{
if (!($loader instanceof \Twig_Loader_Filesystem)) {
return;
}
$gantry = static::gantry();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$loader->setPaths($locator->findResources('gantry-admin://templates'));
$loader->setPaths($locator->findResources('gantry-admin://templates'),
'gantry-admin');
}
}
PK���[܁lAdmin/ThemeList.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Admin;
use Gantry\Component\Filesystem\Folder;
use Gantry\Component\Theme\ThemeDetails;
use Gantry\Framework\Gantry;
use Joomla\Registry\Registry;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class ThemeList
{
/**
* @var ThemeDetails[]
*/
protected static $items;
/**
* @var array
*/
protected static $styles;
/**
* @return array
*/
public static function getThemes()
{
if (!is_array(static::$items)) {
static::loadThemes();
}
$list = [];
foreach (static::$items as $item) {
$details = static::getTheme($item['name']);
if ($details) {
$list[$item['name']] = $details;
}
}
return $list;
}
/**
* @param string $name
* @return mixed
*/
public static function getTheme($name)
{
$styles = static::getStyles($name);
return reset($styles);
}
/**
* @param string $template
* @return array
*/
public static function getStyles($template = null, $force = false)
{
if ($force || !is_array(static::$styles)) {
static::loadStyles();
}
if ($template) {
return isset(static::$styles[$template]) ?
static::$styles[$template] : [];
}
$list = [];
foreach (static::$styles as $styles) {
$list += $styles;
}
ksort($list);
return $list;
}
protected static function loadThemes()
{
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
/** @var array|ThemeDetails[] $list */
$list = [];
$files = Folder::all('gantry-themes://',
['recursive' => false, 'files' => false]);
natsort($files);
foreach ($files as $theme) {
if ($locator('gantry-themes://' . $theme .
'/gantry/theme.yaml')) {
$details = new ThemeDetails($theme);
$details->addStreams();
$details['name'] = $theme;
$details['title'] =
$details['details.name'];
$details['preview_url'] = null;
$details['admin_url'] =
$gantry['platform']->getThemeAdminUrl($theme);
$details['params'] = [];
$list[$details->name] = $details;
}
}
// Add Thumbnails links after adding all the paths to the locator.
foreach ($list as $details) {
$details['thumbnail'] =
$details->getUrl("details.images.thumbnail");
}
static::$items = $list;
}
protected static function loadStyles()
{
$gantry = Gantry::instance();
$db = \JFactory::getDbo();
$query = $db
->getQuery(true)
->select('s.id, e.extension_id, s.template AS name,
s.title, s.params')
->from('#__template_styles AS s')
->where('s.client_id = 0')
->where('e.enabled = 1')
->where('e.state = 0')
->leftJoin('#__extensions AS e ON e.element=s.template
AND e.type='
. $db->quote('template') . ' AND
e.client_id=s.client_id')
->order('s.id');
$db->setQuery($query);
$styles = (array) $db->loadObjectList();
if (!is_array(static::$items)) {
static::loadThemes();
}
/** @var array|ThemeDetails[] $list */
$list = [];
foreach ($styles as $style)
{
$details = isset(static::$items[$style->name]) ?
static::$items[$style->name] : null;
if (!$details) {
continue;
}
$params = new Registry($style->params);
$details = clone $details;
$details['id'] = $style->id;
$details['extension_id'] = $style->extension_id;
$details['style'] = $style->title;
$details['preview_url'] =
$gantry['platform']->getThemePreviewUrl($style->id);
$details['params'] = $params->toArray();
$list[$style->name][$style->id] = $details;
}
static::$styles = $list;
}
}
PK���[�(r��"Component/Admin/HtmlController.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Admin;
use Gantry\Component\Controller\HtmlController as BaseController;
abstract class HtmlController extends BaseController
{
/**
* @param string|array $file
* @param array $context
* @return string
*/
public function render($file, array $context = [])
{
return
$this->container['admin.theme']->render($file, $context);
}
/**
* @param string $action
* @param string $id
* @return boolean
*/
public function authorize($action, $id = null)
{
return
$this->container['platform']->authorize($action, $id);
}
}
PK���[��p���"Component/Admin/JsonController.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Admin;
use Gantry\Component\Controller\JsonController as BaseController;
abstract class JsonController extends BaseController
{
/**
* @param string|array $file
* @param array $context
* @return string
*/
public function render($file, array $context = [])
{
return
$this->container['admin.theme']->render($file, $context);
}
/**
* @param string $action
* @param string $id
* @return boolean
*/
public function authorize($action, $id = null)
{
return
$this->container['platform']->authorize($action, $id);
}
}
PK���[ܵ����-Component/Assignments/AbstractAssignments.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Assignments;
use Gantry\Component\Config\CompiledConfig;
use Gantry\Component\Config\ConfigFileFinder;
use Gantry\Framework\Gantry;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
abstract class AbstractAssignments
{
/**
* @var string
*/
protected $configuration;
/**
* @var string
*/
protected $className =
'\Gantry\%s\Assignments\Assignments%s';
/**
* @var string
*/
protected $platform;
/**
* @var AssignmentFilter
*/
protected $filter;
/**
* @var array
*/
protected $candidates;
/**
* @var array
*/
protected $page;
/** @var callable */
protected $specialFilterMethod;
/**
* @param string $configuration
*/
public function __construct($configuration = null)
{
$this->configuration = $configuration;
}
/**
* Get list of assignment items.
*/
public function get()
{
return $this->getTypes();
}
/**
* Set (save) assignments.
*
* @param array $data
*/
public function set(array $data)
{
$this->save($data);
}
/**
* Select assigned outline.
*
* @param string $default
* @return string
*/
public function select($default = 'default')
{
$scores = $this->scores();
return key($scores) ?: $default;
}
/**
* List matching outlines sorted by score.
*
* @param array $candidates
* @return array
*/
public function scores(array $candidates = null)
{
$this->init();
$candidates = $candidates ?: $this->candidates;
return $this->filter->scores($candidates, $this->page,
$this->specialFilterMethod);
}
/**
* List matching outlines with matched assignments.
*
* @param array $candidates
* @return array
*/
public function matches(array $candidates = null)
{
$this->init();
$candidates = $candidates ?: $this->candidates;
return $this->filter->matches($candidates, $this->page,
$this->specialFilterMethod);
}
/**
* Load all assignments.
*
* @return array
*/
public function loadAssignments()
{
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
// Find all the assignment files.
$paths = $locator->findResources("gantry-config://");
$files = (new
ConfigFileFinder)->locateFileInFolder('assignments', $paths);
// Make sure that base or system outlines aren't in the list.
foreach ($files as $key => $array) {
$key = (string)$key;
if ($key === 'default' || strpos($key, '_')
=== 0) {
unset($files[$key]);
}
}
$cache =
$locator->findResource('gantry-cache://theme/compiled/config',
true, true);
$config = new CompiledConfig($cache, [$files], GANTRY5_ROOT);
return $config->load()->toArray();
}
/**
* Get all assignments for the current page.
*
* @return array
*/
public function getPage()
{
$list = [];
foreach($this->types() as $class => $type) {
$class = is_numeric($class) ? sprintf($this->className,
$this->platform, ucfirst($type)) : $class;
if (!class_exists($class)) {
throw new \RuntimeException("Assignment type {$type}
is missing");
}
/** @var AssignmentsInterface $instance */
$instance = new $class;
$list[$type] = $instance->getRules();
unset($instance);
}
return $list;
}
/**
* Filter assignments data.
*
* @param array $data
* @param bool $minimize
* @return array
*/
public function filter(array $data, $minimize = false)
{
$types = [];
foreach ($this->types() as $type) {
$types[$type] = [];
}
$data = array_replace($types, $data);
foreach ($data as $tname => &$type) {
if (is_array($type)) {
foreach ($type as $gname => &$group) {
if (is_array($group)) {
foreach ($group as $key => $value) {
if (!$value) {
unset($group[$key]);
} else {
$group[$key] = (bool) $value;
}
}
if (empty($group)) {
unset($type[$gname]);
}
} else {
$group = (bool) $group;
}
}
unset($group);
if ($minimize && empty($type)) {
unset($data[$tname]);
}
} else {
$type = (bool) $type;
}
}
return $data;
}
/**
* Save assignments for the configuration.
*
* @param array $data
*/
public function save(array $data)
{
$data = $this->filter($data);
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
// Save layout into custom directory for the current theme.
$save_dir =
$locator->findResource("gantry-config://{$this->configuration}",
true, true);
$filename = "{$save_dir}/assignments.yaml";
$file = YamlFile::instance($filename);
$file->save($data);
$file->free();
}
/**
* Get list of all assignment types for assignments form.
*
* @return array
*/
public function getTypes()
{
$list = [];
foreach ($this->types() as $class => $type) {
$class = is_numeric($class) ? sprintf($this->className,
$this->platform, ucfirst($type)) : $class;
if (!class_exists($class)) {
throw new \RuntimeException("Assignment type
'{$type}' is missing");
}
/** @var AssignmentsInterface $instance */
$instance = new $class;
$list[$type] =
$instance->listRules($this->configuration);
unset($instance);
}
return $list;
}
/**
* Get selected assignment option.
*
* @return string
*/
public function getAssignment()
{
return 'default';
}
/**
* Set extra options for assignments.
*
* @param $value
*/
public function setAssignment($value)
{
}
/**
* Get extra options for assignments.
*
* @return array
*/
public function assignmentOptions()
{
return [];
}
protected function init()
{
if (!$this->filter) {
$this->filter = new AssignmentFilter;
$this->candidates = $this->loadAssignments();
$this->page = $this->getPage();
}
}
/**
* Return list of assignment types.
*
* @return array
*/
abstract public function types();
}
PK���[�d�//*Component/Assignments/AssignmentFilter.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Assignments;
/**
* Class AssignmentFilter
* @package Gantry\Assignments
*/
class AssignmentFilter
{
protected $method;
/**
* Return all matching candidates with their score. Candidates are
ordered by their scores.
*
* @param array $candidates In format of
candidates[name][section][rule].
* @param array $page In format of page[section][rule].
* @return array
*/
public function scores(array &$candidates, array &$page,
callable $function = null)
{
$matches = $this->matches($candidates, $page, $function);
$scores = [];
foreach ($matches as $type => $candidate) {
$scores[$type] = $this->getScore($candidate) +
(isset($candidate['language']) ? 0.01 : 0);
}
// Always return matches by score in alphabetical order.
ksort($scores, SORT_STRING);
arsort($scores, SORT_NUMERIC);
return $scores;
}
/**
* Returns all matching candidates with matching rules.
*
* @param array $candidates In format of
candidates[name][section][rule].
* @param array $page In format of page[section][rule].
* @return array
*/
public function matches(array $candidates, array &$page, callable
$function = null)
{
$matches = [];
foreach ($candidates as $type => $candidate) {
if (!is_array($candidate)) {
if ($candidate === true && $page) {
$matches[$type] = $page;
}
continue;
}
foreach ($candidate as $section => $list) {
if (!is_array($list)) {
if ($list === true && !empty($page[$section]))
{
$matches[$type][$section] = $page[$section];
}
continue;
}
foreach ($list as $name => $rules) {
if (!empty($page[$section][$name])) {
if (!is_array($rules)) {
$match = $rules === true ?
$page[$section][$name] : [];
} else {
$match =
\array_intersect_key($page[$section][$name], $rules);
}
if ($match) {
$matches[$type][$section][$name] = $match;
}
}
}
}
if (isset($matches[$type]) && $function &&
call_user_func($function, $candidate, $matches[$type], $page) === false) {
unset($matches[$type]);
}
}
return $matches;
}
/**
* Returns the calculated score for the assignment.
*
* @param array $matches
* @param string $method
* @return int
*/
public function getScore(array &$matches, $method =
'max')
{
$this->method = 'calc' . ucfirst($method);
if (!method_exists($this, $this->method)) {
$this->method = 'calcMax';
}
return $this->calcArray(0, $matches);
}
/**
* @param float $carry
* @param float|array $item
* @return float
* @internal
*/
protected function calcArray($carry, $item)
{
if (is_array($item)) {
return array_reduce($item, [$this, 'calcArray'],
$carry);
}
$method = $this->method;
return $this->{$method}($carry, (float) $item);
}
/**
* @param float $carry
* @param float $item
* @return float
* @internal
*/
protected function calcOr($carry, $item)
{
return (float) ($carry || $item);
}
/**
* @param float $carry
* @param float $item
* @return float
* @internal
*/
protected function calcMin($carry, $item)
{
return $carry ? min($carry, $item) : $item;
}
/**
* @param float $carry
* @param float $item
* @return float
* @internal
*/
protected function calcMax($carry, $item)
{
return max($carry, $item);
}
/**
* @param float $carry
* @param float $item
* @return float
* @internal
*/
protected function calcSum($carry, $item)
{
return $carry + $item;
}
/**
* @param float $carry
* @param float $item
* @return float
* @internal
*/
protected function calcMul($carry, $item)
{
return $carry ? $carry * $item : $item;
}
}
PK���[3�U���.Component/Assignments/AssignmentsInterface.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Assignments;
interface AssignmentsInterface
{
/**
* Returns list of rules which apply to the current page.
*
* @return array
*/
public function getRules();
/**
* List all the rules available.
*
* @param string $configuration
* @return array
*/
public function listRules($configuration);
}
PK���[�)!�99#Component/Collection/Collection.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Collection;
use RocketTheme\Toolbox\ArrayTraits\ArrayAccess;
use RocketTheme\Toolbox\ArrayTraits\Countable;
use RocketTheme\Toolbox\ArrayTraits\Export;
class Collection implements CollectionInterface
{
use ArrayAccess, Countable, Export;
/**
* @var array
*/
protected $items = [];
public static function __set_state($variables)
{
$instance = new static();
$instance->items = $variables['items'];
return $instance;
}
/**
*
* Create a copy of this collection.
*
* @return static
*/
public function copy()
{
return clone $this;
}
/**
* @param $item
* @return $this
*/
public function add($item)
{
$this->items[] = $item;
return $this;
}
/**
* @return \ArrayIterator
*/
public function getIterator()
{
return new \ArrayIterator($this->items);
}
}
PK���[�?�~~,Component/Collection/CollectionInterface.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Collection;
interface CollectionInterface extends \IteratorAggregate, \ArrayAccess,
\Countable
{
public function toArray();
/**
* @param $item
*/
public function add($item);
/**
* @return \ArrayIterator
*/
public function getIterator();
/**
* @param $offset
*
* @return bool
*/
public function offsetExists($offset);
/**
* @param $offset
* @param $value
*/
public function offsetSet($offset, $value);
/**
* @param $offset
*
* @return mixed
*/
public function offsetGet($offset);
/**
* @param $offset
*/
public function offsetUnset($offset);
/**
* @return int
*/
public function count();
}
PK���[�c��9$9$"Component/Config/BlueprintForm.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Config;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Framework\Gantry;
use RocketTheme\Toolbox\Blueprints\BlueprintForm as BaseBlueprintForm;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* The Config class contains configuration information.
*
* @author RocketTheme
*/
class BlueprintForm extends BaseBlueprintForm
{
/**
* @var string
*/
protected $context = 'gantry-blueprints://';
/**
* @var BlueprintSchema
*/
protected $schema;
/**
* @param string $filename
* @param string $context
* @return BlueprintForm
*/
public static function instance($filename, $context = null)
{
/** @var BlueprintForm $instance */
$instance = new static($filename);
if ($context) {
$instance->setContext($context);
}
return $instance->load()->init();
}
/**
* Get nested structure containing default values defined in the
blueprints.
*
* Fields without default value are ignored in the list.
*
* @return array
*/
public function getDefaults()
{
return $this->schema()->getDefaults();
}
/**
* Merge two arrays by using blueprints.
*
* @param array $data1
* @param array $data2
* @param string $name Optional
* @param string $separator Optional
* @return array
*/
public function mergeData(array $data1, array $data2, $name = null,
$separator = '.')
{
return $this->schema()->mergeData($data1, $data2, $name,
$separator);
}
/**
* Return data fields that do not exist in blueprints.
*
* @param array $data
* @param string $prefix
* @return array
*/
public function extra(array $data, $prefix = '')
{
return $this->schema()->extra($data, $prefix);
}
/**
* Validate data against blueprints.
*
* @param array $data
* @throws \RuntimeException
*/
public function validate(array $data)
{
$this->schema()->validate($data);
}
/**
* Filter data by using blueprints.
*
* @param array $data
* @return array
*/
public function filter(array $data)
{
return $this->schema()->filter($data);
}
/**
* @return BlueprintSchema
*/
public function schema()
{
if (!isset($this->schema)) {
$this->schema = new BlueprintSchema;
$this->schema->embed('', $this->items);
$this->schema->init();
}
return $this->schema;
}
/**
* @param string $filename
* @return string
*/
protected function loadFile($filename)
{
$file = CompiledYamlFile::instance($filename);
$content = $file->content();
$file->free();
return $content;
}
/**
* @param string|array $path
* @param string $context
* @return array
*/
protected function getFiles($path, $context = null)
{
if (is_string($path) && !strpos($path, '://')) {
// Resolve filename.
if (isset($this->overrides[$path])) {
$path = $this->overrides[$path];
} else {
if ($context === null) {
$context = $this->context;
}
if ($context && $context[strlen($context)-1] !==
'/') {
$context .= '/';
}
$path = $context . $path;
if (!preg_match('/\.yaml$/', $path)) {
$path .= '.yaml';
}
}
}
if (is_string($path) && strpos($path, '://')) {
/** @var UniformResourceLocator $locator */
$locator = Gantry::instance()['locator'];
$files = $locator->findResources($path);
} else {
$files = (array) $path;
}
return $files;
}
/**
* @param array $field
* @param string $property
* @param array $call
*/
protected function dynamicData(array &$field, $property, array
&$call)
{
$params = $call['params'];
if (is_array($params)) {
$function = array_shift($params);
} else {
$function = $params;
$params = [];
}
list($o, $f) = preg_split('/::/', $function, 2);
if (!$f) {
if (function_exists($o)) {
$data = call_user_func_array($o, $params);
}
} else {
if (method_exists($o, $f)) {
$data = call_user_func_array(array($o, $f), $params);
}
}
// If function returns a value,
if (isset($data)) {
if (isset($field[$property]) &&
is_array($field[$property]) && is_array($data)) {
// Combine field and @data-field together.
$field[$property] += $data;
} else {
// Or create/replace field with @data-field.
$field[$property] = $data;
}
}
}
/**
* @param array $field
* @param string $property
* @param array $call
*/
protected function dynamicConfig(array &$field, $property, array
&$call)
{
$value = $call['params'];
$default = isset($field[$property]) ? $field[$property] : null;
$config = Gantry::instance()['config']->get($value,
$default);
if (!is_null($config)) {
$field[$property] = $config;
}
}
/**
* Get blueprints by using slash notation for nested arrays/objects.
*
* @param array $path
* @param string $separator
* @return array
*/
public function resolve(array $path, $separator = '/')
{
$fields = false;
$parts = [];
$current = $this['form/fields'];
$result = [null, null, null];
$prefix = '';
while (($field = current($path)) !== false) {
if (!$fields && isset($current['fields'])) {
if (!empty($current['array'])) {
$result = [$current, $parts, $path ?
implode($separator, $path) : null];
// Skip item offset.
$parts[] = array_shift($path);
}
$current = $current['fields'];
$prefix = '';
$fields = true;
} elseif (isset($current[$prefix . $field])) {
$parts[] = array_shift($path);
$current = $current[$prefix . $field];
$prefix = '';
$fields = false;
} elseif (isset($current['.' . $prefix . $field])) {
$parts[] = array_shift($path);
$current = $current['.' . $prefix . $field];
$prefix = '';
$fields = false;
} elseif ($field && $this->fieldExists($prefix .
$field, $current)) {
$parts[] = array_shift($path);
$prefix = "{$prefix}{$field}.";
$fields = false;
} else {
// Check if there's a container with the field.
$current = $this->resolveContainer($current, $prefix,
$field);
// No containers with the field found.
if (!$current) {
break;
}
$prefix = '';
$fields = false;
}
}
if (!$fields && !empty($current['array'])) {
$result = [$current, $parts, $path ? implode($separator, $path)
: null];
}
return $result;
}
protected function resolveContainer($current, $prefix, $fieldName)
{
foreach ($current as $field) {
$type = isset($field['type']) ?
$field['type'] : 'container._implicit';
$container = (0 === strpos($type, 'container.'));
if (!$container || !isset($field['fields'])) {
continue;
}
$current_fields = $field['fields'];
if (isset($current_fields[$prefix . $fieldName]) ||
isset($current_fields['.' . $prefix . $fieldName])
|| $this->fieldExists($prefix . $fieldName,
$current_fields)) {
return $current_fields;
}
$current_fields = $this->resolveContainer($current_fields,
$prefix, $fieldName);
if ($current_fields !== null) {
return $current_fields;
}
}
return null;
}
protected function fieldExists($prefix, $list)
{
foreach ($list as $field => $data) {
$pos = strpos($field, $prefix);
if ($pos === 0 || ($pos === 1 && $field[0] ===
'.')) {
return true;
}
}
return false;
}
}
PK���[ù���$Component/Config/BlueprintSchema.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Config;
use Gantry\Framework\Gantry;
use RocketTheme\Toolbox\Blueprints\BlueprintSchema as BlueprintSchemaBase;
/**
* Blueprint schema handles the internal logic of blueprints.
*
* @author RocketTheme
* @license MIT
*/
class BlueprintSchema extends BlueprintSchemaBase
{
protected $configuration;
protected $ignoreFormKeys = [
'title' => true,
'help' => true,
'placeholder' => true,
'fields' => true
];
protected $types = [
'container.set' => [
'input@' => false
],
'container.tabs' => [
'input@' => false
],
'separator.note' => [
'input@' => false
],
'separator.separator' => [
'input@' => false
],
'key' => [
'input@' => false
],
'collection.list' => [
'array' => true
]
];
/**
* Constructor.
*
* @param array $serialized Serialized content if available.
*/
public function __construct($serialized = null)
{
parent::__construct($serialized);
$this->configuration = new
Config(isset($serialized['configuration']) ?
$serialized['configuration'] : []);
}
/**
* Convert object into an array.
*
* @return array
*/
public function getState()
{
return parent::getState() + ['configuration' =>
$this->configuration->toArray()];
}
/**
* Get nested structure containing default values defined in the
blueprints.
*
* Fields without default value are ignored in the list.
*
* @return array
*/
public function getDefaults()
{
return array_merge_recursive($this->configuration->toArray(),
$this->buildDefaults($this->nested));
}
/**
* Embed an array to the blueprint.
*
* @param $name
* @param array $value
* @param string $separator
* @param bool $merge Merge fields instead replacing them.
* @return $this
*/
public function embed($name, array $value, $separator = '.',
$merge = false)
{
parent::embed($name, $value, $separator, $merge);
if (isset($value['configuration'])) {
$this->configuration->set($name,
$value['configuration'], $separator);
}
return $this;
}
/**
* Validate data against blueprints.
*
* @param array $data
* @throws \RuntimeException
*/
public function validate(array $data)
{
try {
$messages = $this->validateArray($data, $this->nested);
} catch (\RuntimeException $e) {
throw (new ValidationException($e->getMessage(),
$e->getCode(), $e))->setMessages();
}
if (!empty($messages)) {
throw (new ValidationException())->setMessages($messages);
}
}
/**
* Filter data by using blueprints.
*
* @param array $data
* @return array
*/
public function filter(array $data)
{
return $this->filterArray($data, $this->nested);
}
/**
* @param array $data
* @param array $rules
* @returns array
* @throws \RuntimeException
* @internal
*/
protected function validateArray(array $data, array $rules)
{
$messages = $this->checkRequired($data, $rules);
foreach ($data as $key => $field) {
$val = isset($rules[$key]) ? $rules[$key] :
(isset($rules['*']) ? $rules['*'] : null);
$rule = is_string($val) ? $this->items[$val] : null;
if ($rule) {
// Item has been defined in blueprints.
$messages += Validation::validate($field, $rule);
} elseif (is_array($field) && is_array($val)) {
// Array has been defined in blueprints.
$messages += $this->validateArray($field, $val);
} elseif (isset($rules['validation']) &&
$rules['validation'] == 'strict') {
// Undefined/extra item.
throw new \RuntimeException(sprintf('%s is not defined
in blueprints', $key));
}
}
return $messages;
}
/**
* @param array $data
* @param array $rules
* @return array
* @internal
*/
protected function filterArray(array $data, array $rules)
{
$results = array();
foreach ($data as $key => $field) {
$val = isset($rules[$key]) ? $rules[$key] :
(isset($rules['*']) ? $rules['*'] : null);
$rule = is_string($val) ? $this->items[$val] : null;
if ($rule) {
// Item has been defined in blueprints.
$field = Validation::filter($field, $rule);
} elseif (is_array($field) && is_array($val)) {
// Array has been defined in blueprints.
$field = $this->filterArray($field, $val);
} elseif (isset($rules['validation']) &&
$rules['validation'] == 'strict') {
$field = null;
}
if (isset($field) && (!is_array($field) ||
!empty($field))) {
$results[$key] = $field;
}
}
return $results;
}
/**
* @param array $data
* @param array $fields
* @return array
*/
protected function checkRequired(array $data, array $fields)
{
$messages = [];
foreach ($fields as $name => $field) {
if (!is_string($field)) {
continue;
}
$field = $this->items[$field];
if (isset($field['validate']['required'])
&&
$field['validate']['required'] === true
&& !isset($data[$name])) {
$value = isset($field['label']) ?
$field['label'] : $field['name'];
// TODO: translate
$message = sprintf("Please fill up required field
'%s'.", $value);
$messages[$field['name']][] = $message;
}
}
return $messages;
}
/**
* @param array $field
* @param string $property
* @param array $call
*/
protected function dynamicConfig(array &$field, $property, array
&$call)
{
$value = $call['params'];
$default = isset($field[$property]) ? $field[$property] : null;
$config = Gantry::instance()['config']->get($value,
$default);
if (!is_null($config)) {
$field[$property] = $config;
}
}
}
PK���[�-��!Component/Config/CompiledBase.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Config;
use Gantry\Framework\Gantry;
use RocketTheme\Toolbox\File\PhpFile;
/**
* The Compiled base class.
*/
abstract class CompiledBase
{
/**
* @var int Version number for the compiled file.
*/
public $version = 1;
/**
* @var string Filename (base name) of the compiled configuration.
*/
public $name;
/**
* @var string|bool Configuration checksum.
*/
public $checksum;
/**
* @var string Cache folder to be used.
*/
protected $cacheFolder;
/**
* @var array List of files to load.
*/
protected $files;
/**
* @var string
*/
protected $path;
/**
* @var mixed Configuration object.
*/
protected $object;
/**
* @param string $cacheFolder Cache folder to be used.
* @param array $files List of files as returned from
ConfigFileFinder class.
* @param string $path Base path for the file list.
* @throws \BadMethodCallException
*/
public function __construct($cacheFolder, array $files, $path =
GANTRY5_ROOT)
{
if (!$cacheFolder) {
throw new \BadMethodCallException('Cache folder not
defined.');
}
$this->cacheFolder = $cacheFolder;
$this->files = $files;
$this->path = $path ? rtrim($path, '\\/') .
'/' : '';
}
/**
* Get filename for the compiled PHP file.
*
* @param string $name
* @return $this
*/
public function name($name = null)
{
if (!$this->name) {
$this->name = $name ?:
md5(json_encode(array_keys($this->files)));
}
return $this;
}
/**
* Function gets called when cached configuration is saved.
*/
public function modified() {}
/**
* Load the configuration.
*
* @return mixed
*/
public function load()
{
if ($this->object) {
return $this->object;
}
$filename = $this->createFilename();
if (!$this->loadCompiledFile($filename) &&
$this->loadFiles()) {
$this->saveCompiledFile($filename);
}
return $this->object;
}
/**
* Returns checksum from the configuration files.
*
* You can set $this->checksum = false to disable this check.
*
* @return bool|string
*/
public function checksum()
{
if (!isset($this->checksum)) {
$this->checksum = md5(json_encode($this->files) .
$this->version);
}
return $this->checksum;
}
protected function createFilename()
{
return
"{$this->cacheFolder}/{$this->name()->name}.php";
}
/**
* Create configuration object.
*
* @param array $data
*/
abstract protected function createObject(array $data = []);
/**
* Finalize configuration object.
*/
abstract protected function finalizeObject();
/**
* Load single configuration file and append it to the correct
position.
*
* @param string $name Name of the position.
* @param string $filename File to be loaded.
*/
abstract protected function loadFile($name, $filename);
/**
* Load and join all configuration files.
*
* @return bool
* @internal
*/
protected function loadFiles()
{
$this->createObject();
$list = array_reverse($this->files);
foreach ($list as $files) {
foreach ($files as $name => $item) {
$this->loadFile($name, $this->path .
$item['file']);
}
}
$this->finalizeObject();
return true;
}
/**
* Load compiled file.
*
* @param string $filename
* @return bool
* @internal
*/
protected function loadCompiledFile($filename)
{
$gantry = Gantry::instance();
/** @var Config $global */
$global = $gantry['global'];
if (!$global->get('compile_yaml', 1)) {
return false;
}
if (!file_exists($filename)) {
return false;
}
$cache = include $filename;
if (
!is_array($cache)
|| !isset($cache['checksum'])
|| !isset($cache['data'])
|| !isset($cache['@class'])
|| $cache['@class'] != get_class($this)
) {
return false;
}
// Load real file if cache isn't up to date (or is invalid).
if ($cache['checksum'] !== $this->checksum()) {
return false;
}
$this->createObject($cache['data']);
$this->finalizeObject();
return true;
}
/**
* Save compiled file.
*
* @param string $filename
* @throws \RuntimeException
* @internal
*/
protected function saveCompiledFile($filename)
{
$gantry = Gantry::instance();
/** @var Config $global */
$global = $gantry['global'];
if (!$global->get('compile_yaml', 1)) {
return;
}
$file = PhpFile::instance($filename);
// Attempt to lock the file for writing.
try {
$file->lock(false);
} catch (\Exception $e) {
// Another process has locked the file; we will check this in a
bit.
}
if ($file->locked() === false) {
// File was already locked by another process.
return;
}
$cache = [
'@class' => get_class($this),
'timestamp' => time(),
'checksum' => $this->checksum(),
'files' => $this->files,
'data' => $this->getState()
];
$file->save($cache);
$file->unlock();
$file->free();
$this->modified();
}
protected function getState()
{
return $this->object->toArray();
}
}
PK���[�ԂDD'Component/Config/CompiledBlueprints.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Config;
/**
* The Compiled Blueprints class.
*/
class CompiledBlueprints extends CompiledBase
{
/**
* @var int Version number for the compiled file.
*/
public $version = 3;
/**
* @var BlueprintSchema Blueprints object.
*/
protected $object;
/**
* Create configuration object.
*
* @param array $data
*/
protected function createObject(array $data = [])
{
$this->object = new BlueprintSchema($data);
}
/**
* Finalize configuration object.
*/
protected function finalizeObject()
{
}
/**
* Load single configuration file and append it to the correct
position.
*
* @param string $name Name of the position.
* @param array $files Files to be loaded.
*/
protected function loadFile($name, $files)
{
// Load blueprint file.
$blueprint = new BlueprintForm($files);
$this->object->embed($name,
$blueprint->load()->toArray(), '/', true);
}
/**
* Load and join all configuration files.
*
* @return bool
* @internal
*/
protected function loadFiles()
{
$this->createObject();
// Convert file list into parent list.
$list = [];
foreach ($this->files as $files) {
foreach ($files as $name => $item) {
$list[$name][] = $this->path . $item['file'];
}
}
// Load files.
foreach ($list as $name => $files) {
$this->loadFile($name, $files);
}
$this->finalizeObject();
return true;
}
protected function getState()
{
return $this->object->getState();
}
}
PK���[��ͭ
#Component/Config/CompiledConfig.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Config;
use Gantry\Component\File\CompiledYamlFile;
/**
* The Compiled Configuration class.
*/
class CompiledConfig extends CompiledBase
{
/**
* @var int Version number for the compiled file.
*/
public $version = 2;
/**
* @var Config Configuration object.
*/
protected $object;
/**
* @var callable Blueprints loader.
*/
protected $callable;
/**
* @var bool
*/
protected $withDefaults;
/**
* Get filename for the compiled PHP file.
*
* @param string $name
* @return $this
*/
public function name($name = null)
{
if (!$this->name) {
$this->name = $name ?:
md5(json_encode(array_keys($this->files)) . (int)
$this->withDefaults);
}
return $this;
}
/**
* Set blueprints for the configuration.
*
* @param callable $blueprints
* @return $this
*/
public function setBlueprints(callable $blueprints)
{
$this->callable = $blueprints;
return $this;
}
/**
* @param bool $withDefaults
* @return mixed
*/
public function load($withDefaults = false)
{
$this->withDefaults = $withDefaults;
return parent::load();
}
/**
* Create configuration object.
*
* @param array $data
*/
protected function createObject(array $data = [])
{
if ($this->withDefaults && empty($data) &&
is_callable($this->callable)) {
$blueprints = $this->callable;
$data = $blueprints()->getDefaults();
}
$this->object = new Config($data, $this->callable);
}
/**
* Finalize configuration object.
*/
protected function finalizeObject()
{
}
/**
* Load single configuration file and append it to the correct
position.
*
* @param string $name Name of the position.
* @param string $filename File to be loaded.
*/
protected function loadFile($name, $filename)
{
$file = CompiledYamlFile::instance($filename);
$this->object->join($name, $file->content(),
'/');
$file->free();
}
}
PK���[Ѱ�PddComponent/Config/Config.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Config;
use RocketTheme\Toolbox\ArrayTraits\Export;
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
use RocketTheme\Toolbox\ArrayTraits\Iterator;
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters;
/**
* The Config class contains configuration information.
*
* @author RocketTheme
*/
class Config implements \ArrayAccess, \Countable, \Iterator,
ExportInterface
{
use NestedArrayAccessWithGetters, Iterator, Export;
/**
* @var array
*/
protected $items;
/**
* @var BlueprintSchema|BlueprintForm|callable
*/
protected $blueprint;
/**
* Constructor to initialize array.
*
* @param array $items Initial items inside the iterator.
* @param callable $blueprints Function to load Blueprints for the
configuration.
*/
public function __construct(array $items, callable $blueprint = null)
{
$this->items = $items;
$this->blueprint = $blueprint;
}
/**
* Join nested values together by using blueprints.
*
* @param string $name Dot separated path to the requested
value.
* @param mixed $value Value to be joined.
* @param string $separator Separator, defaults to '.'
* @return $this
* @throws \RuntimeException
*/
public function join($name, $value, $separator = '.')
{
$old = $this->get($name, null, $separator);
if ($old !== null) {
if (!is_array($old)) {
throw new \RuntimeException("Value is not array in
{$name}: " . print_r($old, true));
}
if (is_object($value)) {
$value = (array) $value;
} elseif (!is_array($value)) {
throw new \RuntimeException("Value is not array in
{$name}: " . print_r($value, true));
}
$value = $this->blueprint()->mergeData($old, $value,
$name, $separator);
}
$this->set($name, $value, $separator);
return $this;
}
/**
* Get nested structure containing default values defined in the
blueprints.
*
* Fields without default value are ignored in the list.
* @return array
*/
public function getDefaults()
{
return $this->blueprint()->getDefaults();
}
/**
* Set default values by using blueprints.
*
* @param string $name Dot separated path to the requested
value.
* @param mixed $value Value to be joined.
* @param string $separator Separator, defaults to '.'
* @return $this
*/
public function joinDefaults($name, $value, $separator = '.')
{
if (is_object($value)) {
$value = (array) $value;
}
$old = $this->get($name, null, $separator);
if ($old !== null) {
$value = $this->blueprint()->mergeData($value, $old,
$name, $separator);
}
$this->set($name, $value, $separator);
return $this;
}
/**
* Get value from the configuration and join it with given data.
*
* @param string $name Dot separated path to the requested
value.
* @param array $value Value to be joined.
* @param string $separator Separator, defaults to '.'
* @return array
* @throws \RuntimeException
*/
public function getJoined($name, $value, $separator = '.')
{
if (is_object($value)) {
$value = (array) $value;
} elseif (!is_array($value)) {
throw new \RuntimeException("Value is not array in
'{$name}': " . print_r($value, true));
}
$old = $this->get($name, null, $separator);
if ($old === null) {
// No value set; no need to join data.
return $value;
}
if (!is_array($old)) {
throw new \RuntimeException("Value is not array in
'{$name}': " . print_r($value, true));
}
// Return joined data.
return $this->blueprint()->mergeData($old, $value, $name,
$separator);
}
/**
* Merge two configurations together.
*
* @param array $data
* @return $this
*/
public function merge(array $data)
{
$this->items =
$this->blueprint()->mergeData($this->items, $data);
return $this;
}
/**
* Set default values to the configuration if variables were not set.
*
* @param array $data
* @return $this
*/
public function setDefaults(array $data)
{
$this->items = $this->blueprint()->mergeData($data,
$this->items);
return $this;
}
/**
* Make a flat list from the configuration.
*
* @param string $name Dot separated path to the requested value.
* @param string $separator Separator, defaults to '.'
* @param string $prefix Name prefix.
* @return array
*/
public function flatten($name = null, $separator = '.',
$prefix = '')
{
$element = $name ? $this->offsetGet($name) : $this->items;
if (!is_array($element)) {
return [$name, $element];
}
if (strlen($separator) == 2 && in_array($separator,
['][', ')(', '}{'])) {
$separator = [$separator[1], $separator[0]];
}
return $this->flattenNested('', $element, $separator,
$prefix);
}
/**
* @param string $name
* @param array $element
* @param string $separator
* @param string $prefix
* @return array
* @internal
*/
protected function flattenNested($name, &$element, $separator,
$prefix)
{
$list = [];
foreach ($element as $key => $value) {
$new = $name ? $name : $prefix;
if (is_array($separator)) {
$new .= $separator[0] . $key . $separator[1];
} else {
$new .= ($new ? $separator : '') . $key;
}
if (!is_array($value) || empty($value)) {
$list[$new] = $value;
} else {
$list += $this->flattenNested($new, $value, $separator,
$prefix);
}
}
return $list;
}
/**
* Return blueprint.
*
* @return BlueprintSchema|BlueprintForm
* @since 5.4.7
*/
public function blueprint()
{
if (!$this->blueprint){
$this->blueprint = new BlueprintSchema;
} elseif (is_callable($this->blueprint)) {
// Lazy load blueprints.
$blueprint = $this->blueprint;
$this->blueprint = $blueprint();
}
return $this->blueprint;
}
/**
* Return blueprints.
*
* @return BlueprintSchema
* @deprecated 5.4.7
*/
public function blueprints()
{
return $this->blueprint();
}
/**
* Count items in nested array.
*
* @param string $path
* @param string $separator
* @return int
*/
public function count($path = null, $separator = '.')
{
$items = $path ? $this->get($path, null, $separator) :
$this->items;
return is_array($items) ? count($items) : 0;
}
}
PK���[ҽ`\!\!%Component/Config/ConfigFileFinder.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Config;
use Gantry\Component\Filesystem\Folder;
/**
* The Configuration & Blueprints Finder class.
*/
class ConfigFileFinder
{
protected $base = '';
/**
* @param string $base
* @return $this
*/
public function setBase($base)
{
$this->base = $base ? "{$base}/" : '';
return $this;
}
/**
* Return all locations for all the files with a timestamp.
*
* @param array $paths List of folders to look from.
* @param string $pattern Pattern to match the file. Pattern will
also be removed from the key.
* @param int $levels Maximum number of recursive directories.
* @return array
*/
public function locateFiles(array $paths, $pattern =
'|\.yaml$|', $levels = -1)
{
$list = [];
foreach ($paths as $folder) {
$list += $this->detectRecursive($folder, $pattern, $levels);
}
return $list;
}
/**
* Return all locations for all the files with a timestamp.
*
* @param array $paths List of folders to look from.
* @param string $pattern Pattern to match the file. Pattern will
also be removed from the key.
* @param int $levels Maximum number of recursive directories.
* @return array
*/
public function getFiles(array $paths, $pattern =
'|\.yaml$|', $levels = -1)
{
$list = [];
foreach ($paths as $folder) {
$path = trim(Folder::getRelativePath($folder), '/');
$files = $this->detectRecursive($folder, $pattern, $levels);
$list += $files[trim($path, '/')];
}
return $list;
}
/**
* Return all paths for all the files with a timestamp.
*
* @param array $paths List of folders to look from.
* @param string $pattern Pattern to match the file. Pattern will
also be removed from the key.
* @param int $levels Maximum number of recursive directories.
* @return array
*/
public function listFiles(array $paths, $pattern =
'|\.yaml$|', $levels = -1)
{
$list = [];
foreach ($paths as $folder) {
$list = array_merge_recursive($list,
$this->detectAll($folder, $pattern, $levels));
}
return $list;
}
/**
* Find filename from a list of folders.
*
* Note: Only finds the last override.
*
* @param string $filename
* @param array $folders
* @return array
*/
public function locateFileInFolder($filename, array $folders)
{
$list = [];
foreach ($folders as $folder) {
$list += $this->detectInFolder($folder, $filename);
}
return $list;
}
/**
* Find filename from a list of folders.
*
* @param array $folders
* @param string $filename
* @return array
*/
public function locateInFolders(array $folders, $filename = null)
{
$list = [];
foreach ($folders as $folder) {
$path = trim(Folder::getRelativePath($folder), '/');
$list[$path] = $this->detectInFolder($folder, $filename);
}
return $list;
}
/**
* Return all existing locations for a single file with a timestamp.
*
* @param array $paths Filesystem paths to look up from.
* @param string $name Configuration file to be located.
* @param string $ext File extension (optional, defaults to
.yaml).
* @return array
*/
public function locateFile(array $paths, $name, $ext =
'.yaml')
{
$filename = preg_replace('|[.\/]+|', '/',
$name) . $ext;
$list = [];
foreach ($paths as $folder) {
$path = trim(Folder::getRelativePath($folder), '/');
if (is_file("{$folder}/{$filename}")) {
$modified = filemtime("{$folder}/{$filename}");
} else {
$modified = 0;
}
$basename = $this->base . $name;
$list[$path] = [$basename => ['file' =>
"{$path}/{$filename}", 'modified' => $modified]];
}
return $list;
}
/**
* Detects all directories with a configuration file and returns them
with last modification time.
*
* @param string $folder Location to look up from.
* @param string $pattern Pattern to match the file. Pattern will
also be removed from the key.
* @param int $levels Maximum number of recursive directories.
* @return array
* @internal
*/
protected function detectRecursive($folder, $pattern, $levels)
{
$path = trim(Folder::getRelativePath($folder), '/');
if (is_dir($folder)) {
// Find all system and user configuration files.
$options = [
'levels' => $levels,
'compare' => 'Filename',
'pattern' => $pattern,
'filters' => [
'pre-key' => $this->base,
'key' => $pattern,
'value' => function
(\RecursiveDirectoryIterator $file) use ($path) {
return ['file' =>
"{$path}/{$file->getSubPathname()}", 'modified'
=> $file->getMTime()];
}
],
'key' => 'SubPathname'
];
$list = Folder::all($folder, $options);
ksort($list);
} else {
$list = [];
}
return [$path => $list];
}
/**
* Detects all directories with the lookup file and returns them with
last modification time.
*
* @param string $folder Location to look up from.
* @param string $lookup Filename to be located (defaults to directory
name).
* @return array
* @internal
*/
protected function detectInFolder($folder, $lookup = null)
{
$folder = rtrim($folder, '/');
$path = trim(Folder::getRelativePath($folder), '/');
$base = $path === $folder ? '' : ($path ? substr($folder,
0, -strlen($path)) : $folder . '/');
$list = [];
if (is_dir($folder)) {
$iterator = new \DirectoryIterator($folder);
/** @var \DirectoryIterator $directory */
foreach ($iterator as $directory) {
if (!$directory->isDir() || $directory->isDot()) {
continue;
}
$name = $directory->getBasename();
$find = ($lookup ?: $name) . '.yaml';
$filename = "{$path}/{$name}/{$find}";
if (file_exists($base . $filename)) {
$basename = $this->base . $name;
$list[$basename] = ['file' => $filename,
'modified' => filemtime($base . $filename)];
}
}
}
return $list;
}
/**
* Detects all plugins with a configuration file and returns them with
last modification time.
*
* @param string $folder Location to look up from.
* @param string $pattern Pattern to match the file. Pattern will
also be removed from the key.
* @param int $levels Maximum number of recursive directories.
* @return array
* @internal
*/
protected function detectAll($folder, $pattern, $levels)
{
$path = trim(Folder::getRelativePath($folder), '/');
if (is_dir($folder)) {
// Find all system and user configuration files.
$options = [
'levels' => $levels,
'compare' => 'Filename',
'pattern' => $pattern,
'filters' => [
'pre-key' => $this->base,
'key' => $pattern,
'value' => function
(\RecursiveDirectoryIterator $file) use ($path) {
return
["{$path}/{$file->getSubPathname()}" =>
$file->getMTime()];
}
],
'key' => 'SubPathname'
];
$list = Folder::all($folder, $options);
ksort($list);
} else {
$list = [];
}
return $list;
}
}
PK���[��VVComponent/Config/Validation.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Config;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml;
/**
* Data validation.
*
* @author RocketTheme
* @license MIT
*/
class Validation
{
/**
* Validate value against a blueprint field definition.
*
* @param $value
* @param array $field
* @return array
*/
public static function validate($value, array $field)
{
$messages = [];
$validate = isset($field['validate']) ? (array)
$field['validate'] : [];
// If value isn't required, we will stop validation if empty
value is given.
if (empty($validate['required']) && ($value ===
null || $value === '')) {
return $messages;
}
if (!isset($field['type'])) {
$field['type'] = 'input.text';
}
// Special case for files, value is never empty and errors with
code 4 instead.
if (empty($validate['required']) &&
$field['type'] === 'input.file' &&
isset($value['error'])
&& ($value['error'] ===
UPLOAD_ERR_NO_FILE || \in_array(UPLOAD_ERR_NO_FILE,
$value['error'], true))) {
return $messages;
}
// Validate type with fallback type text.
$type = (string)
isset($field['validate']['type']) ?
$field['validate']['type'] : $field['type'];
$method = 'type_'.strtr($type, '-.',
'__');
if (!method_exists(__CLASS__, $method)) {
$method = 'type_Input_Text';
}
$name = ucfirst(isset($field['label']) ?
$field['label'] : $field['name']);
// TODO: translate
$message = (string)
isset($field['validate']['message'])
? sprintf($field['validate']['message'])
: sprintf('Invalid input in field: ') . '
"' . $name . '"';
$success = self::$method($value, $validate, $field);
if (!$success) {
$messages[$field['name']][] = $message;
}
// Check individual rules.
foreach ($validate as $rule => $params) {
$method = 'validate_' . ucfirst(strtr($rule,
'-.', '__'));
if (method_exists(__CLASS__, $method)) {
$success = self::$method($value, $params);
if (!$success) {
$messages[$field['name']][] = $message;
}
}
}
return $messages;
}
/**
* Filter value against a blueprint field definition.
*
* @param mixed $value
* @param array $field
* @return mixed Filtered value.
*/
public static function filter($value, array $field)
{
$validate = isset($field['validate']) ? (array)
$field['validate'] : [];
// If value isn't required, we will return null if empty value
is given.
if (($value === null || $value === '') &&
empty($validate['required'])) {
return null;
}
if (!isset($field['type'])) {
$field['type'] = 'input.text';
}
// Special case for files, value is never empty and errors with
code 4 instead.
if (empty($validate['required']) &&
$field['type'] === 'input.file' &&
isset($value['error'])
&& ($value['error'] === UPLOAD_ERR_NO_FILE ||
\in_array(UPLOAD_ERR_NO_FILE, $value['error'], true))) {
return null;
}
// Validate type with fallback type text.
$type = (string)
isset($field['validate']['type']) ?
$field['validate']['type'] : $field['type'];
$method = 'filter_' . ucfirst(str_replace('-',
'_', $type));
if (!method_exists(__CLASS__, $method)) {
$method = 'filter_Input_Text';
}
return self::$method($value, $validate, $field);
}
/**
* HTML5 input: text
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Text($value, array $params, array
$field)
{
if (!\is_string($value) && !is_numeric($value)) {
return false;
}
$value = (string)$value;
if (isset($params['min']) && \strlen($value) <
$params['min']) {
return false;
}
if (isset($params['max']) && \strlen($value) >
$params['max']) {
return false;
}
$min = isset($params['min']) ? $params['min'] :
0;
if (isset($params['step']) && (strlen($value) -
$min) % $params['step'] === 0) {
return false;
}
if ((!isset($params['multiline']) ||
!$params['multiline']) && preg_match('/\R/um',
$value)) {
return false;
}
return true;
}
protected static function filter_Input_Text($value, array $params,
array $field)
{
return (string) $value;
}
protected static function filter_Input_CommaList($value, array $params,
array $field)
{
return \is_array($value) ? $value :
preg_split('/\s*,\s*/', $value, -1, PREG_SPLIT_NO_EMPTY);
}
protected static function type_Input_CommaList($value, array $params,
array $field)
{
return \is_array($value) ? true : self::type_Input_Text($value,
$params, $field);
}
/**
* HTML5 input: textarea
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Textarea_Textarea($value, array $params,
array $field)
{
if (!isset($params['multiline'])) {
$params['multiline'] = true;
}
return self::type_Input_Text($value, $params, $field);
}
/**
* HTML5 input: password
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Password($value, array $params, array
$field)
{
return self::type_Input_Text($value, $params, $field);
}
/**
* HTML5 input: hidden
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Hidden($value, array $params, array
$field)
{
return self::type_Input_Text($value, $params, $field);
}
/**
* Custom input: checkbox list
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Checkboxes_Checkboxes($value, array
$params, array $field)
{
// Set multiple: true so checkboxes can easily use min/max counts
to control number of options required
$field['multiple'] = true;
return self::typeArray((array) $value, $params, $field);
}
protected static function filter_Checkboxes_Checkboxes($value, array
$params, array $field)
{
return self::filterArray($value, $params, $field);
}
/**
* HTML5 input: checkbox
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Checkbox($value, array $params, array
$field)
{
$value = (string) $value;
if (!isset($field['value'])) {
$field['value'] = 1;
}
if ($value && $value != $field['value']) {
return false;
}
return true;
}
/**
* HTML5 input: radio
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Radio($value, array $params, array
$field)
{
return self::typeArray((array) $value, $params, $field);
}
/**
* Custom input: toggle
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Toggle_Toggle($value, array $params, array
$field)
{
return self::typeArray((array) $value, $params, $field);
}
/**
* Custom input: file
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_File($value, array $params, array
$field)
{
return self::typeArray((array) $value, $params, $field);
}
protected static function filter_Input_File($value, array $params,
array $field)
{
if (isset($field['multiple']) &&
$field['multiple'] === true) {
return (array) $value;
}
if (\is_array($value)) {
return reset($value);
}
return $value;
}
/**
* HTML5 input: select
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Select_Select($value, array $params, array
$field)
{
return self::typeArray((array) $value, $params, $field);
}
/**
* HTML5 input: number
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Number($value, array $params, array
$field)
{
if (!is_numeric($value)) {
return false;
}
if (isset($params['min']) && $value <
$params['min']) {
return false;
}
if (isset($params['max']) && $value >
$params['max']) {
return false;
}
$min = isset($params['min']) ? $params['min'] :
0;
return !(isset($params['step']) && fmod($value -
$min, $params['step']) === 0);
}
protected static function filter_Input_Number($value, array $params,
array $field)
{
return (string)(int)$value !== (string)(float)$value ? (float)
$value : (int) $value;
}
protected static function filter_Input_DateTime($value, array $params,
array $field)
{
$converted = new \DateTime($value);
return $converted->format('Y-m-d H:i:s');
}
/**
* HTML5 input: range
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Range($value, array $params, array
$field)
{
return self::type_Input_Number($value, $params, $field);
}
protected static function filter_Input_Range($value, array $params,
array $field)
{
return self::filter_Input_Number($value, $params, $field);
}
/**
* HTML5 input: color
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Color($value, array $params, array
$field)
{
return preg_match('/^\#[0-9a-fA-F]{3}[0-9a-fA-F]{3}?$/u',
$value);
}
/**
* HTML5 input: email
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Email($value, array $params, array
$field)
{
return self::type_Input_Text($value, $params, $field) &&
filter_var($value, FILTER_VALIDATE_EMAIL);
}
/**
* HTML5 input: url
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Url($value, array $params, array
$field)
{
return self::type_Input_Text($value, $params, $field) &&
filter_var($value, FILTER_VALIDATE_URL);
}
/**
* HTML5 input: datetime
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Datetime($value, array $params, array
$field)
{
if ($value instanceof \DateTime) {
return true;
}
if (!\is_string($value)) {
return false;
}
if (!isset($params['format'])) {
return false !== strtotime($value);
}
$dateFromFormat =
\DateTime::createFromFormat($params['format'], $value);
return $dateFromFormat && $value ===
date($params['format'], $dateFromFormat->getTimestamp());
}
/**
* HTML5 input: datetime-local
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_DatetimeLocal($value, array $params,
array $field)
{
return self::type_Input_Datetime($value, $params, $field);
}
/**
* HTML5 input: date
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Date($value, array $params, array
$field)
{
if (!isset($params['format'])) {
$params['format'] = 'Y-m-d';
}
return self::type_Input_Datetime($value, $params, $field);
}
/**
* HTML5 input: time
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Time($value, array $params, array
$field)
{
if (!isset($params['format'])) {
$params['format'] = 'H:i';
}
return self::type_Input_Datetime($value, $params, $field);
}
/**
* HTML5 input: month
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Month($value, array $params, array
$field)
{
if (!isset($params['format'])) {
$params['format'] = 'Y-m';
}
return self::type_Input_Datetime($value, $params, $field);
}
/**
* HTML5 input: week
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Input_Week($value, array $params, array
$field)
{
if (!isset($params['format']) &&
!preg_match('/^\d{4}-W\d{2}$/u', $value)) {
return false;
}
return self::type_Input_Datetime($value, $params, $field);
}
/**
* Custom input: array
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeArray($value, array $params, array $field)
{
if (!\is_array($value)) {
return false;
}
if (isset($field['multiple'])) {
if (isset($params['min']) && \count($value)
< $params['min']) {
return false;
}
if (isset($params['max']) && \count($value)
> $params['max']) {
return false;
}
$min = isset($params['min']) ?
$params['min'] : 0;
if (isset($params['step']) && (\count($value)
- $min) % $params['step'] === 0) {
return false;
}
}
$options = isset($field['options']) ?
array_keys($field['options']) : [];
$values = isset($field['use']) &&
$field['use'] === 'keys' ? array_keys($value) : $value;
return !($options && array_diff($values, $options));
}
protected static function filterArray($value, $params, $field)
{
$values = (array) $value;
$options = isset($field['options']) ?
array_keys($field['options']) : [];
$multi = isset($field['multiple']) ?
$field['multiple'] : false;
if (\count($values) === 1 && isset($values[0]) &&
$values[0] === '') {
return null;
}
if ($options) {
$useKey = isset($field['use']) &&
$field['use'] === 'keys';
foreach ($values as $key => $val) {
$values[$key] = $useKey ? (bool) $val : $val;
}
}
if ($multi) {
foreach ($values as $key => $val) {
if (\is_array($val)) {
$val = implode(',', $val);
}
$values[$key] = array_map('trim',
explode(',', $val));
}
}
return $values;
}
public static function type_Input_Yaml($value, $params)
{
try {
Yaml::parse($value);
return true;
} catch (ParseException $e) {
return false;
}
}
public static function filter_Input_Yaml($value, $params)
{
try {
return (array) Yaml::parse($value);
} catch (ParseException $e) {
return null;
}
}
/**
* Custom input: ignore (will not validate)
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function type_Novalidate($value, array $params, array
$field)
{
return true;
}
public static function filter_Novalidate($value, array $params, array
$field)
{
return $value;
}
// HTML5 attributes (min, max and range are handled inside the types)
public static function validate_Required($value, $params)
{
if (is_scalar($value)) {
return (bool) $params !== true || $value !== '';
}
return (bool) $params !== true || !empty($value);
}
public static function validate_Pattern($value, $params)
{
return (bool) preg_match("`^{$params}$`u", $value);
}
// Internal types
public static function validate_Alpha($value, $params)
{
return ctype_alpha($value);
}
public static function validate_Alnum($value, $params)
{
return ctype_alnum($value);
}
public static function type_Bool($value, $params)
{
return \is_bool($value) || $value == 1 || $value == 0;
}
public static function validate_Bool($value, $params)
{
return \is_bool($value) || $value == 1 || $value == 0;
}
protected static function filter_Bool($value, $params)
{
return (bool) $value;
}
public static function validate_Digit($value, $params)
{
return ctype_digit($value);
}
public static function validate_Float($value, $params)
{
return \is_float(filter_var($value, FILTER_VALIDATE_FLOAT));
}
protected static function filter_Float($value, $params)
{
return (float) $value;
}
public static function validate_Hex($value, $params)
{
return ctype_xdigit($value);
}
public static function validate_Int($value, $params)
{
return is_numeric($value) && (int) $value == $value;
}
protected static function filter_Int($value, $params)
{
return (int) $value;
}
public static function validate_Array($value, $params)
{
return \is_array($value)
|| ($value instanceof \ArrayAccess
&& $value instanceof \Traversable
&& $value instanceof \Countable);
}
public static function validate_Json($value, $params)
{
return (bool) (@json_decode($value));
}
}
PK���[��"(Component/Config/ValidationException.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Config;
class ValidationException extends \RuntimeException
{
protected $messages = [];
public function setMessages(array $messages = []) {
$this->messages = $messages;
// TODO: add translation.
$this->message = sprintf('Form validation failed:') .
' ' . $this->message;
foreach ($messages as $variable => &$list) {
$list = array_unique($list);
foreach ($list as $message) {
$this->message .= "<br/>$message";
}
}
return $this;
}
public function getMessages()
{
return $this->messages;
}
}
PK���[#NJ���(Component/Content/Block/ContentBlock.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Content\Block;
/**
* Class to create nested blocks of content.
*
* $innerBlock = ContentBlock::create();
* $innerBlock->setContent('my inner content');
* $outerBlock = ContentBlock::create();
* $outerBlock->setContent(sprintf('Inside my outer block I have
%s.', $innerBlock->getToken()));
* $outerBlock->addBlock($innerBlock);
* echo $outerBlock;
*
* @package Gantry\Component\Content\Block
* @since 5.4.3
*/
class ContentBlock implements ContentBlockInterface
{
protected $version = 1;
protected $id;
protected $tokenTemplate = '@@BLOCK-%s@@';
protected $content = '';
protected $blocks = [];
/**
* @param string $id
* @return static
* @since 5.4.3
*/
public static function create($id = null)
{
return new static($id);
}
/**
* @param array $serialized
* @return ContentBlockInterface
* @since 5.4.3
*/
public static function fromArray(array $serialized)
{
try {
$type = isset($serialized['_type']) ?
$serialized['_type'] : null;
$id = isset($serialized['id']) ?
$serialized['id'] : null;
if (!$type || !$id || !is_a($type,
'Gantry\Component\Content\Block\ContentBlockInterface', true)) {
throw new \RuntimeException('Bad data');
}
/** @var ContentBlockInterface $instance */
$instance = new $type($id);
$instance->build($serialized);
} catch (\Exception $e) {
throw new \RuntimeException(sprintf('Cannot unserialize
Block: %s', $e->getMessage()), $e->getCode(), $e);
}
return $instance;
}
/**
* Block constructor.
*
* @param string $id
* @since 5.4.3
*/
public function __construct($id = null)
{
$this->id = $id ? (string) $id : $this->generateId();
}
/**
* @return string
* @since 5.4.3
*/
public function getId()
{
return $this->id;
}
/**
* @return string
* @since 5.4.3
*/
public function getToken()
{
return sprintf($this->tokenTemplate, $this->getId());
}
/**
* @return array
* @since 5.4.3
*/
public function toArray()
{
$blocks = [];
/**
* @var string $id
* @var ContentBlockInterface $block
*/
foreach ($this->blocks as $block) {
$blocks[$block->getId()] = $block->toArray();
}
$array = [
'_type' => get_class($this),
'_version' => $this->version,
'id' => $this->id,
];
if ($this->content) {
$array['content'] = $this->content;
}
if ($blocks) {
$array['blocks'] = $blocks;
}
return $array;
}
/**
* @return string
* @since 5.4.3
*/
public function toString()
{
if (!$this->blocks) {
return (string) $this->content;
}
$tokens = [];
$replacements = [];
foreach ($this->blocks as $block) {
$tokens[] = $block->getToken();
$replacements[] = $block->toString();
}
return str_replace($tokens, $replacements, (string)
$this->content);
}
/**
* @return string
* @since 5.4.3
*/
public function __toString()
{
try {
return $this->toString();
} catch (\Exception $e) {
return sprintf('Error while rendering block: %s',
$e->getMessage());
}
}
/**
* @param array $serialized
* @since 5.4.3
*/
public function build(array $serialized)
{
$this->checkVersion($serialized);
$this->id = isset($serialized['id']) ?
$serialized['id'] : $this->generateId();
if (isset($serialized['content'])) {
$this->setContent($serialized['content']);
}
$blocks = isset($serialized['blocks']) ? (array)
$serialized['blocks'] : [];
foreach ($blocks as $block) {
$this->addBlock(self::fromArray($block));
}
}
/**
* @param string $content
* @return $this
* @since 5.4.3
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* @param ContentBlockInterface $block
* @return $this
* @since 5.4.3
*/
public function addBlock(ContentBlockInterface $block)
{
$this->blocks[$block->getId()] = $block;
return $this;
}
/**
* @return string
* @since 5.4.3
*/
public function serialize()
{
return serialize($this->toArray());
}
/**
* @param string $serialized
* @since 5.4.3
*/
public function unserialize($serialized)
{
$array = unserialize($serialized);
$this->build($array);
}
/**
* @return string
* @since 5.4.3
*/
protected function generateId()
{
return uniqid('', true);
}
/**
* @param array $serialized
* @throws \RuntimeException
* @since 5.4.3
*/
protected function checkVersion(array $serialized)
{
$version = isset($serialized['_version']) ? (string)
$serialized['_version'] : 1;
if ($version != $this->version) {
throw new \RuntimeException(sprintf('Unsupported version
%s', $version));
}
}
}PK���[{�?:xx1Component/Content/Block/ContentBlockInterface.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Content\Block;
/**
* @since 5.4.3
*/
interface ContentBlockInterface extends \Serializable
{
public static function create($id = null);
public static function fromArray(array $serialized);
public function __construct($id = null);
public function getId();
public function getToken();
public function toArray();
public function build(array $serialized);
public function setContent($content);
public function addBlock(ContentBlockInterface $block);
}PK���[��ue�2�2%Component/Content/Block/HtmlBlock.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Content\Block;
use Gantry\Framework\Document;
use Gantry\Framework\Gantry;
use Gantry\Framework\Theme;
/**
* Class HtmlBlock
* @package Gantry\Component\Content\Block
* @since 5.4.3
*/
class HtmlBlock extends ContentBlock implements HtmlBlockInterface
{
protected $version = 1;
protected $frameworks = [];
protected $styles = [];
protected $scripts = [];
protected $html = [];
/**
* @return array
* @since 5.4.3
*/
public function getAssets()
{
$assets = $this->getAssetsFast();
$this->sortAssets($assets['styles']);
$this->sortAssets($assets['scripts']);
$this->sortAssets($assets['html']);
return $assets;
}
/**
* @return array
* @since 5.4.3
*/
public function getFrameworks()
{
$assets = $this->getAssetsFast();
return array_keys($assets['frameworks']);
}
/**
* @param string $location
* @return array
* @since 5.4.3
*/
public function getStyles($location = 'head')
{
$styles = $this->getAssetsInLocation('styles',
$location);
if (!$styles) {
return [];
}
$gantry = Gantry::instance();
/** @var Theme $theme */
$theme = isset($gantry['theme']) ?
$gantry['theme'] : null;
/** @var Document $document */
$document = $gantry['document'];
foreach ($styles as $key => $style) {
if (isset($style['href'])) {
$url = $style['href'];
if ($theme && preg_match('|\.scss$|',
$url)) {
// Compile SCSS files.
$url = $theme->css(basename($url,
'.scss'));
}
// Deal with streams and relative paths.
$url = $document->url($url, false, null, false);
$styles[$key]['href'] = $url;
}
}
return $styles;
}
/**
* @param string $location
* @return array
* @since 5.4.3
*/
public function getScripts($location = 'head')
{
$scripts = $this->getAssetsInLocation('scripts',
$location);
if (!$scripts) {
return [];
}
$gantry = Gantry::instance();
/** @var Document $document */
$document = $gantry['document'];
foreach ($scripts as $key => $script) {
if (isset($script['src'])) {
// Deal with streams and relative paths.
$scripts[$key]['src'] =
$document->url($script['src'], false, null, false);
}
}
return $scripts;
}
/**
* @param string $location
* @return array
* @since 5.4.3
*/
public function getHtml($location = 'bottom')
{
return $this->getAssetsInLocation('html', $location);
}
/**
* @return array
* @since 5.4.3
*/
public function toArray()
{
$array = parent::toArray();
if ($this->frameworks) {
$array['frameworks'] = $this->frameworks;
}
if ($this->styles) {
$array['styles'] = $this->styles;
}
if ($this->scripts) {
$array['scripts'] = $this->scripts;
}
if ($this->html) {
$array['html'] = $this->html;
}
return $array;
}
/**
* @param array $serialized
* @since 5.4.3
*/
public function build(array $serialized)
{
parent::build($serialized);
$this->frameworks = isset($serialized['frameworks']) ?
(array) $serialized['frameworks'] : [];
$this->styles = isset($serialized['styles']) ? (array)
$serialized['styles'] : [];
$this->scripts = isset($serialized['scripts']) ?
(array) $serialized['scripts'] : [];
$this->html = isset($serialized['html']) ? (array)
$serialized['html'] : [];
}
/**
* @param string $framework
* @return $this
* @since 5.4.3
*/
public function addFramework($framework)
{
$this->frameworks[$framework] = 1;
return $this;
}
/**
* @param string|array $element
* @param int $priority
* @param string $location
* @return bool
*
* @example $block->addStyle('assets/js/my.js');
* @example $block->addStyle(['href' =>
'assets/js/my.js', 'media' => 'screen']);
* @since 5.4.3
*/
public function addStyle($element, $priority = 0, $location =
'head')
{
if (!is_array($element)) {
$element = ['href' => (string) $element];
}
if (empty($element['href'])) {
return false;
}
if (!isset($this->styles[$location])) {
$this->styles[$location] = [];
}
$id = !empty($element['id']) ? ['id' =>
(string) $element['id']] : [];
$href = $element['href'];
$type = !empty($element['type']) ? (string)
$element['type'] : 'text/css';
$media = !empty($element['media']) ? (string)
$element['media'] : null;
unset($element['tag'], $element['id'],
$element['rel'], $element['content'],
$element['href'], $element['type'],
$element['media']);
$this->styles[$location][md5($href) . sha1($href)] = [
':type' => 'file',
':priority' => (int) $priority,
'href' => $href,
'type' => $type,
'media' => $media,
'element' => $element
] + $id;
return true;
}
/**
* @param string|array $element
* @param int $priority
* @param string $location
* @return bool
* @since 5.4.3
*/
public function addInlineStyle($element, $priority = 0, $location =
'head')
{
if (!is_array($element)) {
$element = ['content' => (string) $element];
}
if (empty($element['content'])) {
return false;
}
if (!isset($this->styles[$location])) {
$this->styles[$location] = [];
}
$content = (string) $element['content'];
$type = !empty($element['type']) ? (string)
$element['type'] : 'text/css';
$this->styles[$location][md5($content) . sha1($content)] = [
':type' => 'inline',
':priority' => (int) $priority,
'content' => $content,
'type' => $type
];
return true;
}
/**
* @param string|array $element
* @param int $priority
* @param string $location
* @return bool
* @since 5.4.3
*/
public function addScript($element, $priority = 0, $location =
'head')
{
if (!is_array($element)) {
$element = ['src' => (string) $element];
}
if (empty($element['src'])) {
return false;
}
if (!isset($this->scripts[$location])) {
$this->scripts[$location] = [];
}
$src = $element['src'];
$type = !empty($element['type']) ? (string)
$element['type'] : 'text/javascript';
$defer = isset($element['defer']) ? true : false;
$async = isset($element['async']) ? true : false;
$handle = !empty($element['handle']) ? (string)
$element['handle'] : '';
$this->scripts[$location][md5($src) . sha1($src)] = [
':type' => 'file',
':priority' => (int) $priority,
'src' => $src,
'type' => $type,
'defer' => $defer,
'async' => $async,
'handle' => $handle
];
return true;
}
/**
* @param string|array $element
* @param int $priority
* @param string $location
* @return bool
* @since 5.4.3
*/
public function addInlineScript($element, $priority = 0, $location =
'head')
{
if (!is_array($element)) {
$element = ['content' => (string) $element];
}
if (empty($element['content'])) {
return false;
}
if (!isset($this->scripts[$location])) {
$this->scripts[$location] = [];
}
$content = (string) $element['content'];
$type = !empty($element['type']) ? (string)
$element['type'] : 'text/javascript';
$this->scripts[$location][md5($content) . sha1($content)] = [
':type' => 'inline',
':priority' => (int) $priority,
'content' => $content,
'type' => $type
];
return true;
}
/**
* @param string $html
* @param int $priority
* @param string $location
* @return bool
* @since 5.4.3
*/
public function addHtml($html, $priority = 0, $location =
'bottom')
{
if (empty($html) || !is_string($html)) {
return false;
}
if (!isset($this->html[$location])) {
$this->html[$location] = [];
}
$this->html[$location][md5($html) . sha1($html)] = [
':priority' => (int) $priority,
'html' => $html
];
return true;
}
/**
* @param string $location
* @deprecated Temporarily needed in WP
* @since 5.4.3
*/
public function clearStyles($location = 'head')
{
foreach ($this->blocks as $block) {
if (method_exists($block, 'clearStyles')) {
$block->clearStyles($location);
}
}
unset($this->styles[$location]);
}
/**
* @param string $location
* @deprecated Temporarily needed in WP
* @since 5.4.3
*/
public function clearScripts($location = 'head')
{
foreach ($this->blocks as $block) {
if (method_exists($block, 'clearScripts')) {
$block->clearScripts($location);
}
}
unset($this->scripts[$location]);
}
/**
* @return array
* @since 5.4.3
*/
protected function getAssetsFast()
{
$assets = [
'frameworks' => $this->frameworks,
'styles' => $this->styles,
'scripts' => $this->scripts,
'html' => $this->html
];
foreach ($this->blocks as $block) {
if ($block instanceof HtmlBlock) {
$blockAssets = $block->getAssetsFast();
$assets['frameworks'] +=
$blockAssets['frameworks'];
foreach ($blockAssets['styles'] as $location
=> $styles) {
if (!isset($assets['styles'][$location])) {
$assets['styles'][$location] = $styles;
} elseif ($styles) {
$assets['styles'][$location] += $styles;
}
}
foreach ($blockAssets['scripts'] as $location
=> $scripts) {
if (!isset($assets['scripts'][$location])) {
$assets['scripts'][$location] = $scripts;
} elseif ($scripts) {
$assets['scripts'][$location] +=
$scripts;
}
}
foreach ($blockAssets['html'] as $location =>
$htmls) {
if (!isset($assets['html'][$location])) {
$assets['html'][$location] = $htmls;
} elseif ($htmls) {
$assets['html'][$location] += $htmls;
}
}
}
}
return $assets;
}
/**
* @param string $type
* @param string $location
* @return array
* @since 5.4.3
*/
protected function getAssetsInLocation($type, $location)
{
$assets = $this->getAssetsFast();
if (empty($assets[$type][$location])) {
return [];
}
$styles = $assets[$type][$location];
$this->sortAssetsInLocation($styles);
return $styles;
}
/**
* @param array $items
* @since 5.4.3
*/
protected function sortAssetsInLocation(array &$items)
{
$count = 0;
foreach ($items as &$item) {
$item[':order'] = ++$count;
}
uasort(
$items,
function ($a, $b) {
return ($a[':priority'] ==
$b[':priority']) ? $a[':order'] -
$b[':order'] : $b[':priority'] -
$a[':priority'];
}
);
}
/**
* @param array $array
* @since 5.4.3
*/
protected function sortAssets(array &$array)
{
foreach ($array as $location => &$items) {
$this->sortAssetsInLocation($items);
}
}
}PK���[�v*B��.Component/Content/Block/HtmlBlockInterface.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Content\Block;
/**
* @since 5.4.3
*/
interface HtmlBlockInterface extends ContentBlockInterface
{
public function getAssets();
public function addFramework($framework);
public function addStyle($element, $priority = 0, $location =
'head');
public function addInlineStyle($element, $priority = 0, $location =
'head');
public function addScript($element, $priority = 0, $location =
'head');
public function addInlineScript($element, $priority = 0, $location =
'head');
public function addHtml($html, $priority = 0, $location =
'bottom');
}
PK���[ �Q��i�i+Component/Content/Document/HtmlDocument.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Content\Document;
use Gantry\Component\Content\Block\ContentBlock;
use Gantry\Component\Content\Block\HtmlBlock;
use Gantry\Component\Gantry\GantryTrait;
use Gantry\Component\Url\Url;
use Gantry\Framework\Gantry;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class HtmlDocument
{
use GantryTrait;
public static $timestamp_age = 604800;
public static $urlFilterParams;
/**
* @var array|HtmlBlock[]
*/
protected static $stack;
protected static $frameworks = [];
protected static $scripts = [];
protected static $styles = [];
protected static $availableFrameworks = [
'jquery' => 'registerJquery',
'jquery.framework' => 'registerJquery',
'jquery.ui.core' =>
'registerJqueryUiSortable',
'jquery.ui.sortable' =>
'registerJqueryUiSortable',
'bootstrap.2' => 'registerBootstrap2',
'bootstrap.3' => 'registerBootstrap3',
'mootools' => 'registerMootools',
'mootools.framework' => 'registerMootools',
'mootools.core' => 'registerMootools',
'mootools.more' => 'registerMootoolsMore',
'lightcase' => 'registerLightcase',
'lightcase.init' => 'registerLightcaseInit',
];
public function __construct()
{
static::$stack = [];
static::push();
}
/**
* Create new local instance of document allowing asset caching.
*/
public static function push()
{
array_unshift(static::$stack, new HtmlBlock());
}
/**
* Return local instance of document allowing it to be cached.
*
* @return HtmlBlock
*/
public static function pop()
{
return array_shift(static::$stack);
}
/**
* @param ContentBlock $block
* @return $this
*/
public function addBlock(ContentBlock $block)
{
static::$stack[0]->addBlock($block);
return $this;
}
/**
* @param string $framework
* @return bool
*/
public static function addFramework($framework)
{
if (!isset(static::$availableFrameworks[$framework])) {
return false;
}
static::getObject();
static::$stack[0]->addFramework($framework);
return true;
}
/**
* @param string|array $element
* @param int $priority
* @param string $location
* @return bool
*/
public static function addStyle($element, $priority = 0, $location =
'head')
{
static::getObject();
return static::$stack[0]->addStyle($element, $priority,
$location);
}
/**
* @param string|array $element
* @param int $priority
* @param string $location
* @return bool
*/
public static function addInlineStyle($element, $priority = 0,
$location = 'head')
{
static::getObject();
return static::$stack[0]->addInlineStyle($element, $priority,
$location);
}
/**
* @param string|array $element
* @param int $priority
* @param string $location
* @return bool
*/
public static function addScript($element, $priority = 0, $location =
'head')
{
static::getObject();
return static::$stack[0]->addScript($element, $priority,
$location);
}
/**
* @param string|array $element
* @param int $priority
* @param string $location
* @return bool
*/
public static function addInlineScript($element, $priority = 0,
$location = 'head')
{
static::getObject();
return static::$stack[0]->addInlineScript($element, $priority,
$location);
}
/**
* @param string $html
* @param int $priority
* @param string $location
* @return bool
*/
public static function addHtml($html, $priority = 0, $location =
'bottom')
{
static::getObject();
return static::$stack[0]->addHtml($html, $priority, $location);
}
/**
* @param array $element
* @param string $location
* @param int $priority
* @return bool
*/
public static function addHeaderTag(array $element, $location =
'head', $priority = 0)
{
$success = false;
switch ($element['tag']) {
case 'link':
if (!empty($element['rel']) &&
$element['rel'] === 'stylesheet') {
$success = static::addStyle($element, $priority,
$location);
}
break;
case 'style':
$success = static::addInlineStyle($element, $priority,
$location);
break;
case 'script':
if (!empty($element['src'])) {
$success = static::addScript($element, $priority,
$location);
} elseif (!empty($element['content'])) {
$success = static::addInlineScript($element, $priority,
$location);
}
break;
}
return $success;
}
public static function getStyles($location = 'head')
{
static::getObject();
$styles = static::$stack[0]->getStyles($location);
$output = [];
foreach ($styles as $style) {
switch ($style[':type']) {
case 'file':
$attribs = '';
if ($style['media']) {
$attribs .= ' media="' .
static::escape($style['media']) . '"';
}
$output[] = sprintf(
'<link rel="stylesheet"
href="%s" type="%s"%s />',
static::escape($style['href']),
static::escape($style['type']),
$attribs
);
break;
case 'inline':
$attribs = '';
if ($style['type'] !== 'text/css')
{
$attribs .= ' type="' .
static::escape($style['type']) . '"';
}
$output[] = sprintf(
'<style%s>%s</style>',
$attribs,
$style['content']
);
break;
}
}
return $output;
}
public static function getScripts($location = 'head')
{
static::getObject();
$scripts = static::$stack[0]->getScripts($location);
$output = [];
foreach ($scripts as $script) {
switch ($script[':type']) {
case 'file':
$attribs = '';
if ($script['async']) {
$attribs .= ' async="async"';
}
if ($script['defer']) {
$attribs .= ' defer="defer"';
}
$output[] = sprintf(
'<script type="%s"%s
src="%s"></script>',
static::escape($script['type']),
$attribs,
static::escape($script['src'])
);
break;
case 'inline':
$output[] = sprintf(
'<script
type="%s">%s</script>',
static::escape($script['type']),
$script['content']
);
break;
}
}
return $output;
}
public static function getHtml($location = 'bottom')
{
static::getObject();
$htmls = static::$stack[0]->getHtml($location);
$output = [];
foreach ($htmls as $html) {
$output[] = $html['html'];
}
return $output;
}
/**
* Escape string (emulates twig filter).
*
* @param string|object $string
* @param string $strategy
* @return string
*/
public static function escape($string, $strategy = 'html')
{
if (!is_string($string)) {
if (is_object($string) && method_exists($string,
'__toString')) {
$string = (string) $string;
} elseif (in_array($strategy, ['html',
'js', 'css', 'html_attr', 'url']))
{
return $string;
}
}
switch ($strategy) {
case 'html':
return htmlspecialchars($string, ENT_QUOTES |
ENT_SUBSTITUTE, 'UTF-8');
case 'js':
if (0 === strlen($string) ? false : (1 ===
preg_match('/^./su', $string) ? false : true)) {
throw new \RuntimeException('The string to escape
is not a valid UTF-8 string.');
}
$string = preg_replace_callback(
'#[^a-zA-Z0-9,\._]#Su',
'Gantry\\Component\\Content\\Document\\HtmlDocument::_escape_js_callback',
$string
);
return $string;
case 'css':
if (0 === strlen($string) ? false : (1 ===
preg_match('/^./su', $string) ? false : true)) {
throw new \RuntimeException('The string to escape
is not a valid UTF-8 string.');
}
$string = preg_replace_callback(
'#[^a-zA-Z0-9]#Su',
'Gantry\\Component\\Content\\Document\\HtmlDocument::_escape_css_callback',
$string
);
return $string;
case 'html_attr':
if (0 === strlen($string) ? false : (1 ===
preg_match('/^./su', $string) ? false : true)) {
throw new \RuntimeException('The string to escape
is not a valid UTF-8 string.');
}
$string = preg_replace_callback(
'#[^a-zA-Z0-9,\.\-_]#Su',
'Gantry\\Component\\Content\\Document\\HtmlDocument::_escape_html_attr_callback',
$string
);
return $string;
case 'url':
return rawurlencode($string);
default:
throw new \RuntimeException(sprintf('Invalid escaping
strategy "%s" (valid ones: html, js, css, html_attr, url).',
$strategy));
}
}
/**
* @param $framework
* @return bool
* @deprecated 5.3
*/
public static function load($framework)
{
return static::addFramework($framework);
}
/**
* Register assets.
*/
public static function registerAssets()
{
static::registerFrameworks();
}
public static function siteUrl()
{
return static::rootUri();
}
/**
* NOTE: In PHP this function can be called either from Gantry DI
container or statically.
*
* @return string
*/
public static function rootUri()
{
return '';
}
/**
* NOTE: In PHP this function can be called either from Gantry DI
container or statically.
*
* @param bool $addDomain
* @return string
*/
public static function domain($addDomain = false)
{
return '';
}
/**
* Return URL to the resource.
*
* @example {{
url('gantry-theme://images/logo.png')|default('http://www.placehold.it/150x100/f4f4f4')
}}
*
* NOTE: In PHP this function can be called either from Gantry DI
container or statically.
*
* @param string $url Resource to be located.
* @param bool $domain True to include domain name.
* @param int $timestamp_age Append timestamp to files that are less
than x seconds old. Defaults to a week.
* Use value <= 0 to disable the
feature.
* @param bool $allowNull True if non-existing files should return
null.
* @return string|null Returns url to the resource or null if
resource was not found.
*/
public static function url($url, $domain = false, $timestamp_age =
null, $allowNull = true)
{
if (!is_string($url) || $url === '') {
// Return null on invalid input.
return null;
}
if ($url[0] === '#' || $url[0] === '?') {
// Handle urls with query string or fragment only.
return str_replace(' ', '%20', $url);
}
$parts = Url::parse($url);
if (!is_array($parts)) {
// URL could not be parsed.
return $allowNull ? null : str_replace(' ',
'%20', $url);
}
// Make sure we always have scheme, host, port and path.
$scheme = isset($parts['scheme']) ?
$parts['scheme'] : '';
$host = isset($parts['host']) ? $parts['host']
: '';
$port = isset($parts['port']) ? $parts['port']
: '';
$path = isset($parts['path']) ? $parts['path']
: '';
if ($scheme && !$port) {
// If URL has a scheme, we need to check if it's one of
Gantry streams.
$gantry = static::gantry();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
if (!$locator->schemeExists($scheme)) {
// If scheme does not exists as a stream, assume it's
external.
return str_replace(' ', '%20', $url);
}
// Attempt to find the resource (because of parse_url() we need
to put host back to path).
$newPath =
$locator->findResource("{$scheme}://{$host}{$path}", false);
if ($newPath === false) {
if ($allowNull) {
return null;
}
// Return location where the file would be if it was saved.
$path =
$locator->findResource("{$scheme}://{$host}{$path}", false,
true);
} else {
$path = $newPath;
}
} elseif ($host || $port) {
// If URL doesn't have scheme but has host or port, it is
external.
return str_replace(' ', '%20', $url);
}
// At this point URL is either relative or absolute path; let us
find if it is relative and not . or ..
if ($path && '/' !== $path[0] &&
'.' !== $path[0]) {
if ($timestamp_age === null) {
$timestamp_age = static::$timestamp_age;
}
if ($timestamp_age > 0) {
// We want to add timestamp to the URI: do it only for
existing files.
$realPath = @realpath(GANTRY5_ROOT . '/' .
$path);
if ($realPath && is_file($realPath)) {
$time = filemtime($realPath);
// Only append timestamp for files that are less than
the maximum age.
if ($time > time() - $timestamp_age) {
$parts['query'] =
(!empty($parts['query']) ?
"{$parts['query']}&" : '') .
sprintf('%x', $time);
}
}
}
// We need absolute URI instead of relative.
$path = rtrim(static::rootUri(), '/') . '/'
. $path;
}
// Set absolute URI.
$uri = $path;
// Add query string back.
if (!empty($parts['query'])) {
if (!$uri) $uri = static::rootUri();
$uri .= '?' . $parts['query'];
}
// Add fragment back.
if (!empty($parts['fragment'])) {
if (!$uri) $uri = static::rootUri();
$uri .= '#' . $parts['fragment'];
}
return static::domain($domain) . str_replace(' ',
'%20', $uri);
}
/**
* Filter stream URLs from HTML.
*
* @param string $html HTML input to be filtered.
* @param bool $domain True to include domain name.
* @param int $timestamp_age Append timestamp to files that are less
than x seconds old. Defaults to a week.
* Use value <= 0 to disable the
feature.
* @param bool $streamOnly Only touch streams.
* @return string Returns modified HTML.
*/
public static function urlFilter($html, $domain = false, $timestamp_age
= null, $streamOnly = false)
{
static::$urlFilterParams = [$domain, $timestamp_age, $streamOnly];
// Tokenize all PRE, CODE and SCRIPT tags to avoid modifying any
src|href|url in them
$tokens = [];
$html =
preg_replace_callback('#<(pre|code|script)(\s[^>]+)?>.*?</\\1>#ius',
function($matches) use (&$tokens) {
// Unfortunately uniqid() doesn't quite work in Windows,
so we need to work it around by adding some randomness.
$token = '@@'. uniqid(mt_rand(), true) .
'@@';
$match = $matches[0];
$tokens[$token] = $match;
return $token;
}, $html);
if ($streamOnly) {
$gantry = static::gantry();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$schemes = $locator->getSchemes();
$list = [];
foreach ($schemes as $scheme) {
if (strpos($scheme, 'gantry-') === 0) {
$list[] = substr($scheme, 7);
}
}
if (empty($list)) {
return $html;
}
$match = '(gantry-(' . implode('|', $list).
')://.*?)';
} else {
$match = '(.*?)';
}
$html = preg_replace_callback('^(\s)(src|href)="' .
$match . '"^u', 'static::linkHandler', $html);
$html = preg_replace_callback('^(\s)url\(' . $match .
'\)^u', 'static::urlHandler', $html);
$html = static::replaceTokens($tokens, $html);
return $html;
}
/**
* @param array $matches
* @return string
* @internal
*/
public static function linkHandler(array $matches)
{
list($domain, $timestamp_age) = static::$urlFilterParams;
$url = trim($matches[3]);
$url = static::url($url, $domain, $timestamp_age, false);
return "{$matches[1]}{$matches[2]}=\"{$url}\"";
}
/**
* @param array $matches
* @return string
* @internal
*/
public static function urlHandler(array $matches)
{
list($domain, $timestamp_age) = static::$urlFilterParams;
$url = trim($matches[2], '"\'');
$url = static::url($url, $domain, $timestamp_age, false);
return "{$matches[1]}url({$url})";
}
/**
* This function is adapted from code coming from Twig.
*
* @param array $matches
* @return string
* @internal
*/
public static function _escape_js_callback($matches)
{
$char = $matches[0];
/*
* A few characters have short escape sequences in JSON and
JavaScript.
* Escape sequences supported only by JavaScript, not JSON, are
ommitted.
* \" is also supported but omitted, because the resulting
string is not HTML safe.
*/
static $shortMap = [
'\\' => '\\\\',
'/' => '\\/',
"\x08" => '\b',
"\x0C" => '\f',
"\x0A" => '\n',
"\x0D" => '\r',
"\x09" => '\t',
];
if (isset($shortMap[$char])) {
return $shortMap[$char];
}
// \uHHHH
$char = static::convert_encoding($char, 'UTF-16BE',
'UTF-8');
$char = strtoupper(bin2hex($char));
if (4 >= \strlen($char)) {
return sprintf('\u%04s', $char);
}
return sprintf('\u%04s\u%04s', substr($char, 0, -4),
substr($char, -4));
}
/**
* This function is adapted from code coming from Twig.
*
* @param $matches
* @return string
* @internal
*/
public static function _escape_css_callback($matches)
{
$char = $matches[0];
return sprintf('\\%X ', 1 === \strlen($char) ?
\ord($char) : static::ord($char));
}
/**
* This function is adapted from code coming from Twig and Zend
Framework.
*
* @param array $matches
* @return string
*
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc.
(https://www.zend.com)
* @license https://framework.zend.com/license/new-bsd New BSD
License
* @internal
*/
public static function _escape_html_attr_callback($matches)
{
$chr = $matches[0];
$ord = \ord($chr);
/*
* The following replaces characters undefined in HTML with the
* hex entity for the Unicode replacement character.
*/
if (($ord <= 0x1f && "\t" !== $chr &&
"\n" !== $chr && "\r" !== $chr) || ($ord >=
0x7f && $ord <= 0x9f)) {
return '�';
}
/*
* Check if the current character to escape has a name entity we
should
* replace it with while grabbing the hex value of the character.
*/
if (1 === \strlen($chr)) {
/*
* While HTML supports far more named entities, the lowest
common denominator
* has become HTML5's XML Serialisation which is
restricted to the those named
* entities that XML supports. Using HTML entities would result
in this error:
* XML Parsing Error: undefined entity
*/
static $entityMap = [
34 => '"', /* quotation mark */
38 => '&', /* ampersand */
60 => '<', /* less-than sign */
62 => '>', /* greater-than sign */
];
if (isset($entityMap[$ord])) {
return $entityMap[$ord];
}
return sprintf('&#x%02X;', $ord);
}
/*
* Per OWASP recommendations, we'll use hex entities for any
other
* characters where a named entity does not exist.
*/
return sprintf('&#x%04X;', static::ord($chr));
}
/**
* Replace tokens with strings.
*
* @param array $tokens
* @param $html
* @return string|NUll
*/
protected static function replaceTokens(array $tokens, $html)
{
foreach ($tokens as $token => $replacement) {
// We need to use callbacks to turn off backreferences ($1,
\\1) in the replacement string.
$callback = function() use ($replacement) { return
$replacement; };
$html = preg_replace_callback('#' .
preg_quote($token, '#') . '#u', $callback, $html);
}
return $html;
}
/**
* Register loaded frameworks.
*/
protected static function registerFrameworks()
{
foreach (static::$stack[0]->getFrameworks() as $framework) {
if (isset(static::$availableFrameworks[$framework])) {
call_user_func([get_called_class(),
static::$availableFrameworks[$framework]]);
}
}
}
protected static function registerJquery()
{
static::addScript(
[
'src' =>
'https://code.jquery.com/jquery-2.2.2.min.js',
'integrity' =>
'sha256-36cp2Co+/62rEAAYHLmRCPIych47CvdM+uTBJwSzWjI=',
'crossorigin' => 'anonymous'
],
11
);
}
protected static function registerJqueryUiSortable()
{
static::registerJquery();
static::addScript(
[
'src' =>
'https://code.jquery.com/ui/1.11.4/jquery-ui.min.js',
'integrity' =>
'sha256-xNjb53/rY+WmG+4L6tTl9m6PpqknWZvRt0rO1SRnJzw=',
'crossorigin' => 'anonymous'
],
11
);
}
protected static function registerBootstrap2()
{
static::registerJquery();
static::addScript(['src' =>
'https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js'],
11);
}
protected static function registerBootstrap3()
{
static::registerJquery();
static::addScript(['src' =>
'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'],
11);
}
protected static function registerMootools()
{
static::addScript(['src' =>
'https://cdnjs.cloudflare.com/ajax/libs/mootools/1.5.2/mootools-core-compat.min.js'],
11);
}
protected static function registerMootoolsMore()
{
static::registerMootools();
static::addScript(['src' =>
'https://cdnjs.cloudflare.com/ajax/libs/mootools-more/1.5.2/mootools-more-compat-compressed.js'],
11);
}
protected static function registerLightcase()
{
static::registerJquery();
static::addScript(['src' =>
static::url('gantry-assets://js/lightcase.js', false, null,
false)], 11, 'footer');
static::addStyle(['href' =>
static::url('gantry-assets://css/lightcase.css', false, null,
false)], 11);
}
protected static function registerLightcaseInit()
{
static::registerLightcase();
static::addInlineScript(['content' =>
"jQuery(document).ready(function($) {
jQuery('[data-rel^=lightcase]').lightcase({maxWidth:
'100%', maxHeight: '100%', video: {width:
'1280', height: '720'}}); });"], 0,
'footer');
}
protected static function getObject()
{
static $object;
if (!$object) {
// We need to initialize document for backwards compatibility
(RokSprocket/RokGallery in WP).
$object = Gantry::instance()['document'];
}
return $object;
}
/**
* @param string $string
* @param string $to
* @param string $from
* @return false|string|string[]|null
* @internal
*/
private static function convert_encoding($string, $to, $from)
{
if (\function_exists('mb_convert_encoding')) {
return mb_convert_encoding($string, $to, $from);
}
if (\function_exists('iconv')) {
return iconv($from, $to, $string);
}
throw new \RuntimeException('No suitable convert encoding
function (use UTF-8 as your encoding or install the iconv or mbstring
extension).');
}
/**
* @param string $string
* @return false|int|mixed
* @internal
*/
private static function ord($string)
{
if (\function_exists('mb_ord')) {
return mb_ord($string, 'UTF-8');
}
$code = ($string = unpack('C*', substr($string, 0, 4))) ?
$string[1] : 0;
if (0xF0 <= $code) {
return (($code - 0xF0) << 18) + (($string[2] - 0x80)
<< 12) + (($string[3] - 0x80) << 6) + $string[4] - 0x80;
}
if (0xE0 <= $code) {
return (($code - 0xE0) << 12) + (($string[2] - 0x80)
<< 6) + $string[3] - 0x80;
}
if (0xC0 <= $code) {
return (($code - 0xC0) << 6) + $string[2] - 0x80;
}
return $code;
}
}
PK���[,���'Component/Controller/BaseController.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Controller;
use Gantry\Framework\Request;
use RocketTheme\Toolbox\DI\Container;
use RuntimeException;
abstract class BaseController implements RestfulControllerInterface
{
/**
* @var string Default HTTP method.
*/
protected $method = 'GET';
/**
* @var Request
*/
protected $request;
/**
* @var array List of HTTP verbs and their actions.
*/
protected $httpVerbs = [
'GET' => [
'/' => 'index',
'/create' => 'create',
'/*' => 'display',
'/*/edit' => 'edit'
],
'POST' => [
'/' => 'store'
],
'PUT' => [
'/*' => 'replace'
],
'PATCH' => [
'/*' => 'update'
],
'DELETE' => [
'/*' => 'destroy'
]
];
/**
* @var array Parameters from router.
*/
protected $params = [];
/**
* @var Container
*/
protected $container;
public function __construct(Container $container)
{
$this->container = $container;
$this->request = $container['request'];
}
/**
* Execute controller.
*
* @param string $method
* @param array $path
* @param array $params
* @return mixed
* @throws \RuntimeException
*/
public function execute($method, array $path, array $params)
{
$this->method = $method;
$this->setParams($params);
list($action, $path) = $this->resolveHttpVerb($method, $path);
if (!method_exists($this, $action)) {
$action = 'undefined';
}
return call_user_func_array([$this, $action], $path);
}
/**
* Set router parameters. Replaces the old parameters.
*
* @param array $params
* @return $this
*/
public function setParams(array $params)
{
$this->params = $params;
return $this;
}
/**
* @example GET /resources
*
* @return mixed
*/
public function index()
{
return $this->undefined();
}
/**
* @example GET /resources/:id
*
* @param string $id
* @return mixed
*/
public function display($id)
{
return $this->undefined();
}
/**
* Special sub-resource to create a new resource (returns a form).
*
* @example GET /resources/create
*
* @return mixed
*/
public function create()
{
return $this->undefined();
}
/**
* Special sub-resource to edit existing resource (returns a form).
*
* @example GET /resources/:id/edit
*
* @param string $id
* @return mixed
*/
public function edit($id)
{
return $this->undefined();
}
/**
* @example POST /resources
*
* @return mixed
*/
public function store()
{
return $this->undefined();
}
/**
* @example PUT /resources/:id
*
* @param string $id
* @return mixed
*/
public function replace($id)
{
return $this->undefined();
}
/**
* @example PATCH /resources/:id
*
* @param string $id
* @return mixed
*/
public function update($id)
{
return $this->undefined();
}
/**
* @example DELETE /resources/:id
*
* @param string $id
* @return mixed
*/
public function destroy($id)
{
return $this->undefined();
}
/**
* Catch all action for all undefined actions.
*
* @return mixed
* @throws RuntimeException
*/
public function undefined()
{
if (in_array($this->method, ['HEAD',
'GET'])) {
throw new RuntimeException('Page Not Found', 404);
}
throw new RuntimeException('Invalid Action', 405);
}
/**
* Catch all action for forbidden actions.
*
* @return mixed
* @throws RuntimeException
*/
public function forbidden()
{
throw new RuntimeException('Forbidden', 403);
}
/**
* Load resource.
*
* Function throws an exception if resource does not exist.
*
* @param string|int $id
* @throws \RuntimeException
*/
protected function loadResource($id)
{
throw new RuntimeException('Resource Not Found', 404);
}
/**
* Resolve HTTP verb.
*
* @param string $method
* @param array $items
* @return array [function, parameters]
*/
protected function resolveHttpVerb($method, array $items)
{
// HEAD has identical behavior to GET.
$method = ($method == 'HEAD') ? 'GET' :
$method;
if (!isset($this->httpVerbs[$method])) {
// HTTP method is not defined.
return ['undefined', $items];
}
$path = '';
$remaining = $items;
$variables = [];
$actions = $this->httpVerbs[$method];
// Build path for the verb and fetch all the variables.
while (($current = array_shift($remaining)) !== null) {
$test = "{$path}/{$current}";
if (!isset($actions[$test])) {
// Specific path not found, check if we have a variable.
$test = "{$path}/*";
if (isset($actions[$test])) {
// Variable found, save the value and move on.
$variables[] = $current;
} elseif (isset($actions[$test . '*'])) {
// Wildcard found, pass through rest of the variables.
$path = $test . '*';
$variables = array_merge($variables, [$current],
$remaining);
break;
} else {
// No matches; we are done here.
return ['undefined', $items];
}
}
// Path was found.
$path = $test;
}
// No matching path; check if we have verb for the root.
if (!$path && isset($actions['/'])) {
$path = '/';
}
// Get the action.
$action = $path ? $actions[$path] : 'undefined';
return [$action, $variables];
}
}
PK���[���00'Component/Controller/HtmlController.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Controller;
use Gantry\Component\Response\HtmlResponse;
use Gantry\Component\Response\Response;
abstract class HtmlController extends BaseController
{
/**
* Execute controller and returns Response object, defaulting to
HtmlResponse.
*
* @param string $method
* @param array $path
* @param array $params
* @return mixed
* @throws \RuntimeException
*/
public function execute($method, array $path, array $params)
{
$response = parent::execute($method, $path, $params);
if (!$response instanceof Response) {
$response = new HtmlResponse($response);
}
return $response;
}
}
PK���[0s���'Component/Controller/JsonController.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Controller;
use Gantry\Component\Response\JsonResponse;
abstract class JsonController extends BaseController
{
/**
* Execute controller and returns JsonResponse object.
*
* @param string $method
* @param array $path
* @param array $params
* @return mixed
* @throws \RuntimeException
*/
public function execute($method, array $path, array $params)
{
$response = parent::execute($method, $path, $params);
if (!$response instanceof JsonResponse) {
$response = new JsonResponse($response);
}
return $response;
}
}
PK���[�VVaa3Component/Controller/RestfulControllerInterface.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Controller;
interface RestfulControllerInterface
{
/**
* @example GET /resources
*
* @return mixed
*/
public function index();
/**
* @example GET /resources/:id
*
* @param string $id
* @return mixed
*/
public function display($id);
/**
* Special sub-resource to create a new resource (returns a form).
*
* @example GET /resources/create
*
* @return mixed
*/
public function create();
/**
* Special sub-resource to edit existing resource (returns a form).
*
* @example GET /resources/:id/edit
*
* @param string $id
* @return mixed
*/
public function edit($id);
/**
* @example POST /resources
*
* @return mixed
*/
public function store();
/**
* @example PUT /resources/:id
*
* @param string $id
* @return mixed
*/
public function replace($id);
/**
* @example PATCH /resources/:id
*
* @param string $id
* @return mixed
*/
public function update($id);
/**
* @example DELETE /resources/:id
*
* @param string $id
* @return mixed
*/
public function destroy($id);
}
PK���[��7��Component/File/CompiledFile.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\File;
use RocketTheme\Toolbox\File\PhpFile;
/**
* Class CompiledFile
* @package Grav\Common\File
*
* @property string $filename
* @property string $extension
* @property string $raw
* @property array|string $content
*/
trait CompiledFile
{
protected $cachePath;
protected $caching = true;
/**
* @param string $path
* @return $this
*/
public function setCachePath($path)
{
$this->cachePath = $path;
return $this;
}
public function caching($enabled = null)
{
if (null !== $enabled) {
$this->caching = (bool) $enabled;
}
return $this->caching;
}
/**
* Get/set parsed file contents.
*
* @param mixed $var
* @return string
* @throws \BadMethodCallException
*/
public function content($var = null)
{
if (!$this->cachePath) {
throw new \BadMethodCallException("Cache path not defined
for compiled file ({$this->filename})!");
}
try {
// If nothing has been loaded, attempt to get pre-compiled
version of the file first.
if ($var === null && $this->raw === null &&
$this->content === null) {
$modified = $this->modified();
if (!$modified || !$this->caching) {
return $this->decode($this->raw());
}
$key = md5($this->filename);
$file = PhpFile::instance($this->cachePath .
"/{$key}{$this->extension}.php");
$class = get_class($this);
$cache = $file->exists() ? $file->content() : null;
// Load real file if cache isn't up to date (or is
invalid).
if (!isset($cache['@class'])
|| $cache['@class'] != $class
|| $cache['modified'] != $modified
|| $cache['filename'] != $this->filename
) {
// Attempt to lock the file for writing.
try {
$file->lock(false);
} catch (\Exception $e) {
// Another process has locked the file; we will
check this in a bit.
}
// Decode RAW file into compiled array.
$data = $this->decode($this->raw());
$cache = [
'@class' => $class,
'filename' => $this->filename,
'modified' => $modified,
'data' => $data
];
// If compiled file wasn't already locked by
another process, save it.
if ($file->locked() !== false) {
$file->save($cache);
$file->unlock();
// Compile cached file into bytecode cache
if
(function_exists('opcache_invalidate')) {
// Silence error in case if
`opcache.restrict_api` directive is set.
@opcache_invalidate($file->filename(),
true);
} elseif
(function_exists('apc_compile_file')) {
// PHP 5.4
@apc_compile_file($file->filename());
}
}
}
$file->free();
$this->content = $cache['data'];
}
} catch (\Exception $e) {
throw new \RuntimeException(sprintf('Failed to read %s:
%s', basename($this->filename), $e->getMessage()), 500, $e);
}
return parent::content($var);
}
}
PK���[{BB#Component/File/CompiledYamlFile.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\File;
use RocketTheme\Toolbox\File\YamlFile;
class CompiledYamlFile extends YamlFile
{
use CompiledFile;
static public $defaultCachePath;
static public $defaultCaching = true;
protected function __construct()
{
parent::__construct();
$this->caching(static::$defaultCaching);
if (static::$defaultCachePath) {
$this->setCachePath(static::$defaultCachePath);
}
}
}
PK���[�{�+�+Component/Filesystem/Folder.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Filesystem;
/**
* Folder helper class.
*
* @author RocketTheme
* @license MIT
*/
abstract class Folder
{
/**
* Recursively find the last modified time under given path.
*
* @param string $path
* @return int
*/
public static function lastModifiedFolder($path)
{
$last_modified = 0;
$directory = new \RecursiveDirectoryIterator($path,
\RecursiveDirectoryIterator::SKIP_DOTS);
$iterator = new \RecursiveIteratorIterator($directory,
\RecursiveIteratorIterator::SELF_FIRST);
/** @var \RecursiveDirectoryIterator $file */
foreach ($iterator as $file) {
$dir_modified = $file->getMTime();
if ($dir_modified > $last_modified) {
$last_modified = $dir_modified;
}
}
return $last_modified;
}
/**
* Get relative path between target and base path. If path isn't
relative, return full path.
*
* @param string $path
* @param string $base
* @return string
*/
public static function getRelativePath($path, $base = GANTRY5_ROOT)
{
$base = preg_replace('![\\\/]+!', '/', $base);
$path = preg_replace('![\\\/]+!', '/', $path);
if (strpos($path, $base) === 0) {
$path = ltrim(substr($path, strlen($base)), '/');
}
return $path;
}
/**
* Get relative path between target and base path. If path isn't
relative, return full path.
*
* @param string $path
* @param string $base
* @return string
*/
public static function getRelativePathDotDot($path, $base)
{
$base = preg_replace('![\\\/]+!', '/', $base);
$path = preg_replace('![\\\/]+!', '/', $path);
if ($path === $base) {
return '';
}
$baseParts = explode('/', isset($base[0]) &&
'/' === $base[0] ? substr($base, 1) : $base);
$pathParts = explode('/', isset($path[0]) &&
'/' === $path[0] ? substr($path, 1) : $path);
array_pop($baseParts);
$lastPart = array_pop($pathParts);
foreach ($baseParts as $i => $directory) {
if (isset($pathParts[$i]) && $pathParts[$i] ===
$directory) {
unset($baseParts[$i], $pathParts[$i]);
} else {
break;
}
}
$pathParts[] = $lastPart;
$path = str_repeat('../', count($baseParts)) .
implode('/', $pathParts);
return '' === $path
|| '/' === $path[0]
|| false !== ($colonPos = strpos($path, ':'))
&& ($colonPos < ($slashPos = strpos($path, '/')) ||
false === $slashPos)
? "./$path" : $path;
}
/**
* Shift first directory out of the path.
*
* @param string $path
* @return string
*/
public static function shift(&$path)
{
$parts = explode('/', trim($path, '/'), 2);
$result = array_shift($parts);
$path = array_shift($parts);
return $result ?: null;
}
/**
* Return recursive list of all files and directories under given path.
*
* @param string $path
* @param array $params
* @return array
* @throws \RuntimeException
*/
public static function all($path, array $params = array())
{
if ($path === false) {
throw new \RuntimeException("Path to {$path} doesn't
exist.");
}
$compare = isset($params['compare']) ? 'get' .
$params['compare'] : null;
$pattern = isset($params['pattern']) ?
$params['pattern'] : null;
$filters = isset($params['filters']) ?
$params['filters'] : null;
$recursive = isset($params['recursive']) ?
$params['recursive'] : true;
$levels = isset($params['levels']) ?
$params['levels'] : -1;
$key = isset($params['key']) ? 'get' .
$params['key'] : null;
$value = isset($params['value']) ? 'get' .
$params['value'] : ($recursive ? 'getSubPathname' :
'getFilename');
$folders = isset($params['folders']) ?
$params['folders'] : true;
$files = isset($params['files']) ?
$params['files'] : true;
if ($recursive) {
$directory = new \RecursiveDirectoryIterator($path,
\RecursiveDirectoryIterator::SKIP_DOTS +
\FilesystemIterator::UNIX_PATHS + \FilesystemIterator::CURRENT_AS_SELF);
$iterator = new \RecursiveIteratorIterator($directory,
\RecursiveIteratorIterator::SELF_FIRST);
$iterator->setMaxDepth(max($levels, -1));
} else {
$iterator = new \FilesystemIterator($path);
}
$results = array();
/** @var \RecursiveDirectoryIterator $file */
foreach ($iterator as $file) {
// Ignore hidden files.
if ($file->getFilename()[0] == '.') {
continue;
}
if (!$folders && $file->isDir()) {
continue;
}
if (!$files && $file->isFile()) {
continue;
}
if ($compare && $pattern &&
!preg_match($pattern, $file->{$compare}())) {
continue;
}
$fileKey = $key ? $file->{$key}() : null;
$filePath = $file->{$value}();
if ($filters) {
if (isset($filters['key'])) {
$filter = $filters['key'];
$pre = !empty($filters['pre-key']) ?
$filters['pre-key'] : '';
if (is_callable($filter)) {
$fileKey = $pre . call_user_func($filter,
$fileKey);
} else {
$fileKey = $pre . preg_replace($filter,
'', $fileKey);
}
}
if (isset($filters['value'])) {
$filter = $filters['value'];
if (is_callable($filter)) {
$filePath = call_user_func($filter, $file);
} else {
$filePath = preg_replace($filter, '',
$filePath);
}
}
}
if ($fileKey !== null) {
$results[$fileKey] = $filePath;
} else {
$results[] = $filePath;
}
}
return $results;
}
/**
* Recursively copy directory in filesystem.
*
* @param string $source
* @param string $target
* @param string $ignore Ignore files matching pattern (regular
expression).
* @throws \RuntimeException
*/
public static function copy($source, $target, $ignore = null)
{
$source = rtrim($source, '\\/');
$target = rtrim($target, '\\/');
if (!is_dir($source)) {
throw new \RuntimeException('Cannot copy non-existing
folder.');
}
// Make sure that path to the target exists before copying.
self::create($target);
$success = true;
// Go through all sub-directories and copy everything.
$files = self::all($source);
foreach ($files as $file) {
if ($ignore && preg_match($ignore, $file)) {
continue;
}
$src = $source .'/'. $file;
$dst = $target .'/'. $file;
if (is_dir($src)) {
// Create current directory (if it doesn't exist).
if (!is_dir($dst)) {
$success &= @mkdir($dst, 0777, true);
}
} else {
// Or copy current file.
$success &= @copy($src, $dst);
}
}
if (!$success) {
$error = error_get_last();
throw new \RuntimeException($error['message']);
}
// Make sure that the change will be detected when caching.
@touch(dirname($target));
}
/**
* Move directory in filesystem.
*
* @param string $source
* @param string $target
* @throws \RuntimeException
*/
public static function move($source, $target)
{
if (!is_dir($source)) {
throw new \RuntimeException('Cannot move non-existing
folder.');
}
// Make sure that path to the target exists before moving.
self::create(dirname($target));
// Just rename the directory.
$success = @rename($source, $target);
if (!$success) {
$error = error_get_last();
throw new \RuntimeException($error['message']);
}
// Make sure that the change will be detected when caching.
@touch(dirname($source));
@touch(dirname($target));
}
/**
* Recursively delete directory from filesystem.
*
* @param string $target
* @param bool $include_target
* @throws \RuntimeException
*/
public static function delete($target, $include_target = true)
{
if (!$target) { return; }
if (!is_dir($target)) {
throw new \RuntimeException('Cannot delete non-existing
folder.');
}
$success = self::doDelete($target, $include_target);
if (!$success) {
$error = error_get_last();
throw new \RuntimeException($error['message']);
}
// Make sure that the change will be detected when caching.
if ($include_target) {
@touch(dirname($target));
} else {
@touch($target);
}
}
/**
* @param string $folder
* @throws \RuntimeException
*/
public static function create($folder)
{
if (is_dir($folder)) {
return;
}
$success = @mkdir($folder, 0777, true);
if (!$success) {
// Take yet another look, make sure that the folder
doesn't exist.
clearstatcache(true, $folder);
if (is_dir($folder)) {
return;
}
$error = error_get_last();
throw new \RuntimeException($error['message']);
}
}
/**
* @param string $folder
* @param bool $include_target
* @return bool
* @internal
*/
protected static function doDelete($folder, $include_target = true)
{
// Special case for symbolic links.
if ($include_target && is_link($folder)) {
return @unlink($folder);
}
// Go through all items in filesystem and recursively remove
everything.
$files = array_diff(scandir($folder), array('.',
'..'));
foreach ($files as $file) {
$path = "{$folder}/{$file}";
(is_dir($path)) ? self::doDelete($path) : @unlink($path);
}
return $include_target ? @rmdir($folder) : true;
}
}
PK���[ڀ}e
Component/Filesystem/Streams.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Filesystem;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use RocketTheme\Toolbox\StreamWrapper\ReadOnlyStream;
use RocketTheme\Toolbox\StreamWrapper\Stream;
class Streams
{
/**
* @var array
*/
protected $schemes = [];
/**
* @var array
*/
protected $registered;
/**
* @var UniformResourceLocator
*/
protected $locator;
public function __construct(UniformResourceLocator $locator = null)
{
if ($locator) {
$this->setLocator($locator);
}
}
/**
* @param UniformResourceLocator $locator
*/
public function setLocator(UniformResourceLocator $locator)
{
$this->locator = $locator;
// Set locator to both streams.
Stream::setLocator($locator);
ReadOnlyStream::setLocator($locator);
}
/**
* @return UniformResourceLocator
*/
public function getLocator()
{
return $this->locator;
}
public function add(array $schemes)
{
foreach ($schemes as $scheme => $config) {
$force = !empty($config['force']);
if (isset($config['paths'])) {
$this->locator->addPath($scheme, '',
$config['paths'], false, $force);
}
if (isset($config['prefixes'])) {
foreach ($config['prefixes'] as $prefix =>
$paths) {
$this->locator->addPath($scheme, $prefix, $paths,
false, $force);
}
}
$type = !empty($config['type']) ?
$config['type'] : 'ReadOnlyStream';
if ($type[0] != '\\') {
$type = '\\Rockettheme\\Toolbox\\StreamWrapper\\'
. $type;
}
$this->schemes[$scheme] = $type;
if (isset($this->registered)) {
$this->doRegister($scheme, $type);
}
}
}
public function register()
{
$this->registered = stream_get_wrappers();
foreach ($this->schemes as $scheme => $type) {
$this->doRegister($scheme, $type);
}
}
protected function doRegister($scheme, $type)
{
if (in_array($scheme, $this->registered)) {
stream_wrapper_unregister($scheme);
}
if (!stream_wrapper_register($scheme, $type)) {
throw new \InvalidArgumentException("Stream
'{$type}' could not be initialized.");
}
}
}
PK���[����WW
Component/Gantry/GantryTrait.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Gantry;
use Gantry\Framework\Gantry;
trait GantryTrait
{
/**
* @var Gantry
*/
private static $gantry;
/**
* Get global Gantry instance.
*
* @return Gantry
*/
public static function gantry()
{
// We cannot set variable directly for the trait as it doesn't
work in HHVM.
if (!self::$gantry) {
self::$gantry = Gantry::instance();
}
return self::$gantry;
}
}
PK���[�;o�Component/Gettext/Gettext.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Gettext;
/**
* Class Gettext
* @package Gantry\Component\Gettext
*
* Examples on translating gettext in twig:
*
* {% trans string_var %}
* http://twig.sensiolabs.org/doc/extensions/i18n.html
*
* {% trans %}Hello {{ author.name }}{% endtrans %}
* http://symfony.com/doc/current/book/translation.html
*
* {{ 'Hello %name%'|trans({'%name%': name}) }}
* {{ trans('Hello %name%', {'%name%': name}) }}
*/
class Gettext
{
public $pos = 0;
public $str;
public $len;
public $endian = 'V';
public function parse($string)
{
$this->str = $string;
$this->len = strlen($string);
$magic = self::readInt() & 0xffffffff;
if ($magic === 0x950412de) {
// Low endian.
$this->endian = 'V';
} elseif ($magic === 0xde120495) {
// Big endian.
$this->endian = 'N';
} else {
throw new \Exception('Not a Gettext file (.mo)');
}
// Skip revision number.
self::readInt();
// Total count.
$total = self::readInt();
// Offset of original table.
$originals = self::readInt();
// Offset of translation table.
$translations = self::readInt();
$this->seek($originals);
$table_originals = self::readIntArray($total * 2);
$this->seek($translations);
$table_translations = self::readIntArray($total * 2);
$items = [];
for ($i = 0; $i < $total; $i++) {
$this->seek($table_originals[$i * 2 + 2]);
$original = $this->read($table_originals[$i * 2 + 1]);
if ($original) {
$this->seek($table_translations[$i * 2 + 2]);
$items[$original] = $this->read($table_translations[$i *
2 + 1]);
}
}
return $items;
}
/**
* @return int
*/
protected function readInt()
{
$read = $this->read(4);
if ($read === false) {
return false;
}
$read = unpack($this->endian, $read);
return array_shift($read);
}
/**
* @param $count
* @return array
*/
protected function readIntArray($count)
{
return unpack($this->endian . $count, $this->read(4 *
$count));
}
/**
* @param $bytes
* @return string
*/
private function read($bytes)
{
$data = substr($this->str, $this->pos, $bytes);
$this->seek($this->pos + $bytes);
return $data;
}
/**
* @param $pos
* @return mixed
*/
private function seek($pos)
{
$this->pos = max($this->len, $pos);
return $this->pos;
}
}
PK���[�xх����Component/Layout/Layout.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Layout;
use Gantry\Component\Config\Config;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Framework\Outlines;
use Gantry\Framework\Gantry;
use RocketTheme\Toolbox\ArrayTraits\ArrayAccess;
use RocketTheme\Toolbox\ArrayTraits\Export;
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
use RocketTheme\Toolbox\ArrayTraits\Iterator;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceIterator;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* Layout
*/
class Layout implements \ArrayAccess, \Iterator, ExportInterface
{
use ArrayAccess, Iterator, Export;
const VERSION = 7;
protected static $instances = [];
protected static $indexes = [];
protected $layout = ['wrapper', 'container',
'section', 'grid', 'block',
'offcanvas'];
public $name;
public $timestamp = 0;
public $preset = [];
public $equalized = [3 => 33.3, 6 => 16.7, 7 => 14.3, 8 =>
12.5, 9 => 11.1, 11 => 9.1, 12 => 8.3];
protected $exists;
protected $items;
protected $references;
protected $parents;
protected $blocks;
protected $types;
protected $inherit;
/**
* @return array
*/
public static function presets()
{
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
/** @var UniformResourceIterator $iterator */
$iterator = $locator->getIterator(
'gantry-layouts://',
UniformResourceIterator::CURRENT_AS_SELF |
UniformResourceIterator::UNIX_PATHS | UniformResourceIterator::SKIP_DOTS
);
$files = [];
/** @var UniformResourceIterator $info */
foreach ($iterator as $info) {
$name = $info->getBasename('.yaml');
if (!$info->isFile() || $info->getExtension() !==
'yaml' || $name[0] === '.') {
continue;
}
$files[] = $name;
}
sort($files);
$results = ['user' => [], 'system' =>
[]];
foreach ($files as $preset) {
$scope = $preset && $preset[0] !== '_' ?
'user' : 'system';
$results[$scope][$preset] =
ucwords(trim(preg_replace(['|_|', '|/|'], ['
', ' / '], $preset)));
}
return $results;
}
/**
* @param string $name
* @return array
* @throws \RuntimeException
*/
public static function preset($name)
{
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$filename =
$locator->findResource("gantry-layouts://{$name}.yaml");
if (!$filename) {
throw new \RuntimeException(sprintf("Preset '%s'
not found", $name), 404);
}
$layout = LayoutReader::read($filename);
$layout['preset']['name'] = $name;
$layout['preset']['timestamp'] =
filemtime($filename);
return $layout;
}
/**
* @param string $name
* @return Layout
*/
public static function instance($name)
{
if (!isset(static::$instances[$name])) {
static::$instances[$name] = static::load($name);
}
return static::$instances[$name];
}
/**
* @param string $name
* @return Layout
*/
public static function index($name)
{
if (!isset(static::$indexes[$name])) {
static::$indexes[$name] = static::loadIndex($name, true);
}
return static::$indexes[$name];
}
/**
* @param string $name
* @param array $items
* @param array $preset
*/
public function __construct($name, array $items = null, array $preset =
null)
{
$this->name = $name;
$this->items = (array) $items;
$this->exists = $items !== null;
// Add preset data from the layout.
if ($preset) {
$this->preset = $preset;
} elseif (isset($this->items['preset'])) {
$this->preset = (array) $this->items['preset'];
}
unset($this->items['preset']);
$this->preset += [
'name' => '',
'timestamp' => 0,
'image' =>
'gantry-admin://images/layouts/default.png'
];
}
/**
* @return bool
*/
public function exists()
{
return $this->exists;
}
/**
* Initialize layout.
*
* @param bool $force
* @param bool $inherit
* @return $this
*/
public function init($force = false, $inherit = true)
{
if ($force || $this->references === null) {
$this->initReferences();
if ($inherit) {
$this->initInheritance();
}
}
return $this;
}
/**
* Build separate meta-information from the layout.
*
* @return array
*/
public function buildIndex()
{
return [
'name' => $this->name,
'timestamp' => $this->timestamp,
'version' => static::VERSION,
'preset' => $this->preset,
'positions' => $this->positions(),
'sections' => $this->sections(),
'particles' => $this->particles(),
'inherit' => $this->inherit()
];
}
/**
* @return $this
*/
public function clean()
{
$this->references = null;
$this->types = null;
$this->inherit = null;
$this->cleanLayout($this->items);
return $this;
}
/**
* @param string $old
* @param string $new
* @param array $ids
* @return $this
*/
public function updateInheritance($old, $new = null, $ids = null)
{
$this->init();
$inherit = $this->inherit();
if (!empty($inherit[$old])) {
foreach ($inherit[$old] as $id => $inheritId) {
$element = $this->find($id, false);
if ($element) {
$inheritId = isset($element->inherit->particle) ?
$element->inherit->particle : $id;
if ($new && ($ids === null ||
isset($ids[$inheritId]))) {
// Add or modify inheritance.
if (!isset($element->inherit)) {
$element->inherit = new \stdClass;
}
$element->inherit->outline = $new;
} else {
// Remove inheritance.
$element->inherit = new \stdClass;
unset($this->inherit[$element->id]);
}
} else {
// Element does not exist anymore, remove its
reference.
unset($this->inherit[$id]);
}
}
}
return $this;
}
/**
* Save layout.
*
* @param bool $cascade
* @return $this
*/
public function save($cascade = true)
{
if (!$this->name) {
throw new \LogicException('Cannot save unnamed
layout');
}
GANTRY_DEBUGGER &&
\Gantry\Debugger::addMessage("Saving layout for outline
{$this->name}");
$name = strtolower(preg_replace('|[^a-z\d_-]|ui',
'_', $this->name));
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
// If there are atoms in the layout, copy them into outline
configuration.
$atoms = $this->atoms();
if (is_array($atoms) && $cascade) {
// Save layout into custom directory for the current theme.
$filename =
$locator->findResource("gantry-config://{$name}/page/head.yaml",
true, true);
$file = YamlFile::instance($filename);
$config = new Config($file->content());
$file->save($config->set('atoms',
json_decode(json_encode($atoms), true))->toArray());
$file->free();
}
// Remove atoms from the layout.
foreach ($this->items as $key => $section) {
if ($section->type === 'atoms') {
unset ($this->items[$key]);
}
}
// Make sure that base outline never uses inheritance.
if ($name === 'default') {
$this->inheritNothing();
}
$filename =
$locator->findResource("gantry-config://{$name}/layout.yaml",
true, true);
$file = CompiledYamlFile::instance($filename);
$file->settings(['inline' => 20]);
$file->save(LayoutReader::store($this->preset,
$this->items));
$file->free();
$this->timestamp = $file->modified();
$this->exists = true;
static::$instances[$this->name] = $this;
return $this;
}
public function export()
{
return LayoutReader::store($this->preset, $this->items);
}
/**
* Save index.
*
* @return $this
*/
public function saveIndex($index = null)
{
if (!$this->name) {
throw new \LogicException('Cannot save unnamed
layout');
}
GANTRY_DEBUGGER &&
\Gantry\Debugger::addMessage("Saving layout index for outline
{$this->name}");
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$filename =
$locator->findResource("gantry-config://{$this->name}/index.yaml",
true, true);
$cache =
$locator->findResource("gantry-cache://{$this->name}/compiled/yaml",
true, true);
$file = CompiledYamlFile::instance($filename);
// Attempt to lock the file for writing.
try {
$file->lock(false);
} catch (\Exception $e) {
// Another process has locked the file; we will check this in a
bit.
}
$index = $index ? $index : $this->buildIndex();
// If file wasn't already locked by another process, save it.
if ($file->locked() !== false) {
$file->setCachePath($cache)->settings(['inline'
=> 20]);
$file->save($index);
$file->unlock();
}
$file->free();
static::$indexes[$this->name] = $index;
return $this;
}
/**
* @return array
*/
public function getLayoutTypes()
{
return $this->layout;
}
/**
* @param string $type
* @return bool
*/
public function isLayoutType($type)
{
return in_array($type, $this->layout, true);
}
/**
* @param $id
* @return string|null
*/
public function getParentId($id)
{
return isset($this->parents[$id]) ? $this->parents[$id] :
null;
}
/**
* @return array
*/
public function references()
{
$this->init();
return $this->references;
}
/**
* @param string $type
* @param string $subtype
* @return array
*/
public function referencesByType($type = null, $subtype = null)
{
$this->init();
if (!$type) {
return $this->types;
}
if (!$subtype) {
return isset($this->types[$type]) ? $this->types[$type] :
[];
}
return isset($this->types[$type][$subtype]) ?
$this->types[$type][$subtype] : [];
}
/**
* Return list of positions (key) with their titles (value).
*
* @return array Array of position => title
*/
public function positions()
{
$positions = $this->referencesByType('position',
'position');
$list = [];
foreach($positions as $position) {
if (!isset($position->attributes->key)) {
continue;
}
$list[$position->attributes->key] = $position->title;
}
return $list;
}
/**
* Return list of positions (key) with their titles (value).
*
* @return array Array of position => title
*/
public function sections()
{
$list = [];
foreach ($this->referencesByType('section') as $type
=> $sections) {
foreach ($sections as $id => $section) {
$list[$id] = $section->title;
}
}
foreach ($this->referencesByType('offcanvas') as $type
=> $sections) {
foreach ($sections as $id => $section) {
$list[$id] = $section->title;
}
}
return $list;
}
/**
* Return list of particles with their titles.
*
* @param bool $grouped If true, group particles by type.
* @return array Array of position => title
*/
public function particles($grouped = true)
{
$blocks = $this->referencesByType('block',
'block');
$list = [];
foreach ($blocks as $blockId => $block) {
if (!empty($block->children)) {
foreach ($block->children as $id => $particle) {
if (!empty($particle->layout) ||
in_array($particle->type, $this->layout, true)) {
continue;
}
if ($grouped) {
$list[$particle->subtype][$particle->id] =
$particle->title;
} else {
$list[$particle->id] = $particle->title;
}
}
}
}
return $list;
}
/**
* @param string $outline
* @return array
*/
public function inherit($outline = null)
{
$this->init();
$list = [];
foreach ($this->inherit as $name => $item) {
if (isset($item->inherit->outline)) {
if (isset($item->inherit->particle)) {
$list[$item->inherit->outline][$name] =
$item->inherit->particle;
} else {
$list[$item->inherit->outline][$name] = $name;
}
}
}
return $outline ? (!empty($list[$outline]) ? $list[$outline] : [])
: $list;
}
/**
* Return atoms from the layout.
*
* @return array|null
* @deprecated
*/
public function atoms()
{
$list = null;
$atoms = array_filter($this->items, function ($section) {
return $section->type === 'atoms' &&
!empty($section->children);
});
$atoms = array_shift($atoms);
if (!empty($atoms->children)) {
$list = [];
foreach ($atoms->children as $grid) {
if (!empty($grid->children)) {
foreach ($grid->children as $block) {
if (isset($block->children[0])) {
$item = $block->children[0];
$list[] = ['title' =>
$item->title, 'type' => $item->subtype,
'attributes' => $item->attributes];
}
}
}
}
}
return $list;
}
/**
* @param string $id
* @param bool $createIfNotExists
* @return object
*/
public function find($id, $createIfNotExists = true)
{
$this->init();
if (!isset($this->references[$id])) {
return $createIfNotExists ? (object)['id' => $id,
'inherit' => new \stdClass] : null;
}
return $this->references[$id];
}
/**
* @param string $id
* @return null
*/
public function block($id)
{
$this->init();
return isset($this->blocks[$id]) ? $this->blocks[$id] : null;
}
public function clearSections()
{
$this->items = $this->clearChildren($this->items);
return $this;
}
protected function clearChildren(&$items)
{
foreach ($items as $key => $item) {
if (!empty($item->children)) {
$this->children =
$this->clearChildren($item->children);
}
if (empty($item->children) &&
in_array($item->type, ['grid', 'block',
'particle', 'position', 'spacer',
'system'], true)) {
unset($items[$key]);
}
}
return array_values($items);
}
public function copySections(array $old)
{
$this->init();
/** @var Layout $old */
$old = new static('tmp', $old);
$leftover = [];
// Copy normal sections.
$data = $old->referencesByType('section');
if (isset($this->types['section'])) {
$sections = $this->types['section'];
$this->copyData($data, $sections, $leftover);
}
// Copy offcanvas.
$data = $old->referencesByType('offcanvas');
if (isset($this->types['offcanvas'])) {
$offcanvas = $this->types['offcanvas'];
$this->copyData($data, $offcanvas, $leftover);
}
// Copy atoms.
$data = $old->referencesByType('atoms');
if (isset($this->types['atoms'])) {
$atoms = $this->types['atoms'];
$this->copyData($data, $atoms, $leftover);
}
return $leftover;
}
public function inheritAll()
{
foreach ($this->references() as $item) {
if (!empty($item->inherit->outline)) {
continue;
}
if (!$this->isLayoutType($item->type)) {
$item->inherit = (object) ['outline' =>
$this->name, 'include' => ['attributes',
'block']];
} elseif ($item->type === 'section' ||
$item->type === 'offcanvas') {
$item->inherit = (object) ['outline' =>
$this->name, 'include' => ['attributes',
'block', 'children']];
}
}
$this->init(true);
return $this;
}
public function inheritNothing()
{
foreach ($this->references() as $item) {
unset($item->inherit);
}
$this->init(true);
return $this;
}
protected function copyData(array $data, array $sections, array
&$leftover)
{
foreach ($data as $type => $items) {
foreach ($items as $item) {
$found = false;
if (isset($sections[$type])) {
foreach ($sections[$type] as $section) {
if ($section->id === $item->id) {
$found = true;
$section->inherit =
$this->cloneData($item->inherit);
$section->children =
$this->cloneData($item->children);
break;
}
}
}
if (!$found && !empty($item->children)) {
$leftover[$item->id] = $item->title;
}
}
}
}
/**
* Clone data which consists mixed set of arrays and stdClass objects.
*
* @param mixed $data
* @return mixed
*/
protected function cloneData($data)
{
if (!($isObject = is_object($data)) && !is_array($data)) {
return $data;
}
$clone = [];
foreach((array) $data as $key => $value) {
if (is_object($value) || is_array($value)) {
$clone[$key] = $this->cloneData($value);
} else {
$clone[$key] = $value;
}
}
return $isObject ? (object) $clone : $clone;
}
/**
* @param array $items
*/
protected function cleanLayout(array $items)
{
foreach ($items as $item) {
if (!empty($item->inherit->include)) {
$include = $item->inherit->include;
foreach ($include as $part) {
switch ($part) {
case 'attributes':
$item->attributes = new \stdClass();
break;
case 'block':
break;
case 'children':
$item->children = [];
break;
}
}
}
if (!empty($item->children)) {
$this->cleanLayout($item->children);
}
}
}
protected function initInheritance()
{
$index = null;
if ($this->name) {
$index = static::loadIndexFile($this->name);
}
$inheriting = $this->inherit();
if (GANTRY_DEBUGGER && $inheriting) {
\Gantry\Debugger::addMessage(sprintf("Layout from outline
%s inherits %s", $this->name, implode(", ",
array_keys($inheriting))));
}
foreach ($inheriting as $outlineId => $list) {
try {
$outline = $this->instance($outlineId);
} catch (\Exception $e) {
// Outline must have been deleted.
GANTRY_DEBUGGER &&
\Gantry\Debugger::addMessage("Outline {$outlineId} is missing /
deleted", 'error');
$outline = null;
}
foreach ($list as $id => $inheritId) {
$item = $this->find($id);
$inheritId = !empty($item->inherit->particle) ?
$item->inherit->particle : $id;
$inherited = $outline ? $outline->find($inheritId) :
null;
$include = !empty($item->inherit->include) ? (array)
$item->inherit->include : [];
foreach ($include as $part) {
switch ($part) {
case 'attributes':
// Deep clone attributes.
$item->attributes =
isset($inherited->attributes) ?
$this->cloneData($inherited->attributes) : new \stdClass();
break;
case 'block':
$block = $this->block($id);
if (isset($block->attributes)) {
$inheritBlock = $outline ?
$this->cloneData($outline->block($inheritId)) : null;
$blockAttributes = $inheritBlock ?
array_diff_key((array)$inheritBlock->attributes, ['fixed'
=> 1, 'size' => 1]) : [];
$block->attributes =
(object)($blockAttributes + (array)$block->attributes);
}
break;
case 'children':
if (!empty($inherited->children)) {
// Deep clone children.
$item->children =
$this->cloneData($inherited->children);
$this->initReferences($item->children, $this->getParentId($id),
null,
['outline' => $outlineId,
'include' => ['attributes', 'block']],
$index);
} else {
$item->children = [];
}
break;
}
}
if (!$outline || !isset($inherited->attributes)) {
// Remove inheritance information if outline
doesn't exist.
$item->inherit = new \stdClass;
unset($this->inherit[$item->id]);
}
}
}
}
/**
* @param array $items
* @param object $parent
* @param object $block
* @param string $inherit
* @param array $index
*/
protected function initReferences(array $items = null, $parent = null,
$block = null, $inherit = null, array $index = null)
{
if ($items === null) {
$items = $this->items;
$this->references = [];
$this->types = [];
$this->inherit = [];
}
foreach ($items as $item) {
if (is_object($item)) {
$type = $item->type;
$subtype = !empty($item->subtype) ? $item->subtype :
$type;
if ($block) {
$this->parents[$item->id] = $parent;
}
if ($block) {
$this->blocks[$item->id] = $block;
}
if ($inherit && !$this->isLayoutType($type)) {
$item->inherit = (object) $inherit;
$item->inherit->particle = $item->id;
if
(isset($index['inherit'][$item->inherit->outline])
&& ($newId = array_search($item->id,
$index['inherit'][$item->inherit->outline], true))) {
$item->id = $newId;
} else {
$item->id = $this->id($type, $subtype);
}
}
if (isset($item->id)) {
if (isset($this->references[$item->id])) {
if ($type === 'block' || $type ===
'grid') {
$item->id = $this->id($type, $subtype);
}
// elseif (null === $inherit) {
// throw new \RuntimeException('Layout
reference conflict on #' . $item->id);
// }
}
$this->references[$item->id] = $item;
$this->types[$type][$subtype][$item->id] = $item;
if (!empty($item->inherit->outline)) {
$this->inherit[$item->id] = $item;
}
} else {
$this->types[$type][$subtype][] = $item;
}
if (isset($item->children) &&
is_array($item->children)) {
$this->initReferences($item->children, $type ===
'section' ? $item : $parent, $type === 'block' ? $item
: null, $inherit, $index);
}
}
}
}
/**
* @param string $type
* @param string $subtype
* @param string $id
* @return string
*/
protected function id($type, $subtype = null, $id = null)
{
$result = [];
if ($type !== 'particle') {
$result[] = $type;
}
if ($subtype && ($subtype !== $type || $subtype ===
'position')) {
$result[] = $subtype;
}
$key = implode('-', $result);
$key_id = $key . '-'. $id;
if (!$id || isset($this->references[$key_id])) {
while ($id = rand(1000, 9999)) {
$key_id = $key . '-'. $id;
if (!isset($this->references[$key_id])) {
break;
}
}
}
return $key_id;
}
/**
* Prepare block width sizes.
*
* @return $this
*/
public function prepareWidths()
{
$this->init();
$this->calcWidths($this->items);
return $this;
}
/**
* Recalculate block widths.
*
* @param array $items
* @internal
*/
protected function calcWidths(array &$items)
{
foreach ($items as $i => $item) {
if (empty($item->children)) {
continue;
}
$this->calcWidths($item->children);
$dynamicSize = 0;
$fixedSize = 0;
$childrenCount = 0;
foreach ($item->children as $child) {
if ($child->type !== 'block') {
continue;
}
$childrenCount++;
if (!isset($child->attributes->size)) {
$child->attributes->size = 100 /
count($item->children);
}
if (empty($child->attributes->fixed)) {
$dynamicSize += $child->attributes->size;
} else {
$fixedSize += $child->attributes->size;
}
}
if (!$childrenCount) {
continue;
}
$roundSize = round($dynamicSize, 1);
$equalized = isset($this->equalized[$childrenCount]) ?
$this->equalized[$childrenCount] : 0;
// force-casting string for testing comparison due to weird PHP
behavior that returns wrong result
if ($roundSize !== 100 && (string) $roundSize !==
(string) ($equalized * $childrenCount)) {
$fraction = 0;
$multiplier = (100 - $fixedSize) / ($dynamicSize ?: 1);
foreach ($item->children as $child) {
if ($child->type !== 'block') {
continue;
}
if (!empty($child->attributes->fixed)) {
continue;
}
// Calculate size for the next item by taking account
the rounding error from the last item.
// This will allow us to approximate cumulating error
and fix it when rounding error grows
// over the rounding treshold.
$size = ($child->attributes->size * $multiplier)
+ $fraction;
$newSize = round($size);
$fraction = $size - $newSize;
$child->attributes->size = $newSize;
}
}
}
}
/**
* @param string $name
* @param string $preset
* @return static
*/
public static function load($name, $preset = null)
{
if (!$name) {
throw new \BadMethodCallException('Layout needs to have a
name');
}
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$layout = null;
$filename =
$locator("gantry-config://{$name}/layout.yaml");
// If layout file doesn't exists, figure out what preset was
used.
if (!$filename) {
// Attempt to load the index file.
$indexFile =
$locator("gantry-config://{$name}/index.yaml");
if ($indexFile || !$preset) {
$index = static::loadIndex($name, true);
$preset = $index['preset']['name'];
}
try {
$layout = static::preset($preset);
} catch (\Exception $e) {
// Layout doesn't exist, do nothing.
}
} else {
$layout = LayoutReader::read($filename);
}
return new static($name, $layout);
}
protected static function loadIndexFile($name)
{
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
// Attempt to load the index file.
$indexFile =
$locator("gantry-config://{$name}/index.yaml");
if ($indexFile) {
$file = CompiledYamlFile::instance($indexFile);
$index = (array)$file->content();
$file->free();
} else {
$index = [];
}
return $index;
}
/**
* @param string $name
* @param bool $autoSave
* @return array
*/
public static function loadIndex($name, $autoSave = false)
{
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$index = static::loadIndexFile($name);
// Find out the currently used layout file.
$layoutFile =
$locator("gantry-config://{$name}/layout.yaml");
if (!$layoutFile) {
/** @var Outlines $outlines */
$outlines = $gantry['outlines'];
$preset = isset($index['preset']['name']) ?
$index['preset']['name'] : $outlines->preset($name);
}
// Get timestamp for the layout file.
$timestamp = $layoutFile ? filemtime($layoutFile) : 0;
// If layout index file doesn't exist or is not up to date,
rebuild it.
if (empty($index['timestamp']) ||
$index['timestamp'] != $timestamp ||
!isset($index['version']) || $index['version'] !=
static::VERSION) {
$layout = isset($preset) ? new static($name,
static::preset($preset)) : static::instance($name);
$layout->timestamp = $timestamp;
if ($autoSave) {
if (!$layout->timestamp) {
$layout->save();
}
$index = $layout->buildIndex();
$layout->saveIndex($index);
} else {
$index = $layout->buildIndex();
}
}
$index += [
'name' => $name,
'timestamp' => $timestamp,
'preset' => [
'name' => '',
'image' =>
'gantry-admin://images/layouts/default.png'
],
'positions' => [],
'sections' => [],
'inherit' => []
];
return $index;
}
public function check(array $children = null)
{
if ($children === null) {
$children = $this->items;
}
foreach ($children as $item) {
if (!$item instanceof \stdClass) {
throw new \RuntimeException('Invalid layout
element');
}
if (!isset($item->type)) {
throw new \RuntimeException('Type missing');
}
if (!isset($item->subtype)) {
throw new \RuntimeException('Subtype missing');
}
if (!isset($item->attributes)) {
throw new \RuntimeException('Attributes
missing');
}
if (!is_object($item->attributes)) {
throw new \RuntimeException('Attributes not
object');
}
if (isset($item->children)) {
if (!is_array($item->children)) {
throw new \RuntimeException('Children not
array');
}
$this->check($item->children);
}
}
}
}
PK���[.|�G
!Component/Layout/LayoutReader.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Layout;
use Gantry\Component\File\CompiledYamlFile;
/**
* Read layout from yaml file.
*/
class LayoutReader
{
/**
* Get layout version.
*
* @param array $data
* @return int
*/
public static function version(array &$data)
{
if (isset($data['version'])) {
return $data['version'];
}
return isset($data['children']) &&
is_array($data['children']) ? 0 : 1;
}
/**
* Make layout from array data.
*
* @param array $data
* @return array
*/
public static function data(array $data)
{
$version = static::version($data);
$reader = static::getClass($version, $data);
$result = $reader->load();
// Make sure that all preset values are set by defining defaults.
$result['preset'] += [
'name' => '',
'image' =>
'gantry-admin://images/layouts/default.png'
];
return $result;
}
/**
* Read layout from yaml file and return parsed version of it.
*
* @param string $file
* @return array
*/
public static function read($file)
{
if (!$file) {
return [];
}
$file = CompiledYamlFile::instance($file);
$content = (array) $file->content();
$file->free();
return static::data($content);
}
/**
* Convert layout into file format.
*
* @param array $preset
* @param array $structure
* @param int $version
* @return mixed
*/
public static function store(array $preset, array $structure, $version
= 2)
{
$reader = static::getClass($version);
return $reader->store($preset, $structure);
}
/**
* @param int $version
* @param array $data
* @return object
*/
protected static function getClass($version, array $data = [])
{
$class =
"Gantry\\Component\\Layout\\Version\\Format{$version}";
if (!class_exists($class)) {
throw new \RuntimeException('Layout file cound not be
read: unsupported version {$version}.');
}
return new $class($data);
}
}
PK���[Q�E���$Component/Layout/Version/Format0.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Layout\Version;
/**
* Read layout from Layout Manager yaml file.
*/
class Format0 extends Format1
{
/**
* @return array
*/
public function load()
{
$data = &$this->data;
$preset = isset($data['preset']) &&
is_array($data['preset']) ? $data['preset'] : [];
$result = is_array($data['children']) ?
$this->object($data['children']) : [];
$invisible = [
'offcanvas' =>
$this->parse('offcanvas', [], 0),
'atoms' => $this->parse('atoms', [],
0)
];
foreach ($result as $key => &$item) {
if (isset($invisible[$item->type])) {
$invisible[$item->type] = $item;
unset($result[$key]);
}
}
$result += $invisible;
$result = array_values($result);
return ['preset' => $preset] + $result;
}
protected function object(array $items, $container = true)
{
foreach ($items as &$item) {
$item = (object) $item;
if (isset($item->attributes) &&
(is_array($item->attributes) || is_object($item->attributes))) {
$item->attributes = (object) $item->attributes;
} else {
$item->attributes = (object) [];
}
if (!empty($item->children) &&
is_array($item->children)) {
$item->children = $this->object($item->children,
false);
}
$this->normalize($item, $container);
}
return $items;
}
}
PK���[��+�#�#$Component/Layout/Version/Format1.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Layout\Version;
/**
* Read layout from simplified yaml file.
*/
class Format1
{
protected $scopes = [0 => 'grid', 1 =>
'block'];
protected $data;
protected $keys = [];
public function __construct(array $data)
{
$this->data = $data;
}
public function load()
{
$data = &$this->data;
// Check if we have preset.
$preset = [];
if (isset($data['preset']) &&
is_array($data['preset']) &&
isset($data['layout']) &&
is_array($data['layout'])) {
$preset = $data['preset'];
$data = $data['layout'];
}
// We have user entered file; let's build the layout.
// Two last items are always offcanvas and atoms.
$offcanvas = isset($data['offcanvas']) ?
$data['offcanvas'] : [];
$atoms = isset($data['atoms']) ? $data['atoms']
: [];
unset($data['offcanvas'], $data['atoms']);
$data['offcanvas'] = $offcanvas;
if ($atoms) {
$data['atoms'] = $atoms;
}
$result = [];
foreach ($data as $field => $params) {
$child = $this->parse($field, (array) $params, 0);
unset($child->size);
$result[] = $child;
}
return ['preset' => $preset] + $result;
}
public function store(array $preset, array $structure)
{
return ['preset' => $preset, 'children'
=> $structure];
}
protected function normalize(&$item, $container = false)
{
if ($item->type === 'pagecontent') {
// Update pagecontent to match the new standards.
$item->type = 'system';
if (!$item->subtype || $item->subtype ==
'pagecontent') {
$item->subtype = 'content';
$item->title = 'Page Content';
} else {
$item->subtype ='messages';
$item->title = 'System Messages';
}
}
if ($item->type === 'section') {
// Update section to match the new standards.
$section = strtolower($item->title);
$item->id = $section;
$item->subtype = (in_array($section, ['aside',
'nav', 'article', 'header',
'footer', 'main']) ? $section : 'section');
} elseif ($item->type === 'offcanvas') {
$item->id = $item->subtype = $item->type;
unset ($item->attributes->name,
$item->attributes->boxed);
return;
} else {
// Update all ids to match the new standards.
$item->id = $this->id($item->type, $item->subtype);
}
if (!empty($item->attributes->extra)) {
foreach ($item->attributes->extra as $i => $extra) {
$v = reset($extra);
$k = key($extra);
if ($k === 'id') {
$item->id = preg_replace('/^g-/',
'', $v);
$item->attributes->id = $v;
unset ($item->attributes->extra[$i]);
}
}
if (empty($item->attributes->extra)) {
unset ($item->attributes->extra);
}
}
$item->subtype = $item->subtype ?: $item->type;
$item->layout = in_array($item->type, ['container',
'section', 'grid', 'block',
'offcanvas']);
if (isset($item->attributes->boxed)) {
// Boxed already set, just change boxed=0 to boxed=''
to use default settings.
$item->attributes->boxed = $item->attributes->boxed
?: '';
return;
}
if (!$container) {
return;
}
// Update boxed model to match the new standards.
if (isset($item->children) && count($item->children)
=== 1) {
$child = reset($item->children);
if ($item->type === 'container') {
// Remove parent container only if the only child is a
section.
if ($child->type === 'section') {
$child->attributes->boxed = 1;
$item = $child;
}
$item->attributes->boxed = '';
} elseif ($child->type === 'container') {
// Remove child container.
$item->attributes->boxed = '';
$item->children = $child->children;
}
}
}
/**
* @param int|string $field
* @param array $content
* @param int $scope
* @param bool|null $container
* @return array
*/
protected function parse($field, array $content, $scope, $container =
true)
{
if (is_numeric($field)) {
// Row or block
$type = $this->scopes[$scope];
$result = (object) ['id' => null, 'type'
=> $type, 'subtype' => $type, 'layout' =>
true, 'attributes' => (object) []];
$scope = ($scope + 1) % 2;
} elseif (substr($field, 0, 9) == 'container') {
// Container
$type = 'container';
$result = (object) ['id' => null, 'type'
=> $type, 'subtype' => $type, 'layout' =>
true, 'attributes' => (object) []];
$id = substr($field, 10) ?: null;
if ($id !== null) {
$result->attributes->id = $id;
}
} else {
// Section
$list = explode(' ', $field, 2);
$field = array_shift($list);
$size = ((float) array_shift($list)) ?: null;
$type = in_array($field, ['atoms',
'offcanvas']) ? $field : 'section';
$subtype = in_array($field, ['aside',
'nav', 'article', 'header',
'footer', 'main']) ? $field : 'section';
$result = (object) [
'id' => null,
'type' => $type,
'subtype' => $subtype,
'layout' => true,
'title' => ucfirst($field),
'attributes' => (object) ['id' =>
'g-' . $field]
];
if ($size) {
$result->size = $size;
}
}
if (!empty($content)) {
$result->children = [];
foreach ($content as $child => $params) {
if (is_array($params)) {
$child = $this->parse($child, $params, $scope,
false);
} else {
$child = $this->resolve($params, $scope);
}
if (!empty($child->size)) {
$result->attributes->size = $child->size;
}
unset($child->size);
$result->children[] = $child;
}
}
$this->normalize($result, $container);
return $result;
}
/**
* @param string $field
* @param int $scope
* @return array
*/
protected function resolve($field, $scope)
{
$list = explode(' ', $field, 2);
$list2 = explode('-', array_shift($list), 2);
$size = ((float) array_shift($list)) ?: null;
$type = array_shift($list2);
$subtype = array_shift($list2) ?: false;
$title = ucfirst($subtype ?: $type);
$attributes = new \stdClass;
$attributes->enabled = 1;
if ($subtype && $type === 'position') {
$attributes->key = $subtype;
$subtype = false;
}
$result = (object) ['id' => $this->id($type,
$subtype), 'title' => $title, 'type' => $type,
'subtype' => $subtype, 'attributes' =>
$attributes];
$this->normalize($result);
if ($scope > 1) {
if ($size) {
$result->attributes->size = $size;
}
return $result;
}
if ($scope <= 1) {
$result = (object) ['id' =>
$this->id('block'), 'type' => 'block',
'subtype' => 'block', 'layout' => true,
'children' => [$result], 'attributes' => new
\stdClass];
if ($size) {
$result->attributes->size = $size;
}
}
if ($scope == 0) {
$result = (object) ['id' =>
$this->id('grid'), 'type' => 'grid',
'subtype' => 'grid', 'layout' => true,
'children' => [$result], 'attributes' => new
\stdClass];
}
return $result;
}
protected function id($type, $subtype = null)
{
if ($type === 'atoms') {
return $type;
}
$result = [];
if ($type !== 'particle' && $type !==
'atom') {
$result[] = $type;
}
if ($subtype && $subtype !== $type) {
$result[] = $subtype;
}
$key = implode('-', $result);
while ($id = rand(1000, 9999)) {
if (!isset($this->keys[$key][$id])) {
break;
}
}
$this->keys[$key][$id] = true;
return $key . '-'. $id;
}
}
PK���[��]��E�E$Component/Layout/Version/Format2.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Layout\Version;
/**
* Read layout from simplified yaml file.
*/
class Format2
{
protected $scopes = [0 => 'grid', 1 =>
'block'];
protected $sections = ['wrapper', 'container',
'section', 'grid', 'block',
'offcanvas'];
protected $structures = ['div', 'section',
'aside', 'nav', 'article',
'header', 'footer', 'main'];
protected $data;
protected $structure;
protected $content;
protected $keys;
/**
* @param array $data
*/
public function __construct(array $data = [])
{
$this->data = $data;
}
/**
* @return array
*/
public function load()
{
$data = &$this->data;
// Parse layout.
$result = [];
foreach ($data['layout'] as $field => &$params) {
if (!is_array($params)) {
$params = [];
}
$child = $this->parse($field, $params);
unset($child->size);
$result[] = $child;
}
return ['preset' => $data['preset']] +
$result;
}
/**
* @param array $preset
* @param array $structure
* @return array
*/
public function store(array $preset, array $structure)
{
$this->structure = [];
$this->content = [];
$structure = ['children' =>
json_decode(json_encode($structure), true)];
$structure = $this->build($structure);
$result = [
'version' => 2,
'preset' => $preset,
'layout' => $structure
];
if ($this->structure) {
$result['structure'] = $this->structure;
}
if ($this->content) {
$result['content'] = $this->content;
}
return $result;
}
/**
* @param int|string $field
* @param array $content
* @param int $scope
* @param object $parent
* @return array
*/
protected function parse($field, array &$content, $scope = 0,
$parent = null)
{
if (is_numeric($field)) {
// Row or block
$result = (object)['id' =>
$this->id($this->scopes[$scope]), 'type' =>
$this->scopes[$scope], 'subtype' =>
$this->scopes[$scope], 'layout' => true,
'attributes' => (object)[]];
$scope = ($scope + 1) % 2;
} else {
list ($type, $subtype, $id, $size, $section_id, $boxed) =
$this->parseSectionString($field);
if ($type == 'grid') {
$scope = 1;
}
if ($type == 'block') {
$scope = 0;
}
// Build object.
$result =
isset($this->data['structure'][$section_id]) ? (array)
$this->data['structure'][$section_id] : [];
$result += [
'id' => $section_id,
'layout' => true,
'type' => $type,
'subtype' => $subtype,
'title' => $this->getTitle($type, $subtype,
$id),
'attributes' => []
];
if (isset($boxed) &&
!isset($result['attributes']['boxed'])) {
$result['attributes']['boxed'] =
$boxed;
}
if ($parent && $parent->type === 'block'
&& !empty($result['block'])) {
$parent->attributes = (object)
($result['block'] + (array) $parent->attributes);
}
unset ($result['block']);
$result = (object) $result;
$result->attributes = (object) $result->attributes;
if (isset($result->inherit)) {
$result->inherit = (object) $result->inherit;
}
if ($size) {
$result->size = $size;
}
if (($type === 'grid' || $type === 'block')
&& !isset($result->attributes->id)) {
$result->attributes->id = $section_id;
}
}
if (!empty($content)) {
$result->children = [];
foreach ($content as $child => &$params) {
if (!$params && !is_array($params)) {
$params = [];
}
if (is_array($params)) {
$child = $this->parse($child, $params, $scope,
$result);
} else {
$child = $this->resolve($params, $scope, $result);
}
if (!empty($child->size)) {
$result->attributes->size = $child->size;
}
unset($child->size);
$result->children[] = $child;
}
}
return $result;
}
/**
* @param string $field
* @param int $scope
* @param object $parent
* @return array
*/
protected function resolve($field, $scope, $parent)
{
list ($type, $subtype, $id, $size, $content_id) =
$this->parseContentString($field);
$title = $this->getTitle($type, $subtype, $id);
$result = isset($this->data['content'][$content_id]) ?
(array) $this->data['content'][$content_id] : [];
$result += ['id' => $this->id($type, $subtype,
$id), 'title' => $title, 'type' => $type,
'subtype' => $subtype, 'attributes' => []];
$result['attributes'] = (object)
($result['attributes'] + ['enabled' => 1]);
if (isset($result['inherit'])) {
$result['inherit'] = (object)
$result['inherit'];
}
if (isset($result['block'])) {
$block = $result['block'];
unset ($result['block']);
}
$result = (object) $result;
if ($type === 'position' &&
!isset($result->attributes->key) && !in_array($subtype,
['module', 'widget'])) {
$result->attributes->key = $id;
}
if ($scope > 1) {
if ($parent->type === 'block' &&
!empty($block)) {
$parent->attributes = (object) ($block + (array)
$parent->attributes);
}
if ($size) {
$result->attributes->size = $size;
}
}
if ($scope <= 1) {
$result = (object) ['id' =>
$this->id('block'), 'type' => 'block',
'subtype' => 'block', 'layout' => true,
'children' => [$result], 'attributes' => new
\stdClass];
if (!empty($block)) {
$result->attributes = (object) $block;
}
if ($size) {
$result->attributes->size = $size;
}
}
if ($scope == 0) {
$result = (object) ['id' =>
$this->id('grid'), 'type' => 'grid',
'subtype' => 'grid', 'layout' => true,
'children' => [$result], 'attributes' => new
\stdClass];
}
return $result;
}
/**
* @param array $content
* @return array|null
*/
protected function build(array &$content)
{
$result = [];
$ctype = isset($content['type']) ?
$content['type'] : null;
if (in_array($ctype, ['grid', 'block'])) {
if (empty($content['attributes']['id']) ||
$content['attributes']['id'] ===
$content['id']) {
unset ($content['attributes']['id']);
}
}
if ($ctype === 'block') {
if (empty($content['attributes']['extra']))
{
unset
($content['attributes']['extra']);
}
if (empty($content['attributes']['fixed']))
{
unset
($content['attributes']['fixed']);
}
}
if ($ctype === 'section') {
if (empty($content['attributes']['extra']))
{
unset
($content['attributes']['extra']);
}
}
if (!isset($content['children'])) {
$content['children'] = [];
}
unset ($content['layout']);
// Clean up all items for saving.
foreach ($content['children'] as &$child) {
$size = null;
$id = $child['id'];
$type = $child['type'];
$subtype = $child['subtype'];
$isSection = in_array($type, $this->sections);
if (empty($child['inherit']['outline']) ||
empty($child['inherit']['include'])) {
unset ($child['inherit']);
} else {
foreach ($child['inherit']['include']
as $include) {
switch ($include) {
case 'attributes':
unset($child['attributes']);
break;
case 'block':
if ($ctype === 'block') {
// Keep block size and fixed status.
$attributes =
!empty($content['attributes']) ? $content['attributes']
: [];
$content['attributes'] =
array_intersect_key($attributes, ['fixed' => 1,
'size' => 1]);
}
break;
case 'children':
$child['children'] = [];
break;
}
}
}
if (!$isSection) {
// Special handling for positions.
if ($type === 'position') {
// TODO: we may want to simplify position id, but we
need to take into account multiple instances of the same position key.
/*
if (!$subtype || $subtype === 'position') {
$id = 'position-' .
(isset($child['attributes']['key']) ?
$child['attributes']['key'] : rand(1000,9999));
unset
($child['attributes']['key']);
}
*/
unset
($child['attributes']['title']);
}
$value = $id;
if
(!empty($child['attributes']['enabled'])) {
unset
($child['attributes']['enabled']);
}
} else {
// Recursively handle structure.
$value = $this->build($child);
}
// Clean up defaults.
if (empty($child['title']) ||
$child['title'] === 'Untitled' ||
$child['title'] === $this->getTitle($type, $subtype, $id)) {
unset ($child['title']);
}
if (!$subtype || $subtype === $type) {
unset ($child['subtype']);
}
// Remove id and children as we store data in flat structure
with id being the key.
unset ($child['id'], $child['children']);
if ($type === 'offcanvas' &&
isset($child['attributes']['name'])) {
unset ($child['attributes']['name']);
}
if ($ctype === 'block') {
// Embed size into array key/value.
if
(isset($content['attributes']['size']) &&
$content['attributes']['size'] != 100) {
$size =
$content['attributes']['size'];
}
unset ($content['attributes']['size']);
// Embed parent block.
if (!empty($content['attributes'])) {
$child['block'] =
$content['attributes'];
unset ($content['attributes']);
}
}
if (isset($child['attributes']['size'])) {
if ($child['attributes']['size'] != 100
&& is_string($value)) {
$size =
$child['attributes']['size'];
}
unset ($child['attributes']['size']);
}
// Remove attributes if there aren't any.
if (empty($child['attributes'])) {
unset ($child['attributes']);
}
// Special handling for grid and block elements.
if (in_array($type, ['grid', 'block'])
&& count($child) === 1 && isset($child['type']))
{
$id = null;
}
// Check if type and subtype can be generated from the id.
if ($subtype &&
(preg_match("/^{$type}-{$subtype}(-|$)/", $id))
|| (in_array($type, ['section',
'particle']) &&
preg_match("/^{$subtype}(-|$)/", $id))) {
unset ($child['type'],
$child['subtype']);
} elseif (preg_match("/^{$type}(-|$)/", $id)) {
unset ($child['type']);
}
// Add item configuration if not empty.
if ($id && !empty($child)) {
if (!is_string($value)) {
$this->structure[$id] = $child;
} else {
$this->content[$id] = $child;
}
}
// Add item to the layout.
if (!is_string($value)) {
// Add structural item.
if ($id) {
// Sections and other complex items.
$id =
isset($child['attributes']['boxed']) ?
"/{$id}/" : $id;
$result[trim("{$id} {$size}")] = $value;
} elseif (!empty($value)) {
// Simple grid / block item.
$result[] = $value;
}
} else {
// Add content item.
$result[] = trim("{$value} {$size}");
}
}
// TODO: maybe collapse grid as well?
if ($ctype && in_array($ctype, ['block'])
&& count($result) <= 1 && key($result) === 0) {
unset ($this->structure[$content['id']]);
return reset($result) ?: null;
}
return $result;
}
/**
* @param string $string
* @return array
*/
protected function parseSectionString($string)
{
// Extract: "[section-id] [size]".
$list = explode(' ', $string, 2);
$section_id = array_shift($list);
$size = ((float) array_shift($list)) ?: null;
// Extract slashes from "/[section-id]/".
$boxedLeft = $section_id[0] === '/';
$boxedRight = $section_id[strlen($section_id)-1] === '/';
$boxed = ($boxedLeft && $boxedRight ? '' :
($boxedLeft ? '1' : ($boxedRight ? '0' : null)));
$section_id = trim($section_id, '/');
// Extract section id if it exists: "[section]-[id]".
$list = explode('-', $section_id, 2);
// Get section and its type.
$section = reset($list);
$type = (in_array($section, $this->sections)) ? $section :
'section';
$subtype = ($type !== 'section' || in_array($section,
$this->structures)) ? $section : 'section';
// Extract id.
if ($type == 'section' && in_array($section,
$this->structures)) {
$id = array_pop($list);
} else {
$id = $section_id;
}
return [$type, $subtype, $id, $size, $section_id, $boxed];
}
/**
* @param string $string
* @return array
*/
protected function parseContentString($string)
{
// Extract: "[type-subtype] [size]".
$list = explode(' ', $string, 2);
$content_id = array_shift($list);
$size = ((float) array_shift($list)) ?: null;
// Extract sub-type if it exists:
"[type]-[subtype]-[id]".
$list = explode('-', $content_id);
// Get type, subtype and id.
$type = reset($list);
$test = end($list);
$id = ((string)(int) $test === (string) $test) ? array_pop($list) :
null;
if (in_array($type, ['system', 'position',
'particle', 'spacer'])) {
array_shift($list);
} else {
$type = 'particle';
}
$subtype = implode('-', $list);
if ($type === 'position' && !in_array($subtype,
['module', 'widget'])) {
$id = ($subtype ?: $type) . ($id !== null ? "-{$id}"
: '');
$subtype = 'position';
}
return [$type, $subtype ?: $type, $id, $size, $content_id];
}
/**
* @param string $type
* @param string $subtype
* @param string $id
* @return string
*/
protected function getTitle($type, $subtype, $id)
{
if (in_array($type, $this->sections)) {
if ($type === 'offcanvas') {
return 'Offcanvas';
}
if ($type === 'grid' || $type === 'block')
{
return null;
}
return ucfirst((string)(int) $id === (string) $id ? ($subtype
?: $type) . "-{$id}" : $id);
}
if ($type === 'position' && !in_array($subtype,
['module', 'widget'])) {
return
ucfirst(preg_replace('/^position-(.*?[a-z])/ui', '\1',
$id));
}
if ($type === 'system') {
if ($subtype === 'messages') {
return 'System Messages';
}
if ($subtype === 'content') {
return 'Page Content';
}
}
return ucfirst($subtype ?: $type);
}
/**
* @param string $type
* @param string $subtype
* @param string $id
* @return string
*/
protected function id($type, $subtype = null, $id = null)
{
$result = [];
if ($type !== 'particle') {
$result[] = $type;
}
if ($subtype && $subtype !== $type) {
$result[] = $subtype;
}
$key = implode('-', $result);
if (!$id || isset($this->keys[$key][$id])) {
while ($id = rand(1000, 9999)) {
if (!isset($this->keys[$key][$id])) {
break;
}
}
}
$this->keys[$key][$id] = true;
return $key . '-'. $id;
}
}
PK���[j픞--Component/Menu/AbstractMenu.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Menu;
use Gantry\Component\Config\Config;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Component\Gantry\GantryTrait;
use RocketTheme\Toolbox\ArrayTraits\ArrayAccessWithGetters;
use RocketTheme\Toolbox\ArrayTraits\Countable;
use RocketTheme\Toolbox\ArrayTraits\Export;
use RocketTheme\Toolbox\ArrayTraits\Iterator;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
abstract class AbstractMenu implements \ArrayAccess, \Iterator, \Countable
{
use GantryTrait, ArrayAccessWithGetters, Iterator, Export, Countable;
protected $default;
protected $base;
protected $active;
protected $params;
protected $override = false;
protected $config;
/**
* @var array|Item[]
*/
protected $items;
/**
* @var Config|null
*/
protected $pathMap;
protected $defaults = [
'menu' => '',
'base' => '/',
'startLevel' => 1,
'maxLevels' => 0,
'showAllChildren' => true,
'highlightAlias' => true,
'highlightParentAlias' => true
];
abstract public function __construct();
/**
* Return list of menus.
*
* @return array
*/
abstract public function getMenus();
/**
* Return default menu.
*
* @return string
*/
public function getDefaultMenuName()
{
return null;
}
/**
* Returns true if the platform implements a Default menu.
*
* @return boolean
*/
public function hasDefaultMenu()
{
return false;
}
/**
* Return active menu.
*
* @return string
*/
public function getActiveMenuName()
{
return null;
}
/**
* Returns true if the platform implements an Active menu.
*
* @return boolean
*/
public function hasActiveMenu()
{
return false;
}
/**
* @param array $params
* @param Config $menu
* @return AbstractMenu
*/
public function instance(array $params = [], Config $menu = null)
{
$params = $params + $this->defaults;
$menus = $this->getMenus();
if (!$menus) {
throw new \RuntimeException('Site does not have
menus', 404);
}
if (empty($params['menu'])) {
$params['menu'] = $this->getDefaultMenuName();
if (!$params['menu'] &&
!empty($params['admin'])) {
// In admin just select the first menu if there isn't
default menu to be selected.
$params['menu'] = reset($menus);
};
} elseif ($params['menu'] == '-active-') {
$params['menu'] = $this->getActiveMenuName();
}
if (!$params['menu']) {
throw new \RuntimeException('No menu selected', 404);
}
if (!in_array($params['menu'], $menus)) {
throw new \RuntimeException('Menu not found', 404);
}
$instance = clone $this;
$instance->params = $params;
if ($menu) {
$instance->override = true;
$instance->config = $menu;
} else {
$instance->config = null;
}
$config = $instance->config();
$items = isset($config['items']) ?
$config['items'] : [];
// Create menu structure.
$instance->init($params);
// Get menu items from the system (if not specified otherwise).
if ($config->get('settings.type') !==
'custom') {
$instance->getList($params, $items);
}
// Add custom menu items.
$instance->addCustom($params, $items);
// Sort menu items.
$instance->sortAll();
return $instance;
}
/**
* Get menu configuration.
*
* @return Config
*/
public function config()
{
if (!$this->config) {
$gantry = static::gantry();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$menu = $this->params['menu'];
$file =
CompiledYamlFile::instance($locator("gantry-config://menu/{$menu}.yaml"));
$this->config = new Config($file->content());
$this->config->def('settings.title',
ucfirst($menu));
$file->free();
}
return $this->config;
}
public function name()
{
return $this->params['menu'];
}
public function root()
{
return $this->offsetGet('');
}
public function ordering()
{
$list = [];
foreach ($this->items as $name => $item) {
$groups = $item->groups();
if (count($groups) == 1 && empty($groups[0])) {
continue;
}
$list[$name] = [];
foreach ($groups as $col => $children) {
$list[$name][$col] = [];
foreach ($children as $child) {
$list[$name][$col][] = $child->path;
}
}
}
return $list;
}
public function items($withdefaults = true)
{
$list = [];
foreach ($this->items as $key => $item) {
if ($key !== '') {
$list[$item->path] = $item->toArray($withdefaults);
}
}
return $list;
}
public function settings()
{
return (array) $this->config()->get('settings');
}
/**
* @return object
*/
public function getBase()
{
return $this->offsetGet($this->base);
}
/**
* @return object
*/
public function getDefault()
{
return $this->offsetGet($this->default);
}
/**
* @return object
*/
public function getActive()
{
return $this->offsetGet($this->active);
}
/**
* @return string|null
*/
public function getCacheId()
{
return $this->active ?: '-inactive-';
}
public function isActive($item)
{
$active = $this->getActive();
if ($active && $item && ($active->path ===
$item->path || strpos($active->path, $item->path . '/')
=== 0)) {
return true;
}
return false;
}
public function isCurrent($item)
{
$active = $this->getActive();
return $item && $active && $item->path ===
$active->path;
}
public function init(&$params)
{
$this->items = ['' => new Item($this, '',
['layout' => 'horizontal'])];
}
public function add(Item $item)
{
$this->items[$item->path] = $item;
// If parent exists, assign menu item to its parent; otherwise
ignore menu item.
if (isset($this->items[$item->parent_id])) {
$this->items[$item->parent_id]->addChild($item);
} elseif (!$this->items['']->count()) {
$this->items[$item->parent_id] =
$this->items[''];
$this->items[$item->parent_id]->addChild($item);
}
return $this;
}
/**
* Get menu items from the platform.
*
* @param int $levels
* @return array
*/
abstract protected function getItemsFromPlatform($levels);
/**
* Get base menu item.
*
* If itemid is not specified or does not exist, return active menu
item.
* If there is no active menu item, fall back to home page for the
current language.
* If there is no home page, return null.
*
* @param string $path
*
* @return string
*/
abstract protected function calcBase($path);
/**
* Get a list of the menu items.
*
* @param array $params
* @param array $items
*/
abstract public function getList(array $params, array $items);
/**
* Add custom menu items.
*
* @param array $params
* @param array $items
*/
public function addCustom(array $params, array $items)
{
$start = $params['startLevel'];
$max = $params['maxLevels'];
$end = $max ? $start + $max - 1 : 0;
$config = $this->config();
$type = $config->get('settings.type');
// Add custom menu elements.
foreach ($items as $route => $item) {
if ($type !== 'custom' &&
(!isset($item['type']) || $item['type'] !==
'particle')) {
continue;
}
$tree = explode('/', $route);
$parentTree = $tree;
array_pop($parentTree);
// Enabled state should equal particle setting.
$item['enabled'] =
!isset($item['options']['particle']['enabled'])
||
!empty($item['options']['particle']['enabled']);
$item['level'] = $level = count($tree);
$item['parent_id'] = implode('/',
$parentTree);
if (($start && $start > $level)
|| ($end && $level > $end)
// TODO: Improve. In the mean time Item::add() handles this
part.
// || ($start > 1 && !in_array($tree[$start -
2], $tree))
) {
continue;
}
$item = new Item($this, $route, $item);
$this->add($item);
}
}
/**
* @param array $ordering
* @param string $path
* @param array $map
*/
public function sortAll(array $ordering = null, $path = '',
$map = null)
{
if ($ordering === null) {
$config = $this->config();
$ordering = $config['ordering'] ?
$config['ordering'] : [];
}
if (!isset($this->items[$path]) ||
!$this->items[$path]->hasChildren()) {
return;
}
if ($map === null) {
$map = $this->pathMap ? $this->pathMap->toArray() :
[];
}
$order = [];
$newMap = [];
$item = $this->items[$path];
if ($this->isAssoc($ordering)) {
foreach ($ordering as $key => $value) {
if ($map) {
$newMap = isset($map[$key]['children']) ?
$map[$key]['children'] : [];
$key = isset($map[$key]['path']) ?
basename($map[$key]['path']) : $key;
$order[$key] = $value;
}
if (is_array($value)) {
$this->sortAll($value, $path ? $path . '/'
. $key : $key, $newMap);
}
}
$item->sortChildren($order ?: $ordering);
} else {
foreach ($ordering as $i => $group) {
foreach ($group as $key => $value) {
if ($map) {
$newMap = isset($map[$key]['children']) ?
$map[$key]['children'] : [];
$key = isset($map[$key]['path']) ?
basename($map[$key]['path']) : $key;
$order[$i][$key] = $value;
}
if (is_array($value)) {
$this->sortAll($value, $path ? $path .
'/' . $key : $key, $newMap);
}
}
}
$item->groupChildren($order ?: $ordering);
}
}
protected function isAssoc(array $array)
{
return (array_values($array) !== $array);
}
}
PK���[��1D�&�&Component/Menu/Item.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Menu;
use RocketTheme\Toolbox\ArrayTraits\ArrayAccessWithGetters;
use RocketTheme\Toolbox\ArrayTraits\Export;
/**
* @property string $id
* @property string $type
* @property string $path
* @property string $alias
* @property string $title
* @property string $link
* @property string $parent_id
* @property string $layout
* @property int $browserNav
* @property bool $menu_text
* @property bool $visible
* @property int $group
* @property int $level
*/
class Item implements \ArrayAccess, \Iterator, \Serializable, \Countable
{
use ArrayAccessWithGetters, Export;
const VERSION = 1;
protected $items;
protected $menu;
protected $groups = [];
protected $children = [];
protected $url;
protected static $defaults = [
'id' => 0,
'type' => 'link',
'path' => null,
'alias' => null,
'title' => null,
'link' => null,
'parent_id' => null,
'layout' => 'list',
'target' => '_self',
'dropdown' => '',
'icon' => '',
'image' => '',
'subtitle' => '',
'hash' => '',
'class' => '',
'icon_only' => false,
'enabled' => true,
'visible' => true,
'group' => 0,
'columns' => [],
'level' => 0,
'link_title' => '',
'anchor_class' => ''
];
public function __construct(AbstractMenu $menu, $name, array $item =
[])
{
$this->menu = $menu;
$tree = explode('/', $name);
$alias = array_pop($tree);
$parent = implode('/', $tree);
// As we always calculate parent (it can change), prevent old one
from being inserted.
unset($item['parent_id']);
$this->items = $item + [
'id' => preg_replace('|[^a-z0-9]|i',
'-', $name) ?: 'root',
'path' => $name,
'alias' => $alias,
'title' => ucfirst($alias),
'link' => $name,
'parent_id' => $parent != '.' ? $parent
: '',
] + static::$defaults;
}
public function getDropdown()
{
if (!$this->items['dropdown']) {
return count($this->groups()) > 1 ? 'fullwidth'
: 'standard';
}
return $this->items['dropdown'];
}
public function serialize()
{
// FIXME: need to create collection class to gather the sibling
data.
return serialize([
'version' => static::VERSION,
'items' => $this->items,
'groups' => $this->groups,
'children' => $this->children,
'url' => $this->url
]);
}
public function unserialize($serialized)
{
// FIXME: need to create collection class to gather the sibling
data.
$data = unserialize($serialized);
if (!isset($data['version']) &&
$data['version'] === static::VERSION) {
throw new \UnexpectedValueException('Serialized data is
not valid');
}
$this->items = $data['items'];
$this->groups = $data['groups'];
$this->children = $data['children'];
$this->url = $data['url'];
}
/**
* @param string|null|bool $url
* @return string
*/
public function url($url = false)
{
if ($url !== false) {
$this->url = $url;
}
return $this->url;
}
/**
* @return AbstractMenu
* @deprecated Need to break relationship to the menu and use a
collection instead.
*/
protected function menu()
{
return $this->menu;
}
/**
* @return Item
*/
public function parent()
{
return $this->menu()[$this->items['parent_id']];
}
public function columnWidth($column)
{
if (isset($this->items['columns'][$column])) {
return $this->items['columns'][$column];
}
return 100 / count($this->groups());
}
public function groups()
{
if ($this->groups) {
$list = [];
foreach ($this->groups as $i => $group) {
$list[$i] = [];
foreach ($group as $path) {
$list[$i][] = $this->menu()[$path];
}
}
return $list;
}
return [$this->children()];
}
public function children()
{
$list = [];
foreach ($this as $child) {
$list[] = $child;
}
return $list;
}
public function hasChildren()
{
return !empty($this->children);
}
public function getGroup($i)
{
$groups = $this->groups();
$i = (int) $i;
return isset($groups[$i]) ? $groups[$i] : [];
}
public function update(array $data)
{
$this->items = array_replace($this->items, $data);
return $this;
}
public function addChild(Item $child)
{
$child->level = $this->level + 1;
$child->parent_id = $this->path;
$this->children[$child->alias] = $child->path;
return $this;
}
public function removeChild(Item $child)
{
unset($this->children[$child->alias]);
return $this;
}
public function sortChildren($ordering)
{
// Array with keys that point to the items.
$children =& $this->children;
if ($children) {
if (is_array($ordering)) {
// Remove extra items from ordering and reorder.
$children = array_replace(array_intersect_key($ordering,
$children), $children);
} else {
switch ((string) $ordering) {
case 'abc':
// Alphabetical ordering.
ksort($children, SORT_NATURAL);
break;
case 'cba':
// Reversed alphabetical ordering.
krsort($children, SORT_NATURAL);
break;
}
}
}
return $this;
}
public function reverse()
{
array_reverse($this->children, true);
array_reverse($this->groups, true);
return $this;
}
public function groupChildren(array $groups)
{
// Array with keys that point to the items.
$children =& $this->children;
if ($children) {
$menu = $this->menu();
$ordered = [];
// Create empty groups.
$this->groups = array_fill(0, max(1,
count($this->items['columns'])), []);
foreach ($groups as $i => $ordering) {
if (!is_array($ordering)) {
continue;
}
// Get the items for this group with proper ordering.
$group = array_replace(
array_intersect_key($ordering, $children),
array_intersect_key($children, $ordering)
);
// Assign each menu items to the group.
$group = array_map(
function($value) use ($i, $menu) {
$item = $menu[$value];
$item->group = $i;
return $value;
},
$group
);
// Update remaining children.
$children = array_diff_key($children, $ordering);
// Build child ordering.
$ordered += $group;
// Add items to the current group.
$this->groups[$i] = $group;
}
if ($children) {
// Add leftover children to the ordered list and to the
first group.
$ordered += $children;
$this->groups[0] += $children;
}
// Reorder children by their groups.
$children = $ordered;
}
return $this;
}
// Implements \Iterator
/**
* Returns the current child.
*
* @return Item
*/
public function current()
{
return $this->menu()[current($this->children)];
}
/**
* Returns the key of the current child.
*
* @return mixed Returns scalar on success, or NULL on failure.
*/
public function key()
{
return key($this->children);
}
/**
* Moves the current position to the next child.
*
* @return void
*/
public function next()
{
next($this->children);
}
/**
* Rewinds back to the first child.
*
* @return void
*/
public function rewind()
{
reset($this->children);
}
/**
* Count number of children.
*
* @return int
*/
public function count()
{
return count($this->children);
}
/**
* This method is called after Iterator::rewind() and Iterator::next()
to check if the current position is valid.
*
* @return bool Returns TRUE on success or FALSE on failure.
*/
public function valid()
{
return key($this->children) !== null;
}
/**
* Convert object into an array.
*
* @return array
*/
public function toArray($withDefaults = true)
{
$items = $this->items;
if (!$withDefaults) {
foreach (static::$defaults as $key => $value) {
if ($items[$key] === $value) {
unset($items[$key]);
}
}
}
return $items;
}
}
PK���[�{{GLGL'Component/Outline/OutlineCollection.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Outline;
use FilesystemIterator;
use Gantry\Component\Collection\Collection;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Component\Filesystem\Folder;
use Gantry\Component\Layout\Layout;
use Gantry\Framework\Atoms;
use RocketTheme\Toolbox\DI\Container;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceIterator;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class OutlineCollection extends Collection
{
/**
* @var Container
*/
protected $container;
/**
* @var string
*/
protected $path;
/**
* @param Container $container
* @param array $items
*/
public function __construct(Container $container, $items = [])
{
$this->container = $container;
$this->items = $items;
}
/**
* @param string $id
* @return string|null
*/
public function name($id)
{
return isset($this->items[$id]) ? $this->items[$id] : null;
}
/**
* @param string $id
* @return string
*/
public function title($id)
{
return isset($this->items[$id]) ? $this->items[$id] : $id;
}
public function all()
{
return $this;
}
public function system()
{
foreach ($this->items as $key => $item) {
if (substr($key, 0, 1) !== '_') {
unset($this->items[$key]);
}
}
return $this;
}
public function user()
{
foreach ($this->items as $key => $item) {
if (substr($key, 0, 1) === '_' || $key ==
'default') {
unset($this->items[$key]);
}
}
return $this;
}
public function filter(array $include = null)
{
if ($include !== null) {
foreach ($this->items as $key => $item) {
if (!in_array($key, $include)) {
unset($this->items[$key]);
}
}
}
return $this;
}
/**
* Returns list of all positions defined in all outlines.
*
* @return array
*/
public function positions()
{
$list = [];
foreach ($this->items as $name => $title) {
try {
$index = Layout::index($name);
$list += $index['positions'];
} catch (\Exception $e) {
// Layout cannot be read. We will just skip it instead of
throwing an exception.
}
}
return $list;
}
/**
* @param string $section
* @param bool $includeInherited
* @return array
*/
public function getOutlinesWithSection($section, $includeInherited =
true)
{
$list = [];
foreach ($this->items as $name => $title) {
try {
$index = Layout::index($name);
} catch (\Exception $e) {
// Layout cannot be read. We will just skip it instead of
throwing an exception.
continue;
}
if (isset($index['sections'][$section])) {
if (!$includeInherited) {
foreach ($index['inherit'] as $outline =>
$items) {
if (is_array($items) && in_array($section,
$items)) {
continue 2;
}
}
}
$list[$name] = $title;
}
}
return $list;
}
/**
* @param string $particle
* @param bool $includeInherited
* @return array
*/
public function getOutlinesWithParticle($particle, $includeInherited =
true)
{
$list = [];
foreach ($this->items as $name => $title) {
try {
$index = Layout::index($name);
} catch (\Exception $e) {
// Layout cannot be read. We will just skip it instead of
throwing an exception.
continue;
}
if (isset($index['particles'][$particle])) {
$ids = $index['particles'][$particle];
if (!$includeInherited &&
!empty($index['inherit'])) {
foreach ($index['inherit'] as $items) {
foreach ((array) $items as $id => $inheritId) {
unset($ids[$id]);
}
}
}
if ($ids) {
$list[$name] = $title;
}
}
}
return $list;
}
/**
* @param string $type
* @param bool $includeInherited
* @return array
*/
public function getOutlinesWithAtom($type, $includeInherited = true)
{
$list = [];
foreach ($this->items as $name => $title) {
$file =
CompiledYamlFile::instance("gantry-theme://config/{$name}/page/head.yaml");
$index = $file->content();
$file->free();
if (isset($index['atoms'])) {
foreach ($index['atoms'] as $atom) {
if (!empty($atom['id']) &&
$atom['type'] === $type && ($includeInherited ||
empty($atom['inherit']))) {
$list[$name] = $title;
}
}
}
}
return $list;
}
/**
* @param string $particle
* @param bool $includeInherited
* @return array
*/
public function getAllParticleInstances($particle, $includeInherited =
true)
{
$list = [];
foreach ($this->items as $name => $title) {
$list += $this->getParticleInstances($name, $particle,
$includeInherited);
}
return $list;
}
/**
* @param string $outline
* @param string $particle
* @param bool $includeInherited
* @return array
*/
public function getParticleInstances($outline, $particle,
$includeInherited = true)
{
$list = [];
$index = Layout::index($outline);
if (isset($index['particles'][$particle])) {
$list = $index['particles'][$particle];
if (!$includeInherited &&
!empty($index['inherit'])) {
foreach ($index['inherit'] as $items) {
foreach ((array) $items as $id => $inheritId) {
unset($list[$id]);
}
}
}
}
$layout = Layout::instance($outline);
foreach ($list as $id => $title) {
$item = clone $layout->find($id);
$block = $layout->block($id);
$item->block = isset($block->attributes) ?
$block->attributes : new \stdClass();
$list[$id] = $item;
}
return $list;
}
/**
* @param string $outline
* @param string $type
* @param bool $includeInherited
* @return array
*/
public function getAtomInstances($outline, $type, $includeInherited =
true)
{
$list = [];
$file =
CompiledYamlFile::instance("gantry-theme://config/{$outline}/page/head.yaml");
$head = $file->content();
$file->free();
if (isset($head['atoms'])) {
foreach ($head['atoms'] as $atom) {
if (!empty($atom['id']) &&
$atom['type'] === $type && ($includeInherited ||
empty($atom['inherit']['outline']))) {
$list[$atom['id']] = (object) $atom;
}
}
}
return $list;
}
/**
* Return list of outlines which are inheriting the specified atom.
*
* @param string $outline
* @param string $id
* @return array
*/
public function getInheritingOutlinesWithAtom($outline, $id = null)
{
$list = [];
foreach ($this->items as $name => $title) {
$file =
CompiledYamlFile::instance("gantry-theme://config/{$name}/page/head.yaml");
$head = $file->content();
$file->free();
if (isset($head['atoms'])) {
foreach ($head['atoms'] as $atom) {
if
(!empty($atom['inherit']['outline']) &&
$atom['inherit']['outline'] == $outline &&
(!$id || $atom['inherit']['atom'] == $id)) {
$list[$name] = $title;
}
}
}
}
return $list;
}
/**
* Return list of outlines which are inheriting the specified outline.
*
* You can additionally pass section or particle id to filter the
results for only that type.
*
* @param string $outline
* @param string|array $id
* @return array
*/
public function getInheritingOutlines($outline, $id = null)
{
$list = [];
foreach ($this->items as $name => $title) {
try {
$index = Layout::index($name);
} catch (\Exception $e) {
// Layout cannot be read. We will just skip it instead of
throwing an exception.
continue;
}
if (!empty($index['inherit'][$outline]) &&
(!$id || array_intersect((array) $id,
$index['inherit'][$outline]))) {
$list[$name] = $title;
}
}
return $list;
}
/**
* Return list of outlines inherited by the specified outline.
*
* You can additionally pass section or particle id to filter the
results for only that type.
*
* @param string $outline
* @param string $id
* @return array
*/
public function getInheritedOutlines($outline, $id = null)
{
try {
$index = Layout::index($outline);
} catch (\Exception $e) {
// Layout cannot be read. We will just return nothing instead
of throwing an exception.
return [];
}
$list = [];
foreach ($index['inherit'] as $name => $inherited) {
if (!$id || array_intersect_key((array) $id, $inherited[$id]))
{
$list[$name] = isset($this->items[$name]) ?
$this->items[$name] : $name;
}
}
return $list;
}
/**
* @param int|string $id
* @return int|string
*/
public function preset($id)
{
return $id;
}
/**
* @param int|string $id
* @return Layout
*/
public function layout($id)
{
return Layout::load($id);
}
/**
* @param int|string $id
* @return array
*/
public function layoutPreset($id)
{
$layout = Layout::load($id);
$preset = $layout->preset;
unset($layout);
return $preset;
}
/**
* @param string $path
* @return $this
* @throws \RuntimeException
*/
public function load($path = 'gantry-config://')
{
$this->path = $path;
$iterator = $this->getFilesystemIterator($path);
$files = [];
/** @var FilesystemIterator $info */
foreach ($iterator as $name => $info) {
if (!$info->isDir() || $name[0] == '.' ||
!is_file($info->getPathname() . '/index.yaml')) {
continue;
}
$files[$name] = ucwords(trim(preg_replace(['|_|',
'|/|'], [' ', ' / '], $name)));
}
unset($files['default']);
unset($files['menu']);
asort($files);
$this->items = $this->addDefaults($files);
return $this;
}
/**
* @param string|null $id
* @param string $title
* @param string|array $preset
* @return string
* @throws \RuntimeException
*/
public function create($id, $title = null, $preset = null)
{
$title = $title ?: 'Untitled';
$name = ltrim(strtolower(preg_replace('|[^a-z\d_-]|ui',
'_', $id ?: $title)), '_');
if (!$name) {
throw new \RuntimeException("Outline needs a name",
400);
}
if ($name === 'default') {
throw new \RuntimeException("Outline cannot use reserved
name '{$name}'", 400);
}
$name = $this->findFreeName($name);
if (!$id) {
$title = ucwords(trim(preg_replace(['|_|',
'|/|'], [' ', ' / '], $name)));
}
if (!is_array($preset)) {
// Load preset.
$preset = Layout::preset($preset ?: 'default');
}
// Create layout and index for the new layout.
$layout = new Layout($name, $preset);
$layout->save()->saveIndex();
$this->items[$name] = $title;
return $name;
}
/**
* @param string $id
* @param string $title
* @param bool $inherit
* @return string
* @throws \RuntimeException
*/
public function duplicate($id, $title = null, $inherit = false)
{
if (!$this->canDuplicate($id)) {
throw new \RuntimeException("Outline '$id'
cannot be duplicated", 400);
}
$layout = Layout::load($id);
if ($inherit) {
$layout->inheritAll()->clean();
}
$new = $this->create(null, $title, $layout->toArray() +
['preset' => $layout->preset]);
if ($id === 'default') {
// For Base Outline we're done.
return $new;
}
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
$path =
$locator->findResource("{$this->path}/{$id}");
if (!$path) {
// Nothing to copy.
return $new;
}
$newPath =
$locator->findResource("{$this->path}/{$new}", true, true);
try {
// Copy everything over except index, layout and assignments.
Folder::copy($path, $newPath,
'/^(index|layout|assignments)\..*$/');
} catch (\Exception $e) {
throw new \RuntimeException(sprintf('Duplicating Outline
failed: ', $e->getMessage()), 500, $e);
}
return $new;
}
/**
* @param string $id
* @param string $title
* @return string
* @throws \RuntimeException
*/
public function rename($id, $title)
{
if (!$this->canDelete($id)) {
throw new \RuntimeException("Outline '$id'
cannot be renamed", 400);
}
$gantry = $this->container;
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$path =
$locator->findResource("{$this->path}/{$id}", true, true);
if (!$path || !is_dir($path)) {
throw new \RuntimeException('Outline not found',
404);
}
$folder = strtolower(preg_replace('|[^a-z\d_-]|ui',
'_', $title));
if ($folder === 'default' || $folder[0] ===
'_') {
throw new \RuntimeException("Outline cannot use reserved
name '{$folder}'", 400);
}
$newPath =
$locator->findResource("{$this->path}/{$folder}", true,
true);
if (is_dir($newPath)) {
throw new \RuntimeException("Outline '$id'
already exists.", 400);
}
try {
foreach ($this->getInheritingOutlines($id) as $outline =>
$title) {
$this->layout($outline)->updateInheritance($id,
$folder)->save()->saveIndex();
}
foreach ($this->getInheritingOutlinesWithAtom($id) as
$outline => $title) {
Atoms::instance($outline)->updateInheritance($id,
$folder)->save();
}
Folder::move($path, $newPath);
} catch (\Exception $e) {
throw new \RuntimeException(sprintf('Renaming Outline
failed: %s', $e->getMessage()), 500, $e);
}
$this->items[$id] = $title;
return $folder;
}
/**
* @param string $id
* @throws \RuntimeException
*/
public function delete($id)
{
if (!$this->canDelete($id)) {
throw new \RuntimeException("Outline '$id'
cannot be deleted", 400);
}
$gantry = $this->container;
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$path =
$locator->findResource("{$this->path}/{$id}", true, true);
if (!is_dir($path)) {
throw new \RuntimeException('Outline not found',
404);
}
foreach ($this->getInheritingOutlines($id) as $outline =>
$title) {
$this->layout($outline)->updateInheritance($id)->save()->saveIndex();
}
foreach ($this->getInheritingOutlinesWithAtom($id) as $outline
=> $title) {
Atoms::instance($outline)->updateInheritance($id)->save();
}
if (file_exists($path)) {
Folder::delete($path);
}
unset($this->items[$id]);
}
/**
* @param string $id
* @return boolean
*/
public function canDuplicate($id)
{
if (!isset($this->items[$id])) {
return false;
}
return true;
}
/**
* @param string $id
* @return boolean
*/
public function canDelete($id)
{
if (!$id || $id[0] === '_' || $id ===
'default') {
return false;
}
return true;
}
/**
* @param string $id
* @return boolean
*/
public function isDefault($id)
{
return $id === 'default';
}
/**
* @param array $outlines
* @return array
*/
protected function addDefaults(array $outlines)
{
return [
'default' => 'Base Outline',
'_body_only' => 'Body Only',
'_error' => 'Error',
'_offline' => 'Offline'
] + $outlines;
}
/**
* Find unused name with number appended to it when duplicating an
outline.
*
* @param string $id
* @return string
*/
protected function findFreeName($id)
{
if (!isset($this->items[$id])) {
return $id;
}
$name = $id;
$count = 0;
if (preg_match('|^(?:_)?(.*?)(?:_(\d+))?$|ui', $id,
$matches)) {
$matches += ['', '', ''];
list (, $name, $count) = $matches;
}
$count = max(1, $count);
do {
$count++;
} while (isset($this->items["{$name}_{$count}"]));
return "{$name}_{$count}";
}
protected function getFilesystemIterator($path)
{
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
$custom = $locator->findResource($path, true, true);
if (is_dir($custom)) {
/** @var FilesystemIterator $iterator */
$iterator = new FilesystemIterator(
$custom,
FilesystemIterator::CURRENT_AS_SELF |
FilesystemIterator::KEY_AS_FILENAME |
FilesystemIterator::UNIX_PATHS |
FilesystemIterator::SKIP_DOTS
);
} else {
/** @var UniformResourceIterator $iterator */
$iterator = $locator->getIterator(
$path,
UniformResourceIterator::CURRENT_AS_SELF |
UniformResourceIterator::KEY_AS_FILENAME |
UniformResourceIterator::UNIX_PATHS |
UniformResourceIterator::SKIP_DOTS
);
}
return $iterator;
}
}
PK���[�T�ڍ�Component/Position/Module.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Position;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Framework\Gantry;
use RocketTheme\Toolbox\ArrayTraits\Export;
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Module implements \ArrayAccess
{
use NestedArrayAccessWithGetters, Export;
public $name;
public $position;
public $assigned;
protected $items;
/**
* Module constructor.
*
* @param string $name
* @param string $position
* @param array $data
*/
public function __construct($name, $position = null, array $data =
null)
{
$this->name = $name;
$this->position = $position;
if ($data) {
$this->init($data);
} else {
$this->load();
}
}
public function update(array $data)
{
$this->init($data);
return $this;
}
/**
* Save module.
*
* @param string $position
* @param string $name
* @return $this
*/
public function save($name = null, $position = null)
{
$this->name = $name ?: $this->name;
$this->position = $position ?: $this->position;
$items = $this->toArray();
unset($items['position'], $items['id']);
$file = $this->file(true);
$file->save($items);
return $this;
}
/**
* Delete module.
*
* @return $this
*/
public function delete()
{
$file = $this->file(true);
if ($file->exists()) {
$file->delete();
}
return $this;
}
/**
* Return true if module exists.
*
* @return bool
*/
public function exists()
{
return $this->name ? $this->file()->exists() : false;
}
public function toArray()
{
return ['position' => $this->position,
'id' => $this->name] + $this->items;
}
protected function load()
{
$file = $this->file();
$this->init($file->content());
$file->free();
}
protected function init($data)
{
unset($data['id'], $data['position']);
$this->items = $data;
if (isset($this->items['assignments'])) {
$assignments = $this->items['assignments'];
if (is_array($assignments)) {
$this->assigned = 'some';
} elseif ($assignments !== 'all') {
$this->assigned = 'none';
} else {
$this->assigned = 'all';
}
} else {
$this->assigned = 'all';
}
}
protected function file($save = false)
{
$position = $this->position ?: '_unassigned_';
$this->name = $this->name ?: ($save ?
$this->findFreeName() : null);
$name = $this->name ?: '_untitled_';
/** @var UniformResourceLocator $locator */
$locator = Gantry::instance()['locator'];
return
CompiledYamlFile::instance($locator->findResource("gantry-positions://{$position}/{$name}.yaml",
true, $save));
}
/**
* Find unused name with number appended.
*/
protected function findFreeName()
{
$position = $this->position ?: '_unassigned_';
$name = $this->get('type');
$name = $name == 'particle' ?
$this->get('options.type') : $name;
/** @var UniformResourceLocator $locator */
$locator = Gantry::instance()['locator'];
if
(!file_exists($locator->findResource("gantry-positions://{$position}/{$name}.yaml",
true, true))) {
return $name;
}
$count = 1;
do {
$count++;
} while
(file_exists($locator->findResource("gantry-positions://{$position}/{$name}_{$count}.yaml",
true, true)));
return "{$name}_{$count}";
}
}
PK���[�l*�)#)#Component/Position/Position.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Position;
use Gantry\Component\Collection\Collection;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Component\Filesystem\Folder;
use Gantry\Framework\Gantry;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use Symfony\Component\Yaml\Yaml;
class Position extends Collection
{
public $name;
public $title;
protected $modules = [];
/**
* Position constructor.
*
* @param string $name
* @param array $items
*/
public function __construct($name, array $items = null)
{
$this->name = $name;
$this->load($items);
}
/**
* Save position.
*
* @return $this
*/
public function save()
{
$file = $this->file(true);
$file->save($this->toArray());
return $this;
}
/**
* Clone position together with its modules. Returns new position.
*
* @param string $name
* @return Position
*/
public function duplicate($name)
{
$new = clone $this;
$new->name = $name;
$new->save();
foreach ($this as $module) {
$clone = clone $module;
$clone->position = $name;
$clone->save();
}
return $new;
}
/**
* Raname module key
*
* @param string $name
* @return static
*/
public function rename($name)
{
$new = $this->duplicate($name);
$this->delete();
return $new;
}
/**
* Delete position.
*
* @return $this
*/
public function delete()
{
$file = $this->file(true);
if ($file->exists()) {
$file->delete();
}
$folder = $this->folder(true);
if (is_dir($folder)) {
Folder::delete($folder);
}
return $this;
}
/**
* Update modules in the position.
*
* @param array $items
* @return $this
*/
public function update(array $items)
{
$list = [];
foreach ($items as $item) {
$name = ($item instanceof Module) ? $item->name : $item;
$list[] = $name;
if (!in_array($name, $this->items)) {
$this->add($item);
}
}
$remove = array_diff($this->items, $list);
foreach ($remove as $item) {
$module = $this->get($item);
if ($module->position === $this->name) {
$module->delete();
}
}
$this->items = $list;
return $this;
}
/**
* @param Module|string $item
* @param string $name Temporary name for the module.
* @return $this
*/
public function add($item, $name = null)
{
if ($item instanceof Module) {
$this->modules[$name ?: $item->name] = $item;
$item = $name ?: $item->name;
}
$this->items[] = $item;
return $this;
}
public function remove($item)
{
if ($item instanceof Module) {
$item = $item->name;
}
unset($this->modules[$item]);
$this->items = array_diff($this->items, $item);
return $this;
}
/**
* @param $name
* @return Module
*/
public function get($name)
{
if (!isset($this->modules[$name])) {
$this->modules[$name] = $this->loadModule($name);
}
return $this->modules[$name];
}
/**
* Returns the value at specified offset.
*
* @param string $offset The offset to retrieve.
* @return Module
*/
public function offsetGet($offset)
{
if (!isset($this->items[$offset])) {
return null;
}
$name = $this->items[$offset];
if (!isset($this->modules[$name])) {
$this->modules[$name] = $this->loadModule($name);
}
return $this->modules[$name];
}
/**
* Assigns a value to the specified offset.
*
* @param mixed $offset The offset to assign the value to.
* @param mixed $value The value to set.
*/
public function offsetSet($offset, $value)
{
if (!$value instanceof Position) {
throw new \InvalidArgumentException('Value has to be
instance of Position');
}
if (is_null($offset)) {
$this->items[] = $value->name;
$this->modules[$value->name] = $value;
} else {
$this->items[$offset] = $value->name;
$this->modules[$value->name] = $value;
}
}
/**
* Unsets an offset.
*
* @param mixed $offset The offset to unset.
*/
public function offsetUnset($offset)
{
parent::offsetUnset($offset);
if (!isset($this->items[$offset])) {
return;
}
$name = $this->items[$offset];
if (isset($this->modules[$name])) {
unset($this->modules[$name]);
}
}
/**
* @return \ArrayIterator
*/
public function getIterator()
{
$items = [];
foreach ($this->items as $key => $name) {
$items[] = $this->offsetGet($key);
}
return new \ArrayIterator($items);
}
/**
* @return array
*/
public function toArray($includeModules = false)
{
$array = [
'name' => $this->name,
'title' => $this->title,
];
if (!$includeModules) {
$array['ordering'] = $this->items;
} else {
$list = [];
foreach ($this->getIterator() as $key => $module) {
$list[$key] = $module->toArray();
}
$array['modules'] = $list;
}
return $array;
}
/**
* @param int $inline
* @param int $indent
* @param bool $includeModules
* @return string
*/
public function toYaml($inline = 3, $indent = 2, $includeModules =
false)
{
return Yaml::dump($this->toArray($includeModules), $inline,
$indent, true, false);
}
/**
* @param bool $includeModules
* @return string
*/
public function toJson($includeModules = false)
{
return json_encode($this->toArray($includeModules));
}
/**
* @return array
*/
public function listModules()
{
$list = [];
foreach ($this->items as $name) {
$list[] = "{$this->name}/{$name}";
}
return $list;
}
/**
* @param bool $save
* @return string
*/
public function folder($save = false)
{
return $this->locator()->findResource($this->path(), true,
$save);
}
/**
* @param $data
*/
protected function load($data)
{
if ($data === null) {
$file = $this->file();
$data = $file->content();
$file->free();
}
$this->title = isset($data['title']) ?
$data['title'] : $this->name;
if (isset($data['modules'])) {
foreach ($data['modules'] as $array) {
$this->add(new Module($array['id'],
$this->name, $array), $array['id'] ?: rand());
}
return;
}
// Sort modules by ordering, if items are not listed in ordering,
use alphabetical order.
$ordering = isset($data['ordering']) ?
array_flip($data['ordering']) : [];
$path = $this->locator()->findResource($this->path());
$files = $path ? Folder::all(
$path,
[
'compare' => 'Filename',
'pattern' => '|\.yaml$|',
'folders' => false,
'recursive' => false,
'key' => 'Filename',
'filters' => ['key' =>
'|\.yaml$|']
]
) : [];
ksort($files);
$this->items = array_keys($ordering + $files);
}
/**
* @param string $name
* @return $this
*/
protected function loadModule($name)
{
return new Module($name, $this->name);
}
/**
* @param bool $save
* @return CompiledYamlFile
*/
protected function file($save = false)
{
return
CompiledYamlFile::instance($this->locator()->findResource($this->path()
. '.yaml', true, $save));
}
/**
* @return UniformResourceLocator
*/
protected function locator()
{
return Gantry::instance()['locator'];
}
/**
* @return string
*/
protected function path()
{
return "gantry-positions://{$this->name}";
}
}
PK���[���..
Component/Position/Positions.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Position;
use Gantry\Component\Collection\Collection;
use Gantry\Component\File\CompiledYamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceIterator;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use RocketTheme\Toolbox\DI\Container;
class Positions extends Collection
{
/**
* @var array|Position[]
*/
protected $items;
/**
* @var string
*/
protected $path;
/**
* @var Container
*/
protected $container;
public function __construct(Container $container)
{
$this->container = $container;
}
/**
* @param string $path
*
* @return $this
* @throws \RuntimeException
*/
public function load($path = 'gantry-positions://')
{
$this->path = $path;
$positions = [];
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
if ($locator->findResource($path)) {
/** @var UniformResourceIterator $iterator */
$iterator = $locator->getIterator($path);
/** @var UniformResourceIterator $info */
foreach ($iterator as $info) {
if (!$info->isFile() || $info->getExtension() !==
'yaml') {
continue;
}
$name = $info->getBasename('.yaml');
$position =
CompiledYamlFile::instance($info->getPathname())->content();
// Only use filesystem position if it it is properly set
up.
if ($position) {
$positions[$name] = new Position($name, $position);
}
}
}
// Add empty positions from the layouts.
foreach ($this->container['outlines']->positions()
as $name => $title) {
if (!isset($positions[$name])) {
$positions[$name] = new Position($name, ['title'
=> $title]);
}
}
ksort($positions);
$this->items = $positions;
return $this;
}
/**
* Updates all positions with their modules from an array and saves
them.
*
* @param array $data
* @return $this
*/
public function import(array $data)
{
foreach ($data as $pos) {
$list = [];
$position = $pos['name'];
foreach ($pos['modules'] as $item) {
$name = !empty($item['id']) ?
$item['id'] : '';
if ($name && !empty($item['position'])) {
$module =
$this[$item['position']]->get($name);
if ($position !== $item['position']) {
$module->delete();
}
} else {
$module = new Module($name, $position);
}
$module->update($item)->save($name, $position);
$list[] = $module;
}
$this[$pos['name']]->update($list)->save();
}
return $this;
}
/**
* @param Position $item
* @return $this
*/
public function add($item)
{
if ($item instanceof Position) {
$this->items[$item->name] = $item;
}
return $this;
}
/**
* @param string $title
* @param string $id
*
* @return string
* @throws \RuntimeException
*/
public function create($title = 'Untitled', $id = null)
{
$name = strtolower(preg_replace('|[^a-z\d_-]|ui',
'_', $id ?: $title));
if (!$name) {
throw new \RuntimeException("Position needs a name",
400);
}
$name = $this->findFreeName($name);
$position = new Position($name, ['title' => $title]);
$position->save();
return $name;
}
/**
* @param string $id
* @param string $new
*
* @return string
* @throws \RuntimeException
*/
public function duplicate($id, $new = null)
{
if (!isset($this->items[$id])) {
throw new \RuntimeException(sprintf("Duplicating Position
failed: '%s' not found.", $id), 400);
}
$new = $this->findFreeName($new ?
strtolower(preg_replace('|[^a-z\d_-]|ui', '_', $new)) :
$id);
$position = $this->items[$id];
$new = $position->duplicate($new);
return $new->name;
}
/**
* @param string $id
* @param string $new
*
* @return string
* @throws \RuntimeException
*/
public function rename($id, $new)
{
if (!isset($this->items[$id])) {
throw new \RuntimeException(sprintf("Renaming Position
failed: '%s' not found.", $id), 400);
}
$newId = strtolower(preg_replace('|[^a-z\d_-]|ui',
'_', $new));
if (isset($this->items[$newId])) {
throw new \RuntimeException(sprintf("Renaming Position
failed: '%s' already exists.", $newId), 400);
}
$position = $this->items[$id];
$position->rename($new);
return $position->name;
}
/**
* @param string $id
*
* @throws \RuntimeException
*/
public function delete($id)
{
if (!isset($this->items[$id])) {
throw new \RuntimeException(sprintf("Deleting Position
failed: '%s' not found.", $id), 400);
}
$position = $this->items[$id];
$position->delete();
}
/**
* Find unused name with number appended to it when duplicating an
position.
*
* @param string $id
*
* @return string
*/
protected function findFreeName($id)
{
if (!isset($this->items[$id])) {
return $id;
}
$name = $id;
$count = 0;
if (preg_match('|^(?:_)?(.*?)(?:_(\d+))?$|ui', $id,
$matches)) {
$matches += ['', '', ''];
list (, $name, $count) = $matches;
}
$count = max(1, $count);
do {
$count++;
} while (isset($this->items["{$name}_{$count}"]));
return "{$name}_{$count}";
}
}
PK���[���O��Component/Remote/Response.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Remote;
class Response
{
/**
* The callback for the progress
*
* @var callable Either a function or callback in array notation
*/
public static $callback = null;
/**
* Which method to use for HTTP calls, can be 'curl',
'fopen' or 'auto'. Auto is default and fopen is the
preferred method
*
* @var string
*/
private static $method = 'auto';
/**
* Default parameters for `curl` and `fopen`
*
* @var array
*/
private static $defaults = [
'curl' => [
CURLOPT_REFERER => 'Gantry5 Response',
CURLOPT_USERAGENT => 'Gantry5 Response',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HEADER => false,
/**
* Example of callback parameters from within your own class
*/
//CURLOPT_NOPROGRESS => false,
//CURLOPT_PROGRESSFUNCTION => [$this, 'progress']
],
'fopen' => [
'method' => 'GET',
'user_agent' => 'Gantry5 Response',
'max_redirects' => 5,
'follow_location' => 1,
'timeout' => 15,
/**
* Example of callback parameters from within your own class
*/
//'notification' => [$this, 'progress']
]
];
/**
* Sets the preferred method to use for making HTTP calls.
*
* @param string $method Default is `auto`
*
* @return Response
*/
public static function setMethod($method = 'auto')
{
if (!in_array($method, ['auto', 'curl',
'fopen'])) {
$method = 'auto';
}
self::$method = $method;
return new self();
}
/**
* Makes a request to the URL by using the preferred method
*
* @param string $uri URL to call
* @param array $options An array of parameters for both `curl` and
`fopen`
* @param callable $callback
*
* @return string The response of the request
*/
public static function get($uri = '', $options = [],
$callback = null)
{
if (!self::isCurlAvailable() && !self::isFopenAvailable())
{
throw new \RuntimeException('Could not start an HTTP
request. `allow_url_open` is disabled and `cURL` is not available');
}
$options = array_replace_recursive(self::$defaults, $options);
$method = 'get' . ucfirst(strtolower(self::$method));
self::$callback = $callback;
return static::$method($uri, $options, $callback);
}
/**
* Checks if cURL is available
*
* @return boolean
*/
public static function isCurlAvailable()
{
return function_exists('curl_version');
}
/**
* Checks if the remote fopen request is enabled in PHP
*
* @return boolean
*/
public static function isFopenAvailable()
{
return preg_match('/1|yes|on|true/i',
ini_get('allow_url_fopen'));
}
/**
* Progress normalized for cURL and fopen
*
* @return array Normalized array with useful data.
* Format: ['code' => int|false,
'filesize' => bytes, 'transferred' => bytes,
'percent' => int]
*/
public static function progress()
{
static $filesize = null;
$args = func_get_args();
$isCurlResource = is_resource($args[0]) &&
get_resource_type($args[0]) == 'curl';
$notification_code = !$isCurlResource ? $args[0] : false;
$bytes_transferred = $isCurlResource ? $args[2] : $args[4];
if ($isCurlResource) {
$filesize = $args[1];
} elseif ($notification_code == STREAM_NOTIFY_FILE_SIZE_IS) {
$filesize = $args[5];
}
if ($bytes_transferred > 0) {
if ($notification_code == STREAM_NOTIFY_PROGRESS |
STREAM_NOTIFY_COMPLETED || $isCurlResource) {
$progress = [
'code' => $notification_code,
'filesize' => $filesize,
'transferred' => $bytes_transferred,
'percent' => $filesize <= 0 ?
'-' : round(($bytes_transferred * 100) / $filesize, 1)
];
if (self::$callback !== null) {
call_user_func_array(self::$callback, [$progress]);
}
}
}
}
/**
* Automatically picks the preferred method
*
* @return string The response of the request
*/
private static function getAuto()
{
if (self::isFopenAvailable()) {
return self::getFopen(func_get_args());
}
if (self::isCurlAvailable()) {
return self::getCurl(func_get_args());
}
return '';
}
/**
* Starts a HTTP request via fopen
*
* @return string The response of the request
*/
private static function getFopen()
{
if (count($args = func_get_args()) == 1) {
$args = $args[0];
}
$uri = $args[0];
$options = $args[1];
$callback = $args[2];
if ($callback) {
$options['fopen']['notification'] =
['self', 'progress'];
}
$stream = stream_context_create(['http' =>
$options['fopen']], $options['fopen']);
$content = @file_get_contents($uri, false, $stream);
if ($content === false) {
throw new \RuntimeException("Error while trying to
download '$uri'");
}
return $content;
}
/**
* Starts a HTTP request via cURL
*
* @return string The response of the request
*/
private static function getCurl()
{
$args = func_get_args();
$args = count($args) > 1 ? $args : array_shift($args);
$uri = $args[0];
$options = $args[1];
$callback = $args[2];
$ch = curl_init($uri);
curl_setopt_array($ch, $options['curl']);
if ($callback) {
curl_setopt_array(
$ch,
[
CURLOPT_NOPROGRESS => false,
CURLOPT_PROGRESSFUNCTION => ['self',
'progress']
]
);
}
$response = curl_exec($ch);
if ($errno = curl_errno($ch)) {
$error_message = curl_strerror($errno);
throw new \RuntimeException("cURL error ({$errno}):\n
{$error_message}");
}
curl_close($ch);
return $response;
}
}
PK���[��N@Component/Request/Input.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Request;
use RocketTheme\Toolbox\ArrayTraits\Export;
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
use RocketTheme\Toolbox\ArrayTraits\Iterator;
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters;
class Input implements \ArrayAccess, \Iterator, ExportInterface
{
use NestedArrayAccessWithGetters, Iterator, Export;
/**
* @var array
*/
protected $items;
/**
* Constructor to initialize array.
*
* @param array $items Initial items inside the iterator.
*/
public function __construct(array &$items = [])
{
$this->items = &$items;
}
/**
* Returns input array. If there are any JSON encoded fields (key:
_json), those will be decoded as well.
*
* @param string $path Dot separated path to the requested
value.
* @param mixed $default Default value (or null).
* @param string $separator Separator, defaults to '.'
* @return array
*/
public function getArray($path = null, $default = null, $separator =
'.')
{
$data = $path ? $this->get($path, $default, $separator) :
$this->items;
return (array) $this->getChildren($data);
}
/**
* Returns JSON decoded input array.
*
* @param string $path Dot separated path to the requested
value.
* @param mixed $default Default value (or null).
* @param string $separator Separator, defaults to '.'
* @return array
*/
public function getJsonArray($path = null, $default = null, $separator
= '.')
{
return (array) $this->getJson($path, $default, $separator,
true);
}
/**
* Returns JSON decoded input. Accosiative arrays become objects.
*
* @param string|null $path Dot separated path to the requested
value.
* @param mixed $default Default value (or null).
* @param string $separator Separator, defaults to '.'
* @param bool $assoc True to return associative arrays
instead of objects.
* @return mixed
*/
public function getJson($path = null, $default = null, $separator =
'.', $assoc = false)
{
$data = $this->get($path, null, $separator);
if (!isset($data)) {
return $default;
}
if (!is_string($data)) {
throw new \RuntimeException(sprintf('%s::%s(%s) expects
input to be JSON encoded string', __CLASS__, __FUNCTION__, $path));
}
$data = json_decode($data, $assoc);
if (!isset($data)) {
throw new \RuntimeException(sprintf('%s::%s(): %s',
__CLASS__, __FUNCTION__, json_last_error_msg()));
}
return $data;
}
/**
* @param $current
* @return array|mixed
* @internal
*/
protected function getChildren(&$current)
{
if (!is_array($current)) {
return $current;
}
$array = [];
foreach ($current as $key => &$value) {
if ($key === '_json') {
$array += json_decode($value, true);
} else {
$array[$key] = $this->getChildren($value);
}
}
return $array;
}
}
PK���[(5���Component/Request/Request.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Request;
class Request
{
/**
* @var string
*/
protected $method;
/**
* @var Input
*/
public $get;
/**
* @var Input
*/
public $post;
/**
* @var Input
*/
public $cookie;
/**
* @var Input
*/
public $server;
/**
* @var Input
*/
public $request;
public function __construct()
{
$this->init();
}
public function getMethod()
{
if (!$this->method) {
$method = $this->server['REQUEST_METHOD'] ?:
'GET';
if ('POST' === $method) {
$method =
$this->server['X-HTTP-METHOD-OVERRIDE'] ?: $method;
$method = $this->post['METHOD'] ?: $method;
}
$this->method = strtoupper($method);
}
return $this->method;
}
protected function init()
{
$this->get = new Input($_GET);
$this->post = new Input($_POST);
$this->cookie = new Input($_COOKIE);
$this->server = new Input($_SERVER);
$this->request = new Input($_REQUEST);
}
}
PK���[]�>J��#Component/Response/HtmlResponse.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Response;
class HtmlResponse extends Response
{
}
PK���[(�gg#Component/Response/JsonResponse.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Response;
class JsonResponse extends Response
{
public $mimeType = 'application/json';
protected $success = true;
protected $message;
protected $exceptions = [];
protected $messages = [];
protected $content = [];
/**
* @param string $content
* @param bool $success
* @return $this
*/
public function setContent($content, $success = true)
{
$this->success = (bool) $success;
if (is_array($content)) {
foreach ($content as $key => $value) {
$this->parseValue($key, $value);
}
} else {
$this->parseValue(null, $content);
}
return $this;
}
/**
* @return string
*/
public function __toString()
{
// Empty output buffer to make sure that the response is clean and
valid.
while (($output = ob_get_clean()) !== false) {
// In debug mode send also output buffers (debug dumps, PHP
notices and warnings).
if ($output && (GANTRY5_DEBUG || headers_sent())) {
$this->messages['php'][] = $output;
}
}
$json = [
'code' => $this->code,
'success' => $this->success
];
if ($this->messages) {
$json['messages'] = $this->messages;
}
if ($this->exceptions) {
$json['exceptions'] = $this->exceptions;
}
if (GANTRY5_DEBUG) {
$json['memory'] = ['peak' =>
memory_get_peak_usage(), 'current' => memory_get_usage()];
}
$json += $this->content;
return (string) json_encode($json);
}
protected function parseValue($key, $value)
{
if ($value instanceof \Exception) {
// Prepare the error response if we are dealing with an error.
$this->success = false;
$this->exceptions = $this->parseException($value);
} elseif ($value instanceof HtmlResponse) {
// Add HTML response (numeric keys are always integers).
$key = !$key || is_int($key) ? 'html' : $key;
$this->content[$key] = trim((string) $value);
} elseif (is_null($key)) {
// If the returned value was not an array, put the contents
into data variable.
$this->content['data'] = $value;
} elseif (is_int($key)) {
// If the key was an integer, also put the contents into data
variable.
$this->content['data'][$key] = $value;
} else {
$this->content[$key] = $value;
}
}
protected function parseException(\Exception $e)
{
$this->code = $e->getCode();
// Build data from exceptions.
$exceptions = [];
do {
$exception = [
'code' => $e->getCode(),
'message' => $e->getMessage()
];
if (GANTRY5_DEBUG) {
$exception += [
'type' => get_class($e),
'file' => $e->getFile(),
'line' => $e->getLine()
];
}
$exceptions[] = $exception;
$e = $e->getPrevious();
}
while (GANTRY5_DEBUG && $e);
return $exceptions;
}
}
PK���[�~�77'Component/Response/RedirectResponse.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Response;
class RedirectResponse extends Response
{
public function __construct($content = '', $status = 303)
{
parent::__construct('', $status);
$this->setHeader('Location', $content);
}
public function getContent()
{
return (string) $this->getHeaders()['Location'];
}
public function setContent($content)
{
$this->setHeader('Location', $content);
}
}
PK���[ʚ@%��Component/Response/Response.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Response;
class Response
{
public $charset = 'utf-8';
public $mimeType = 'text/html';
protected $code = 200;
protected $message = 'OK';
protected $lifetime = 0;
protected $etag;
/**
* @var array Response headers.
*/
protected $headers = [];
/**
* @var string Response body.
*/
protected $content;
protected $responseCodes = [
200 => 'OK',
400 => 'Bad Request',
401 => 'Unauthorized',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
410 => 'Gone',
500 => 'Internal Server Error',
501 => 'Not Implemented',
503 => 'Service Temporarily Unavailable'
];
public function __construct($content = '', $status = 200)
{
if ($content) {
$this->setContent($content);
}
if ($status != 200) {
$this->setStatusCode($status);
}
}
/**
* @param int $seconds
* @return $this
*/
public function setLifetime($seconds)
{
$this->lifetime = $seconds;
return $this;
}
/**
* @param mixed $key
* @return $this
*/
public function setKey($key)
{
$this->etag = md5(json_encode($key));
return $this;
}
/**
* @return int
*/
public function getStatusCode()
{
return $this->code;
}
/**
* @param int $code
* @param string $message
* @return $this
*/
public function setStatusCode($code, $message = null)
{
if ($message) {
$this->code = $code;
$this->message = $message;
} else {
$this->code = isset($this->responseCodes[$code]) ? (int)
$code : 500;
$this->message = $this->responseCodes[$this->code];
}
return $this;
}
/**
* @return string
*/
public function getStatus()
{
$code = $this->getStatusCode();
return $code . ' ' .
(isset($this->responseCodes[$code]) ? $this->responseCodes[$code] :
'Unknown error');
}
/**
* @return array
*/
public function getHeaders()
{
return $this->headers;
}
/**
* @param array $headers
* @param bool $replace
* @return $this
*/
public function setHeaders(array $headers, $replace = false)
{
foreach ($headers as $key => $values) {
$act = $replace;
foreach ((array) $values as $value) {
$this->setHeader($key, $value, $act);
$act = false;
}
}
return $this;
}
/**
* @return $this
*/
public function clearHeaders()
{
$this->headers = [];
return $this;
}
/**
* @param $name
* @param $value
* @param bool $replace
* @return $this
*/
public function setHeader($name, $value, $replace = false)
{
if ($replace) {
$this->headers[$name] = [$value];
} else {
$this->headers[$name][] = $value;
}
return $this;
}
/**
* @return string
*/
public function getContent()
{
return (string) $this->content;
}
/**
* @param string $content
* @return Response
* @throws \UnexpectedValueException
*/
public function setContent($content) {
if ($content !== null && !is_string($content) &&
!is_numeric($content) && !is_callable([$content,
'__toString'])) {
throw new \UnexpectedValueException(
sprintf('Content must be a string or object
implementing __toString()')
);
}
$this->content = $content;
return $this;
}
/**
* @return string
*/
public function __toString()
{
return (string) $this->content;
}
}
PK���[V�99Component/Router/Router.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Router;
use Gantry\Admin\EventListener;
use Gantry\Admin\Theme;
use Gantry\Component\Controller\BaseController;
use Gantry\Component\Response\HtmlResponse;
use Gantry\Component\Response\Response;
use Gantry\Component\Response\JsonResponse;
use Gantry\Framework\Services\ErrorServiceProvider;
use RocketTheme\Toolbox\DI\Container;
use RocketTheme\Toolbox\Event\EventDispatcher;
use Whoops\Exception\ErrorException;
abstract class Router implements RouterInterface
{
/**
* @var Container
*/
protected $container;
protected $format;
protected $resource;
protected $method;
protected $path;
protected $params;
public function __construct(Container $container)
{
$this->container = $container;
}
public function dispatch()
{
$this->boot();
$this->load();
// Render the page or execute the task.
try {
$response = static::execute($this->resource,
$this->method, $this->path, $this->params, $this->format);
} catch (ErrorException $e) {
throw $e;
} catch (\Exception $e) {
// Handle errors.
if ($this->container->debug()) {
throw $e;
}
$response = $this->getErrorResponse($e, $this->format ==
'json');
}
return $this->send($response);
}
public function execute($resource, $method = 'GET', $path,
$params = [], $format = 'html')
{
$class = '\\Gantry\\Admin\\Controller\\' .
ucfirst($format) . '\\' . strtr(ucwords(strtr($resource,
'/', ' ')), ' ', '\\');
// Protect against CSRF Attacks.
if (!in_array($method, ['GET', 'HEAD'], true)
&& !$this->checkSecurityToken()) {
throw new \RuntimeException('Invalid security token;
please reload the page and try again.', 403);
}
if (!class_exists($class)) {
if ($format === 'json') {
// Special case: All HTML requests can be returned also as
JSON.
$response = $this->execute($resource, $method, $path,
$params, 'html');
return $response instanceof JsonResponse ? $response : new
JsonResponse($response);
}
throw new \RuntimeException('Page Not Found', 404);
}
/** @var BaseController $controller */
$controller = new $class($this->container);
// Execute action.
$response = $controller->execute($method, $path, $params);
if (!$response instanceof Response) {
$response = new HtmlResponse($response);
}
return $response;
}
/**
* @return $this
*/
abstract protected function boot();
abstract protected function checkSecurityToken();
/**
* @return $this
*/
public function load()
{
static $loaded = false;
if ($loaded) {
return $this;
}
$loaded = true;
if (isset($this->container['theme.path']) &&
file_exists($this->container['theme.path'] .
'/includes/gantry.php')) {
include $this->container['theme.path'] .
'/includes/gantry.php';
}
if (isset($this->container['theme'])) {
// Initialize current theme if it is set.
$this->container['theme'];
} else {
// Otherwise initialize streams and error handler manually.
$this->container['streams']->register();
$this->container->register(new ErrorServiceProvider);
}
$this->container['admin.theme'] = function () {
return new Theme(GANTRYADMIN_PATH);
};
// Add event listener.
if (class_exists('Gantry\\Admin\\EventListener')) {
$listener = new EventListener;
/** @var EventDispatcher $events */
$events = $this->container['events'];
$events->addSubscriber($listener);
}
// Boot the service.
$this->container['admin.theme'];
return $this;
}
protected function getErrorResponse(\Exception $e, $json = false)
{
$response = new HtmlResponse;
$response->setStatusCode($e->getCode());
$params = [
'ajax' => $json,
'title' => $response->getStatus(),
'error' => $e,
];
$response->setContent($this->container['admin.theme']->render('@gantry-admin/error.html.twig',
$params));
if ($json) {
return new JsonResponse([$e, $response]);
}
return $response;
}
protected function send(Response $response) {
// Output HTTP header.
header("HTTP/1.1 {$response->getStatus()}", true,
$response->getStatusCode());
header("Content-Type: {$response->mimeType};
charset={$response->charset}");
foreach ($response->getHeaders() as $key => $values) {
foreach ($values as $value) {
header("{$key}: {$value}");
}
}
echo $response;
return true;
}
}
PK���[�M�6��$Component/Router/RouterInterface.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Router;
interface RouterInterface
{
public function dispatch();
}
PK���[X}�q&q&$Component/Stylesheet/CssCompiler.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Stylesheet;
use Gantry\Component\Config\Config;
use Gantry\Component\Gantry\GantryTrait;
use Gantry\Framework\Gantry;
use Leafo\ScssPhp\Colors;
use RocketTheme\Toolbox\File\PhpFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
abstract class CssCompiler implements CssCompilerInterface
{
use GantryTrait;
protected $type;
protected $name;
protected $debug = false;
protected $warnings = [];
/**
* @var array
*/
protected $fonts;
/**
* @var array
*/
protected $variables;
/**
* @var string
*/
protected $target = 'gantry-theme://css-compiled';
/**
* @var string
*/
protected $configuration = 'default';
/**
* @var array
*/
protected $paths;
/**
* @var array
*/
protected $files;
/**
* @var mixed
*/
protected $compiler;
/**
* @var bool
*/
protected $production;
public function __construct()
{
$gantry = static::gantry();
/** @var Config $global */
$global = $gantry['global'];
// In production mode we do not need to do any other checks.
$this->production = (bool)
$global->get('production');
}
public function getWarnings()
{
return $this->warnings;
}
/**
* @return string
*/
public function getTarget()
{
return $this->target;
}
/**
* @param string $target
* @return $this
*/
public function setTarget($target = null)
{
if ($target !== null) {
$this->target = (string) $target;
}
return $this;
}
/**
* @param string $configuration
* @return $this
*/
public function setConfiguration($configuration = null)
{
if ($configuration !== null) {
$this->configuration = $configuration;
}
return $this;
}
/**
* @param array $fonts
* @return $this
*/
public function setFonts(array $fonts = null)
{
if ($fonts !== null) {
// Normalize font data.
$list = [];
foreach ($fonts as $family => $data) {
$family = strtolower($family);
if (is_array($data)) {
// font: [400: url1, 500: url2, 700: url3]
$list[$family] = $data;
} else {
// font: url
$list[$family] = [400 => (string) $data];
}
}
$this->compiler->setFonts($list);
}
return $this;
}
/**
* @param array $paths
* @return $this
*/
public function setPaths(array $paths = null)
{
if ($paths !== null) {
$this->paths = $paths;
}
return $this;
}
/**
* @param array $files
* @return $this
*/
public function setFiles(array $files = null)
{
if ($files !== null) {
$this->files = $files;
}
return $this;
}
/**
* @param string $name
* @return string
*/
public function getCssUrl($name)
{
$out = $name . ($this->configuration !== 'default' ?
'_'. $this->configuration : '');
return "{$this->target}/{$out}.css";
}
/**
* @return $this
*/
public function compileAll()
{
foreach ($this->files as $file) {
$this->compileFile($file);
}
return $this;
}
public function needsCompile($in, $variables)
{
$gantry = static::gantry();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$out = $this->getCssUrl($in);
$path = $locator->findResource($out);
// Check if CSS file exists at all.
if (!$path) {
$this->setVariables($variables());
return true;
}
if ($this->production) {
// Open the file to see if it contains development comment in
the beginning of the file.
$handle = fopen($path, 'rb');
$contents = fread($handle, 36);
fclose($handle);
if ($contents === '/* GANTRY5 DEVELOPMENT MODE
ENABLED.') {
$this->setVariables($variables());
return true;
}
// Compare checksum comment in the file.
if ($contents !== $this->checksum()) {
$this->setVariables($variables());
return true;
}
// In production mode we do not need to do any other checks.
return false;
}
$uri = basename($out);
$metaFile =
PhpFile::instance($locator->findResource("gantry-cache://theme/scss/{$uri}.php",
true, true));
// Check if meta file exists.
if (!$metaFile->exists()) {
$this->setVariables($variables());
return true;
}
$content = $metaFile->content();
$metaFile->free();
// Check if filename in meta file matches.
if (empty($content['file']) || $content['file']
!== $out) {
$this->setVariables($variables());
return true;
}
// Check if meta timestamp matches to CSS file.
if (filemtime($path) !== $content['timestamp']) {
$this->setVariables($variables());
return true;
}
$this->setVariables($variables());
// Check if variables have been changed.
$oldVariables = isset($content['variables']) ?
$content['variables'] : [];
if ($oldVariables != $this->getVariables()) {
return true;
}
// Preload all CSS files to locator cache.
foreach ($this->paths as $path) {
$locator->fillCache($path);
}
// Check if any of the imported files have been changed.
$imports = isset($content['imports']) ?
$content['imports'] : [];
if (!$imports) {
return $this->findImport($in) !== null;
}
foreach ($imports as $resource => $timestamp) {
$import = $locator->isStream($resource) ?
$locator->findResource($resource) : realpath($resource);
if (!$import || filemtime($import) !== $timestamp) {
return true;
}
}
return false;
}
public function setVariables(array $variables)
{
$this->variables = array_filter($variables);
foreach($this->variables as &$value) {
// Check variable against colors and units.
/* Test regex against these:
* Should only match the ones marked as +
* - family=Aguafina+Script
* - #zzzzzz
* - #fff
* + #ffaaff
* + 33em
* + 0.5px
* - 50 rem
* - rgba(323,323,2323)
* + rgba(125,200,100,0.3)
* - rgb(120,12,12)
*/
if
(preg_match('/(^(#([a-fA-F0-9]{6})|(rgba\(\s*(0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])\s*,\s*(0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])\s*,\s*(0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])\s*,\s*((0.[0-9]+)|[01])\s*\)))|(\d+(\.\d+){0,1}(rem|em|ex|ch|vw|vh|vmin|vmax|%|px|cm|mm|in|pt|pc))$)/i',
$value)) {
continue;
}
// Check variable against predefined color names (we use Leafo
SCSS Color class to do that).
if (isset(Colors::$cssColors[strtolower($value)])) {
continue;
}
// All the unknown values need to be quoted.
$value = "'{$value}'";
}
return $this;
}
public function getVariables()
{
return $this->variables;
}
public function reset()
{
$this->compiler->reset();
return $this;
}
/**
* @param string $url
* @return null|string
*/
abstract public function findImport($url);
protected function checksum($len = 36)
{
static $checksum;
if (!$checksum) {
$checksum = md5(GANTRY5_VERSION . ' ' .
Gantry::instance()['theme']->version);
}
return '/*' . substr($checksum, 0, $len - 4) .
'*/';
}
protected function createMeta($out, $md5)
{
$gantry = Gantry::instance();
if ($this->production) {
return;
}
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$uri = basename($out);
$metaFile =
PhpFile::instance($locator->findResource("gantry-cache://theme/scss/{$uri}.php",
true, true));
$data = [
'file' => $out,
'timestamp' =>
filemtime($locator->findResource($out)),
'md5' => $md5,
'variables' => $this->getVariables(),
'imports' =>
$this->compiler->getParsedFiles()
];
// Attempt to lock the file for writing.
try {
$metaFile->lock(false);
} catch (\Exception $e) {
// Another process has locked the file; we will check this in a
bit.
}
// If meta file wasn't already locked by another process, save
it.
if ($metaFile->locked() !== false) {
$metaFile->save($data);
$metaFile->unlock();
}
$metaFile->free();
}
}
PK���[�03��-Component/Stylesheet/CssCompilerInterface.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Stylesheet;
interface CssCompilerInterface
{
/**
* @return array
*/
public function getWarnings();
/**
* @return string
*/
public function getTarget();
/**
* @param string $target
* @return $this
*/
public function setTarget($target = null);
/**
* @param string $configuration
* @return $this
*/
public function setConfiguration($configuration = null);
/**
* @param array $paths
* @return $this
*/
public function setPaths(array $paths = null);
/**
* @param array $files
* @return $this
*/
public function setFiles(array $files = null);
/**
* @param array $fonts
* @return $this
*/
public function setFonts(array $fonts);
/**
* @param string $name
* @return string
*/
public function getCssUrl($name);
public function getVariables();
public function setVariables(array $variables);
public function registerFunction($name, callable $callback);
public function unregisterFunction($name);
public function needsCompile($in, $variables);
public function compileFile($in);
/**
* @return $this
*/
public function reset();
/**
* @return $this
*/
public function compileAll();
public function resetCache();
}
PK���[�d瑄,�,&Component/Stylesheet/Scss/Compiler.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Stylesheet\Scss;
use Gantry\Component\Filesystem\Folder;
use Gantry\Framework\Document;
use Gantry\Framework\Gantry;
use Leafo\ScssPhp\Compiler as BaseCompiler;
use Leafo\ScssPhp\Formatter\OutputBlock;
use Leafo\ScssPhp\Parser;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Compiler extends BaseCompiler
{
protected $basePath;
protected $fonts;
protected $usedFonts;
protected $streamNames;
protected $parsedFiles = [];
public function __construct()
{
parent::__construct();
$this->registerFunction('get-font-url', [$this,
'userGetFontUrl']);
$this->registerFunction('get-font-family', [$this,
'userGetFontFamily']);
$this->registerFunction('get-local-fonts', [$this,
'userGetLocalFonts']);
$this->registerFunction('get-local-font-weights',
[$this, 'userGetLocalFontWeights']);
$this->registerFunction('get-local-font-url', [$this,
'userGetLocalFontUrl']);
}
/**
* @param $basePath
*/
public function setBasePath($basePath)
{
/** @var Document $document */
$document = Gantry::instance()['document'];
$this->basePath = rtrim($document->rootUri(), '/')
. '/' . Folder::getRelativePath($basePath);
}
/**
* @param array $fonts
*/
public function setFonts(array $fonts)
{
$this->fonts = $fonts;
}
/**
* @param $args
* @return mixed
*/
public function compileArgs($args)
{
foreach ($args as &$arg) {
$arg = $this->compileValue($arg);
}
return $args;
}
/**
* Get variable
*
* @api
*
* @param string $name
* @param boolean $shouldThrow
* @param BaseCompiler\Environment $env
* @param bool $unreduced
*
* @return mixed
*/
public function get($name, $shouldThrow = true,
BaseCompiler\Environment $env = null, $unreduced = false)
{
try {
return parent::get($name, $shouldThrow, $env, $unreduced);
} catch (\Exception $e) {
echo $e->getMessage() . "\n";
return ['string', '', ['']];
}
}
/**
* @param array $args
* @return string
* @throws \Leafo\ScssPhp\Exception\CompilerException
*/
public function libUrl(array $args)
{
// Function has a single parameter.
$parsed = reset($args);
if (!$parsed) {
$this->throwError('url() is missing parameter');
}
// Compile parsed value to string.
$url = trim($this->compileValue($parsed),
'\'"');
// Handle ../ inside CSS files (points to current theme).
if (strpos($url, '../') === 0 && strpos($url,
'../', 3) === false) {
$url = 'gantry-theme://' . substr($url, 3);
}
// Generate URL, failed streams will be transformed to 404 URLs.
$url = Gantry::instance()['document']->url($url, null,
null, false);
// Changes absolute URIs to relative to make the path to work even
if the site gets moved.
if ($url && $url[0] === '/' &&
$this->basePath) {
$url = Folder::getRelativePathDotDot($url, $this->basePath);
}
// Make sure that all the URLs inside CSS are https compatible by
replacing http:// protocol with //.
if (strpos($url, 'http://') === 0) {
$url = str_replace('http://', '//', $url);
}
// Return valid CSS.
return "url('{$url}')";
}
/**
* get-font-url($my-font-variable);
*
* @param array $args
* @return string
*/
public function userGetFontUrl($args)
{
$value = trim($this->compileValue(reset($args)),
'\'"');
// It's a google font
if (0 === strpos($value, 'family=')) {
$fonts = $this->decodeFonts($value);
$font = reset($fonts);
// Only return url once per font.
if ($font && !isset($this->usedFonts[$font])) {
$this->usedFonts[$font] = true;
return
"url('//fonts.googleapis.com/css?{$value}')";
}
}
return false;
}
/**
* font-family: get-font-family($my-font-variable);
*
* @param array $args
* @return string
*/
public function userGetFontFamily($args)
{
$value = trim($this->compileValue(reset($args)),
'\'"');
return $this->encodeFonts($this->decodeFonts($value));
}
/**
* get-local-fonts($my-font-variable, $my-font-variable2, ...);
*
* @param array $args
* @return array
*/
public function userGetLocalFonts($args)
{
$args = $this->compileArgs($args);
$fonts = [];
foreach ($args as $value) {
// It's a local font, we need to load any of the mapped
fonts from the theme
$fonts = array_merge($fonts, $this->decodeFonts($value,
true));
}
$fonts = $this->getLocalFonts($fonts);
// Create a basic list of strings so that SCSS parser can parse the
list.
$list = [];
foreach ($fonts as $font => $data) {
$list[] = ['string', '"', [$font]];
}
return ['list', ',', $list];
}
/**
* get-local-font-weights(roboto);
*
* @param array $args
* @return array
*/
public function userGetLocalFontWeights($args)
{
$name = trim($this->compileValue(reset($args)),
'\'"');
$weights = isset($this->fonts[$name]) ?
array_keys($this->fonts[$name]) : [];
// Create a list of numbers so that SCSS parser can parse the list.
$list = [];
foreach ($weights as $weight) {
$list[] = ['string', '', [(int) $weight]];
}
return ['list', ',', $list];
}
/**
* get-local-font-url(roboto, 400);
*
* @param array $args
* @return string
*/
public function userGetLocalFontUrl($args)
{
$args = $this->compileArgs($args);
$name = isset($args[0]) ? trim($args[0], '\'"')
: '';
$weight = isset($args[1]) ? $args[1] : 400;
// Only return url once per font.
$weightName = $name . '-' . $weight;
if (isset($this->fonts[$name][$weight]) &&
!isset($this->usedFonts[$weightName])) {
$this->usedFonts[$weightName] = true;
return $this->fonts[$name][$weight];
}
return false;
}
/**
* Get local font data.
*
* @param array $fonts
* @return array
*/
protected function getLocalFonts(array $fonts)
{
$list = [];
foreach ($fonts as $family) {
$family = strtolower($family);
if (isset($this->fonts[$family])) {
$list[$family] = $this->fonts[$family];
}
}
return $list;
}
/**
* Convert array of fonts into a CSS parameter string.
*
* @param array $fonts
* @return string
*/
protected function encodeFonts(array $fonts)
{
array_walk($fonts, function(&$val) {
// Check if font family is one of the 4 default ones, otherwise
add quotes.
if (!\in_array($val, ['cursive', 'serif',
'sans-serif', 'monospace'], true)) {
$val = '"' . $val . '"';
}
});
return implode(', ', $fonts);
}
/**
* Convert string into array of fonts.
*
* @param string $string
* @param bool $localOnly
* @return array
*/
protected function decodeFonts($string, $localOnly = false)
{
if (0 === strpos($string, 'family=')) {
if ($localOnly) {
// Do not return external fonts.
return [];
}
// Matches google font family name
preg_match('/^family=([^&:]+).*$/ui', $string,
$matches);
return [urldecode($matches[1])];
}
// Filter list of fonts and quote them.
$list = (array) explode(',', $string);
array_walk($list, function(&$val) {
$val = trim($val, "'\" \t\n\r\0\x0B");
});
array_filter($list);
return $list;
}
public function reset()
{
$this->usedFonts = [];
return $this;
}
/**
* Instantiate parser
*
* @param string $path
*
* @return \Leafo\ScssPhp\Parser
*/
protected function parserFactory($path)
{
$parser = new Parser($path, count($this->sourceNames),
$this->encoding);
/** @var UniformResourceLocator $locator */
$locator = Gantry::instance()['locator'];
$this->sourceNames[] = $locator->isStream($path) ?
$locator->findResource($path, false) : $path;
$this->streamNames[] = $path;
$this->addParsedFile($path);
return $parser;
}
/**
* Adds to list of parsed files
*
* @api
*
* @param string $path
*/
public function addParsedFile($path)
{
if ($path && file_exists($path)) {
$this->parsedFiles[$path] = filemtime($path);
}
}
/**
* Returns list of parsed files
*
* @api
*
* @return array
*/
public function getParsedFiles()
{
return $this->parsedFiles;
}
/**
* Clean parset files.
*
* @api
*/
public function cleanParsedFiles()
{
$this->parsedFiles = [];
}
/**
* Handle import loop
*
* @param string $name
*
* @throws \Exception
*/
protected function handleImportLoop($name)
{
for ($env = $this->env; $env; $env = $env->parent) {
$file = $this->streamNames[$env->block->sourceIndex];
if (realpath($file) === $name) {
$this->throwError('An @import loop has been found:
%s imports %s', $file, basename($file));
break;
}
}
}
/**
* Override function to improve the logic.
*
* @param string $path
* @param OutputBlock $out
*
* @throws \Exception
*/
protected function importFile($path, OutputBlock $out)
{
$this->addParsedFile($path);
/** @var UniformResourceLocator $locator */
$locator = Gantry::instance()['locator'];
// see if tree is cached
$realPath = $locator($path);
if (isset($this->importCache[$realPath])) {
$this->handleImportLoop($realPath);
$tree = $this->importCache[$realPath];
} else {
$code = file_get_contents($realPath);
$parser = $this->parserFactory($path);
$tree = $parser->parse($code);
$this->importCache[$realPath] = $tree;
}
$dirname = dirname($path);
array_unshift($this->importPaths, $dirname);
$this->compileChildrenNoReturn($tree->children, $out);
array_shift($this->importPaths);
}
}
PK���[�}��%Component/Stylesheet/ScssCompiler.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Stylesheet;
use Gantry\Component\Stylesheet\Scss\Compiler;
use Gantry\Framework\Document;
use Gantry\Framework\Gantry;
use Leafo\ScssPhp\Exception\CompilerException;
use RocketTheme\Toolbox\File\File;
use RocketTheme\Toolbox\File\JsonFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class ScssCompiler extends CssCompiler
{
/**
* @var string
*/
public $type = 'scss';
/**
* @var string
*/
public $name = 'SCSS';
/**
* @var Compiler
*/
protected $compiler;
/**
* Constructor.
*/
public function __construct()
{
parent::__construct();
$this->compiler = new Compiler();
if ($this->production) {
$this->compiler->setFormatter('Leafo\ScssPhp\Formatter\Crunched');
} else {
$this->compiler->setFormatter('Leafo\ScssPhp\Formatter\Expanded');
// Work around bugs in SCSS compiler.
// TODO: Pass our own SourceMapGenerator instance instead.
$this->compiler->setSourceMap(Compiler::SOURCE_MAP_INLINE);
$this->compiler->setSourceMapOptions([
'sourceMapBasepath' => '/',
'sourceRoot' => '/',
]);
$this->compiler->setLineNumberStyle(Compiler::LINE_COMMENTS);
}
}
public function compile($in)
{
return $this->compiler->compile($in);
}
public function resetCache()
{
}
/**
* @param string $in Filename without path or extension.
* @return bool True if the output file was saved.
* @throws \RuntimeException
*/
public function compileFile($in)
{
// Buy some extra time as compilation may take a lot of time in
shared environments.
@set_time_limit(30);
@set_time_limit(60);
@set_time_limit(90);
@set_time_limit(120);
ob_start();
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$out = $this->getCssUrl($in);
$path = $locator->findResource($out, true, true);
$file = File::instance($path);
// Attempt to lock the file for writing.
try {
$file->lock(false);
} catch (\Exception $e) {
// Another process has locked the file; we will check this in a
bit.
}
if ($file->locked() === false) {
// File was already locked by another process, lets avoid
compiling the same file twice.
return false;
}
// Set the lookup paths.
$this->compiler->setBasePath($path);
$this->compiler->setImportPaths([[$this,
'findImport']]);
// Run the compiler.
$this->compiler->setVariables($this->getVariables());
$scss = '@import "' . $in . '.scss"';
try {
$css = $this->compiler->compile($scss);
} catch (CompilerException $e) {
throw new \RuntimeException("CSS Compilation on file
'{$in}.scss' failed on error: {$e->getMessage()}", 500,
$e);
}
if (strpos($css, $scss) === 0) {
$css = '/* ' . $scss . ' */';
}
// Extract map from css and save it as separate file.
if ($pos = strrpos($css, '/*# sourceMappingURL=')) {
$map = json_decode(urldecode(substr($css, $pos + 43, -3)),
true);
/** @var Document $document */
$document = $gantry['document'];
foreach ($map['sources'] as &$source) {
$source = $document->url($source, null, -1);
}
unset($source);
$mapFile = JsonFile::instance($path . '.map');
$mapFile->save($map);
$mapFile->free();
$css = substr($css, 0, $pos) . '/*#
sourceMappingURL=' . basename($out) . '.map */';
}
$warnings = trim(ob_get_clean());
if ($warnings) {
$this->warnings[$in] = explode("\n", $warnings);
}
if (!$this->production) {
$warning = <<<WARN
/* GANTRY5 DEVELOPMENT MODE ENABLED.
WARNING: This file is automatically generated by Gantry5. Any
modifications to this file will be lost!
For more information on modifying CSS, please read:
http://docs.gantry.org/gantry5/configure/styles
http://docs.gantry.org/gantry5/tutorials/adding-a-custom-style-sheet
*/
WARN;
$css = $warning . "\n\n" . $css;
} else {
$css = "{$this->checksum()}\n{$css}";
}
$file->save($css);
$file->unlock();
$file->free();
$this->createMeta($out, md5($css));
$this->compiler->cleanParsedFiles();
return true;
}
/**
* @param string $name Name of function to register to the
compiler.
* @param callable $callback Function to run when called by the
compiler.
* @return $this
*/
public function registerFunction($name, callable $callback)
{
$this->compiler->registerFunction($name, $callback);
return $this;
}
/**
* @param string $name Name of function to unregister.
* @return $this
*/
public function unregisterFunction($name)
{
$this->compiler->unregisterFunction($name);
return $this;
}
/**
* @param string $url
* @return null|string
* @internal
*/
public function findImport($url)
{
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
// Ignore vanilla css and external requests.
if (preg_match('/\.css$|^https?:\/\//', $url)) {
return null;
}
// Try both normal and the _partial filename.
$files = array($url, preg_replace('/[^\/]+$/',
'_\0', $url));
foreach ($this->paths as $base) {
foreach ($files as $file) {
if (!preg_match('|\.scss$|', $file)) {
$file .= '.scss';
}
if ($locator->findResource($base . '/' .
$file)) {
return $base . '/' . $file;
}
}
}
return null;
}
}
PK���[�i}}Component/System/Messages.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Component\System;
class Messages
{
protected $messages = [];
public function add($message, $type = 'warning')
{
$this->messages[] = ['type' => $type,
'message' => $message];
return $this;
}
public function get()
{
return $this->messages;
}
public function clean()
{
$this->messages = [];
return $this;
}
}
PK���[�Y�22!Component/Theme/AbstractTheme.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Theme;
use Gantry\Component\Config\Config;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Component\Filesystem\Folder;
use Gantry\Component\Gantry\GantryTrait;
use Gantry\Component\Twig\TwigCacheFilesystem;
use Gantry\Component\Twig\TwigExtension;
use Gantry\Framework\Platform;
use Gantry\Framework\Services\ErrorServiceProvider;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* Class AbstractTheme
* @package Gantry\Component
*
* @property string $path
* @property string $layout
*/
abstract class AbstractTheme
{
use GantryTrait;
/**
* @var string
*/
public $name;
/**
* @var string
*/
public $path;
/**
* @var \Twig_Environment
*/
protected $renderer;
/**
* Construct theme object.
*
* @param string $path
* @param string $name
*/
public function __construct($path, $name = null)
{
if (!is_dir($path)) {
throw new \LogicException('Theme not found!');
}
$this->name = $name ? $name : basename($path);
$this->path = $path;
$this->init();
}
/**
* Get context for render().
*
* @param array $context
* @return array
*/
public function getContext(array $context)
{
$context['theme'] = $this;
return $context;
}
/**
* Define twig environment.
*
* @param \Twig_Environment $twig
* @param \Twig_LoaderInterface $loader
* @return \Twig_Environment
*/
public function extendTwig(\Twig_Environment $twig,
\Twig_LoaderInterface $loader = null)
{
if
($twig->hasExtension('Gantry\Component\Twig\TwigExtension')) {
return $twig;
}
if (!$loader) {
$loader = $twig->getLoader();
}
$this->setTwigLoaderPaths($loader);
$twig->addExtension(new TwigExtension);
if (method_exists($this, 'toGrid')) {
$filter = new \Twig_SimpleFilter('toGrid', [$this,
'toGrid']);
$twig->addFilter($filter);
}
return $twig;
}
/**
* Return renderer.
*
* @return \Twig_Environment
*/
public function renderer()
{
if (!$this->renderer) {
$gantry = static::gantry();
/** @var Config $global */
$global = $gantry['global'];
$cachePath = $global->get('compile_twig', 1) ?
$this->getCachePath('twig') : null;
$cache = $cachePath ? new TwigCacheFilesystem($cachePath,
\Twig_Cache_Filesystem::FORCE_BYTECODE_INVALIDATION) : null;
$debug = $gantry->debug();
$production = (bool) $global->get('production',
1);
$loader = new \Twig_Loader_Filesystem();
$params = [
'cache' => $cache,
'debug' => $debug,
'auto_reload' => !$production,
'autoescape' => 'html'
];
$twig = new \Twig_Environment($loader, $params);
$this->setTwigLoaderPaths($loader);
if ($debug) {
$twig->addExtension(new \Twig_Extension_Debug());
}
$this->renderer = $this->extendTwig($twig, $loader);
}
return $this->renderer;
}
/**
* Render a template file by using given context.
*
* @param string $file
* @param array $context
* @return string
*/
public function render($file, array $context = [])
{
// Include Gantry specific things to the context.
$context = $this->getContext($context);
return $this->renderer()->render($file, $context);
}
/**
* Compile and render twig string.
*
* @param string $string
* @param array $context
* @return string
*/
public function compile($string, array $context = [])
{
$renderer = $this->renderer();
$template = $renderer->createTemplate($string);
// Include Gantry specific things to the context.
$context = $this->getContext($context);
return $template->render($context);
}
/**
* Initialize theme.
*/
protected function init()
{
$gantry = static::gantry();
$gantry['streams']->register();
// Only add error service if development or debug mode has been
enabled or user is admin.
if (!$gantry['global']->get('production', 0)
|| $gantry->debug() || $gantry->admin()) {
$gantry->register(new ErrorServiceProvider);
}
// Initialize theme cache stream.
$cachePath = $this->getCachePath();
Folder::create($cachePath);
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$locator->addPath('gantry-cache', 'theme',
[$cachePath], true, true);
CompiledYamlFile::$defaultCachePath =
$locator->findResource('gantry-cache://theme/compiled/yaml',
true, true);
CompiledYamlFile::$defaultCaching =
$gantry['global']->get('compile_yaml', 1);
}
/**
* Set twig lookup paths to the loader.
*
* @param \Twig_LoaderInterface $loader
* @return \Twig_Loader_Filesystem|null
* @internal
*/
protected function setTwigLoaderPaths(\Twig_LoaderInterface $loader)
{
if ($loader instanceof \Twig_Loader_Chain) {
$new = new \Twig_Loader_Filesystem();
$loader->addLoader($new);
$loader = $new;
} elseif (!($loader instanceof \Twig_Loader_Filesystem)) {
return null;
}
$gantry = static::gantry();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$loader->setPaths($locator->findResources('gantry-engine://templates'),
'nucleus');
$loader->setPaths($locator->findResources('gantry-particles://'),
'particles');
return $loader;
}
/**
* Get path to Twig cache.
*
* @param string $path
* @return string
*/
protected function getCachePath($path = '')
{
$gantry = static::gantry();
/** @var Platform $patform */
$patform = $gantry['platform'];
// Initialize theme cache stream.
return $patform->getCachePath() . '/' . $this->name
. ($path ? '/' . $path : '');
}
/**
* @deprecated 5.0.2
*/
public function debug()
{
return static::gantry()->debug();
}
/**
* @deprecated 5.1.5
*/
public function add_to_context(array $context)
{
return $this->getContext($context);
}
/**
* @deprecated 5.1.5
*/
public function add_to_twig(\Twig_Environment $twig,
\Twig_LoaderInterface $loader = null)
{
return $this->extendTwig($twig, $loader);
}
}
PK���[�����
Component/Theme/ThemeDetails.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Theme;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Component\Filesystem\Streams;
use Gantry\Framework\Gantry;
use RocketTheme\Toolbox\ArrayTraits\Export;
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* Class ThemeDetails
* @package Gantry\Component\Theme
*/
class ThemeDetails implements \ArrayAccess
{
use NestedArrayAccessWithGetters, Export;
protected $items;
protected $parent;
/**
* Create new theme details.
*
* @param string $theme
*/
public function __construct($theme)
{
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$filename =
$locator->findResource("gantry-themes://{$theme}/gantry/theme.yaml");
if (!$filename) {
throw new \RuntimeException(sprintf('Theme %s not
found', $theme), 404);
}
$cache =
$locator->findResource("gantry-cache://{$theme}/compiled/yaml",
true, true);
$file = CompiledYamlFile::instance($filename);
$this->items = $file->setCachePath($cache)->content();
$file->free();
$this->offsetSet('name', $theme);
$parent = (string)
$this->get('configuration.theme.parent', $theme);
$parent = $parent != $theme ? $parent : null;
$this->offsetSet('parent', $parent);
}
/**
* @return string
*/
public function addStreams()
{
$gantry = Gantry::instance();
// Initialize theme stream.
$streamName =
$this->addStream($this->offsetGet('name'),
$this->getPaths());
// Initialize parent theme streams.
$loaded = [$this->offsetGet('name')];
$details = $this;
while ($details = $details->parent()) {
if (in_array($details->name, $loaded)) {
break;
}
$this->addStream($details->name,
$details->getPaths(false));
$loaded[] = $details->name;
}
/** @var Streams $streams */
$streams = $gantry['streams'];
$streams->register();
return $streamName;
}
/**
* Get parent theme details if theme has a parent.
*
* @return ThemeDetails|null
* @throws \RuntimeException
*/
public function parent()
{
$parent = $this->offsetGet('parent');
if (!$this->parent && $parent) {
try {
$this->parent = new ThemeDetails($parent);
} catch (\RuntimeException $e) {
throw new \RuntimeException(sprintf('Parent theme %s
not found', $parent), 404);
}
}
return $this->parent;
}
/**
* Get all possible paths to the theme.
*
* @return array
*/
public function getPaths($overrides = true)
{
$paths = array_merge(
$overrides ? (array)
$this->get('configuration.theme.overrides',
'gantry-theme://custom') : [],
['gantry-theme://'],
(array) $this->get('configuration.theme.base',
'gantry-theme://common')
);
$parent = $this->offsetGet('parent');
if ($parent) {
// Stream needs to be valid URL.
$streamName = 'gantry-themes-' .
preg_replace('|[^a-z\d+.-]|ui', '-', $parent);
$paths[] = "{$streamName}://";
}
return $this->parsePaths($paths);
}
/**
* Convert theme path into stream URI.
*
* @param string $path
* @return string
*/
public function getUrl($path)
{
$uri = (string) $this->offsetGet($path);
if (strpos($uri, 'gantry-theme://') === 0) {
list (, $uri) = explode('://', $uri, 2);
}
if (!strpos($uri, '://')) {
$name = $this->offsetGet('name');
// Stream needs to be valid URL.
$streamName = 'gantry-themes-' .
preg_replace('|[^a-z\d+.-]|ui', '-', $name);
$uri = "{$streamName}://{$uri}";
}
return $uri;
}
/**
* Turn list of theme paths to be universal, so they can be used
outside of the theme.
*
* @param array $items
* @return array
*/
public function parsePaths(array $items)
{
foreach ($items as &$item) {
$item = $this->parsePath($item);
}
return $items;
}
/**
* Convert theme paths to be universal, so they can be used outside of
the theme.
*
* @param string $path
* @return string
*/
public function parsePath($path)
{
if (strpos($path, 'gantry-theme://') === 0) {
list (, $path) = explode('://', $path, 2);
}
if (!strpos($path, '://')) {
$name = $this->offsetGet('name');
$path = "gantry-themes://{$name}/{$path}";
}
return $path;
}
/**
* @return string|null
* @deprecated 5.1.5
*/
public function getParent()
{
return $this->offsetGet('parent');
}
/**
* @param string $name
* @param array $paths
* @return string|null
*/
protected function addStream($name, $paths)
{
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
/** @var Streams $streams */
$streams = $gantry['streams'];
// Add theme stream.
$streamName = 'gantry-themes-' .
preg_replace('|[^a-z\d+.-]|ui', '-', $name);
if (!$locator->schemeExists($streamName)) {
$streams->add([$streamName => ['paths' =>
$paths]]);
}
return $streamName;
}
}
PK���[1���%�%"Component/Theme/ThemeInstaller.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Theme;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Component\Filesystem\Folder;
use Gantry\Component\Layout\Layout;
use Gantry\Framework\Gantry;
use Gantry\Framework\Platform;
use Gantry\Framework\Services\ErrorServiceProvider;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
abstract class ThemeInstaller
{
/**
* Set to true if in Gantry.
*
* @var bool
*/
public $initialized = false;
public $actions = [];
protected $name;
protected $outlines;
protected $script;
public function __construct($extension = null)
{
if ($extension) {
$this->name = $extension;
}
}
abstract public function getPath();
/**
* Get list of available outlines.
*
* @param array $filter
* @return array
*/
public function getOutlines(array $filter = null)
{
if (!isset($this->outlines)) {
$this->outlines = [];
$path = $this->getPath();
// If no outlines are given, try loading outlines.yaml file.
$file = YamlFile::instance($path .
'/install/outlines.yaml');
if ($file->exists()) {
// Load the list from the yaml file.
$this->outlines = (array) $file->content();
$file->free();
} elseif (is_dir($path . '/install/outlines')) {
// Build the list from the install folder.
// recurse = false, full=true
$folders = Folder::all($path .
'/install/outlines', ['folders' => true,
'recursive' => false]);
foreach ($folders as $folder) {
$this->outlines[basename($folder)] = [];
}
}
// Always include system outlines.
$this->outlines += ['default' => [],
'_body_only' => [], '_error' => [],
'_offline' => []];
}
return is_array($filter) ? array_intersect_key($this->outlines,
array_flip($filter)) : $this->outlines;
}
public function getOutline($name)
{
$list = $this->getOutlines([$name]);
return reset($list);
}
public function installDefaults()
{
$installerScript = $this->getInstallerScript();
if ($installerScript && method_exists($installerScript,
'installDefaults')) {
$installerScript->installDefaults($this);
} else {
$this->createDefaults();
}
}
public function installSampleData()
{
$installerScript = $this->getInstallerScript();
if ($installerScript && method_exists($installerScript,
'installSampleData')) {
$installerScript->installSampleData($this);
} else {
$this->createSampleData();
}
}
public function createDefaults()
{
$this->createOutlines();
}
public function createSampleData()
{
}
public function render($template, $context = [])
{
try {
$loader = new \Twig_Loader_Filesystem();
$loader->setPaths([$this->getPath() .
'/install/templates']);
$params = [
'cache' => null,
'debug' => false,
'autoescape' => 'html'
];
$twig = new \Twig_Environment($loader, $params);
$name = $this->name;
$context += [
'name' => $this->translate($name),
'actions' => $this->actions
];
return $twig->render($template, $context);
} catch (\Exception $e) {
return '';
}
}
/**
* Set available outlines.
*
* @param array $outlines If parameter isn't provided, outlines
list get reloaded from the disk.
* @return $this
*/
public function setOutlines(array $outlines = null)
{
$this->outlines = $outlines;
return $this;
}
/**
* @param array $filter
*/
public function createOutlines(array $filter = null)
{
$outlines = $this->getOutlines($filter);
foreach ($outlines as $folder => $params) {
$this->createOutline($folder, $params);
}
}
/**
* @param string $folder
* @param array $params
* @return string|bool
*/
public function createOutline($folder, array $params = [])
{
if (!$folder) {
throw new \RuntimeException('Cannot create outline without
folder name');
}
$this->initialize();
$created = false;
$params += [
'preset' => null,
'title' => null
];
$title = $params['title'] ?: ucwords(trim(strtr($folder,
['_' => ' '])));
$preset = $params['preset'] ?: 'default';
// Copy configuration for the new layout.
if (($this->copyCustom($folder, $folder) || $created)) {
// Update layout and save it.
$layout = Layout::load($folder, $preset);
$layout->save()->saveIndex();
if ($created) {
$this->actions[] = ['action' =>
'outline_created', 'text' =>
$this->translate('GANTRY5_INSTALLER_ACTION_OUTLINE_CREATED',
$title)];
} else {
$this->actions[] = ['action' =>
'outline_updated', 'text' =>
$this->translate('GANTRY5_INSTALLER_ACTION_OUTLINE_UPDATED',
$title)];
}
}
return $folder;
}
public function initialize()
{
if ($this->initialized) {
return;
}
$name = $this->name;
$path = $this->getPath();
// Remove compiled CSS files if they exist.
$cssPath = $path . '/custom/css-compiled';
if (is_dir($cssPath)) {
Folder::delete($cssPath);
} elseif (is_file($cssPath)) {
@unlink($cssPath);
}
// Remove wrongly named file if it exists.
$md5path = $path . '/MD5SUM';
if (is_file($md5path)) {
@unlink($md5path);
}
// Restart Gantry and initialize it.
$gantry = Gantry::restart();
$gantry['theme.name'] = $name;
$gantry['streams']->register();
// Only add error service if debug mode has been enabled.
if ($gantry->debug()) {
$gantry->register(new ErrorServiceProvider);
}
/** @var Platform $patform */
$patform = $gantry['platform'];
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
// Initialize theme stream.
$details = new ThemeDetails($name);
$locator->addPath('gantry-theme', '',
$details->getPaths(), false, true);
// Initialize theme cache stream and clear theme cache.
$cachePath = $patform->getCachePath() . '/' . $name;
if (is_dir($cachePath)) {
Folder::delete($cachePath);
}
Folder::create($cachePath);
$locator->addPath('gantry-cache', 'theme',
[$cachePath], true, true);
CompiledYamlFile::$defaultCachePath =
$locator->findResource('gantry-cache://theme/compiled/yaml',
true, true);
CompiledYamlFile::$defaultCaching =
$gantry['global']->get('compile_yaml', 1);
$this->initialized = true;
}
public function finalize()
{
// Copy standard outlines if they haven't been copied already.
$this->copyCustom('default', 'default');
$this->copyCustom('_body_only',
'_body_only');
$this->copyCustom('_error', '_error');
$this->copyCustom('_offline', '_offline');
$this->initialize();
}
/**
* @param string $layout
* @param string $id
* @return bool True if files were copied over.
*/
protected function copyCustom($layout, $id)
{
$path = $this->getPath();
// Only copy files if the target id doesn't exist.
$dst = $path . '/custom/config/' . $id;
if (!$layout || !$id || is_dir($dst)) {
return false;
}
// New location for G5.3.2+
$src = $path . '/install/outlines/' . $layout;
if (!is_dir($src)) {
// Old and deprecated location.
$src = $path . '/install/layouts/' . $layout;
}
try {
is_dir($src) ? Folder::copy($src, $dst) : Folder::create($dst);
} catch (\Exception $e) {
throw new \RuntimeException("Creating configuration for
outline '{$layout}' failed: {$e->getMessage()}", 500,
$e);
}
return true;
}
protected function translate($text)
{
$translator = Gantry::instance()['translator'];
$args = func_get_args();
return call_user_func_array([$translator, 'translate'],
$args);
}
protected function getInstallerScript()
{
if (!$this->script) {
$className = ucfirst($this->name) .
'InstallerScript';
if (!class_exists($className)) {
$path = "{$this->getPath()}/install.php";
if (is_file($path)) {
require_once $path;
}
}
if (class_exists($className)) {
$this->script = new $className;
}
}
return $this->script;
}
}
PK���[��IA��"Component/Theme/ThemeInterface.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Theme;
use Gantry\Component\Config\Config;
use Gantry\Component\Layout\Layout;
use Gantry\Component\Stylesheet\CssCompilerInterface;
/**
* Class ThemeTrait
* @package Gantry\Framework\Base
*
* @property string $path
* @property string $layout
*/
interface ThemeInterface
{
// AbstractTheme class
/**
* Get context for render().
*
* @param array $context
* @return array
*/
public function getContext(array $context);
/**
* Define twig environment.
*
* @param \Twig_Environment $twig
* @param \Twig_LoaderInterface $loader
* @return \Twig_Environment
*/
public function extendTwig(\Twig_Environment $twig,
\Twig_LoaderInterface $loader = null);
/**
* Returns renderer.
*
* @return \Twig_Environment
*/
public function renderer();
/**
* Render a template file.
*
* @param string $file
* @param array $context
* @return string
*/
public function render($file, array $context = array());
// ThemeTrait class
/**
* Update all CSS files in the theme.
*
* @param array $outlines
* @return array List of CSS warnings.
*/
public function updateCss(array $outlines = null);
/**
* Set current layout.
*
* @param string $name
* @param bool $force
* @return $this
*/
public function setLayout($name = null, $force = false);
/**
* Get current preset.
*
* @param bool $forced If true, return only forced preset or null.
* @return string|null $preset
*/
public function preset($forced = false);
/**
* Set preset to be used.
*
* @param string $name
* @return $this
*/
public function setPreset($name = null);
/**
* Return CSS compiler used in the theme.
*
* @return CssCompilerInterface
* @throws \RuntimeException
*/
public function compiler();
/**
* Returns URL to CSS file.
*
* If file does not exist, it will be created by using CSS compiler.
*
* @param string $name
* @return string
*/
public function css($name);
/**
* Return all CSS variables.
*
* @return array
*/
public function getCssVariables();
/**
* Returns style presets for the theme.
*
* @return Config
*/
public function presets();
/**
* Return name of the used layout preset.
*
* @return string
* @throws \RuntimeException
*/
public function type();
/**
* Load current layout and its configuration.
*
* @param string $name
* @return Layout
* @throws \LogicException
*/
public function loadLayout($name = null);
/**
* Check whether layout has content bock.
*
* @return bool
*/
public function hasContent();
/**
* Returns all non-empty segments from the layout.
*
* @return array
*/
public function segments();
/**
* Returns details of the theme.
*
* @return ThemeDetails
*/
public function details();
/**
* Returns configuration of the theme.
*
* @return array
*/
public function configuration();
/**
* Function to convert block sizes into CSS classes.
*
* @param $text
* @return string
*/
public function toGrid($text);
}
PK���[b����Z�ZComponent/Theme/ThemeTrait.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Theme;
use Gantry\Component\Config\Config;
use Gantry\Component\Content\Block\ContentBlock;
use Gantry\Component\Content\Block\HtmlBlock;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Component\Filesystem\Folder;
use Gantry\Component\Gantry\GantryTrait;
use Gantry\Component\Layout\Layout;
use Gantry\Component\Stylesheet\CssCompilerInterface;
use Gantry\Framework\Document;
use Gantry\Framework\Menu;
use Gantry\Framework\Services\ConfigServiceProvider;
use RocketTheme\Toolbox\File\PhpFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* Class ThemeTrait
* @package Gantry\Component
*
* @property string $path
* @property string $layout
*/
trait ThemeTrait
{
use GantryTrait;
protected $layoutObject;
protected $atoms;
protected $segments;
protected $preset;
protected $cssCache;
/**
* @var CssCompilerInterface
*/
protected $compiler;
protected $equalized = [3 => 33.3, 6 => 16.7, 7 => 14.3, 8
=> 12.5, 9 => 11.1, 11 => 9.1, 12 => 8.3];
/**
* @var ThemeDetails
*/
protected $details;
/**
* Register Theme stream.
*
* @param string $savePath
*/
public function registerStream($savePath = null)
{
$streamName = $this->details()->addStreams();
/** @var UniformResourceLocator $locator */
$locator = self::gantry()['locator'];
$locator->addPath('gantry-theme', '',
array_merge((array) $savePath, [[$streamName, '']]));
}
/**
* Update all CSS files in the theme.
*
* @param array $outlines
* @return array List of CSS warnings.
*/
public function updateCss(array $outlines = null)
{
$gantry = static::gantry();
$compiler = $this->compiler();
if (is_null($outlines)) {
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$path = $locator->findResource($compiler->getTarget(),
true, true);
// Make sure that all the CSS files get deleted.
if (is_dir($path)) {
Folder::delete($path, false);
}
$outlines = $gantry['outlines'];
}
// Make sure that PHP has the latest data of the files.
clearstatcache();
$warnings = [];
foreach ($outlines as $outline => $title) {
$config = ConfigServiceProvider::load($gantry, $outline);
$compiler->reset()->setConfiguration($outline)->setVariables($config->flatten('styles',
'-'));
$results = $compiler->compileAll()->getWarnings();
if ($results) {
$warnings[$outline] = $results;
}
}
return $warnings;
}
/**
* Set layout to be used.
*
* @param string $name
* @param bool $force
* @return $this
*/
public function setLayout($name = null, $force = false)
{
$gantry = static::gantry();
// Force new layout to be set.
if ($force) {
unset($gantry['configuration']);
}
// Set default name only if configuration has not been set before.
if ($name === null &&
!isset($gantry['configuration'])) {
$name = 'default';
}
$outline = isset($gantry['configuration']) ?
$gantry['configuration'] : null;
// Set configuration if given.
if ($name && $name != $outline) {
GANTRY_DEBUGGER &&
\Gantry\Debugger::addMessage("Using Gantry outline {$name}");
$gantry['configuration'] = $name;
unset($gantry['config']);
$gantry['config'] =
ConfigServiceProvider::load($gantry, $name);
}
return $this;
}
/**
* Get current preset.
*
* @param bool $forced If true, return only forced preset or null.
* @return string|null $preset
*/
public function preset($forced = false)
{
$presets = $this->presets()->toArray();
$preset = $this->preset;
if (!$preset && !$forced) {
$preset =
static::gantry()['config']->get('styles.preset',
'-undefined-');
}
if ($preset && !isset($presets[$preset])) {
$preset = null;
}
return $preset;
}
/**
* Set preset to be used.
*
* @param string $name
* @return $this
*/
public function setPreset($name = null)
{
// Set preset if given.
if ($name) {
$this->preset = $name;
}
return $this;
}
/**
* Return CSS compiler used in the theme.
*
* @return CssCompilerInterface
* @throws \RuntimeException
*/
public function compiler()
{
if (!$this->compiler) {
$compilerClass = (string)
$this->details()->get('configuration.css.compiler',
'\Gantry\Component\Stylesheet\ScssCompiler');
if (!class_exists($compilerClass)) {
throw new \RuntimeException('CSS compiler used by the
theme not found');
}
$details = $this->details();
/** @var CssCompilerInterface $compiler */
$this->compiler = new $compilerClass();
$this->compiler
->setTarget($details->get('configuration.css.target'))
->setPaths($details->get('configuration.css.paths'))
->setFiles($details->get('configuration.css.files'))
->setFonts($details->get('configuration.fonts'));
}
$preset = $this->preset(true);
if ($preset) {
$this->compiler->setConfiguration($preset);
} else {
$gantry = static::gantry();
$this->compiler->setConfiguration(isset($gantry['configuration'])
? $gantry['configuration'] : 'default');
}
return $this->compiler->reset();
}
/**
* Returns URL to CSS file.
*
* If file does not exist, it will be created by using CSS compiler.
*
* @param string $name
* @return string
*/
public function css($name)
{
if (!isset($this->cssCache[$name])) {
$compiler = $this->compiler();
if ($compiler->needsCompile($name, [$this,
'getCssVariables'])) {
GANTRY_DEBUGGER &&
\Gantry\Debugger::startTimer("css-{$name}", "Compiling CSS:
{$name}") && \Gantry\Debugger::addMessage("Compiling CSS:
{$name}");
$compiler->compileFile($name);
GANTRY_DEBUGGER &&
\Gantry\Debugger::stopTimer("css-{$name}");
}
$this->cssCache[$name] = $compiler->getCssUrl($name);
}
return $this->cssCache[$name];
}
public function getCssVariables()
{
if ($this->preset) {
$variables = $this->presets()->flatten($this->preset .
'.styles', '-');
} else {
$gantry = self::gantry();
$variables =
$gantry['config']->flatten('styles', '-');
}
return $variables;
}
/**
* Returns style presets for the theme.
*
* @return Config
*/
public function presets()
{
static $presets;
if (!$presets) {
$gantry = static::gantry();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$filename =
$locator->findResource("gantry-theme://gantry/presets.yaml");
$file = CompiledYamlFile::instance($filename);
$presets = new Config($file->content());
$file->free();
}
return $presets;
}
/**
* Return name of the used layout preset.
*
* @return string
* @throws \RuntimeException
*/
public function type()
{
if (!$this->layoutObject) {
throw new \RuntimeException('Function called too
early');
}
$name = isset($this->layoutObject->preset['name'])
? $this->layoutObject->preset['name'] :
'unknown';
return $name;
}
/**
* Load current layout and its configuration.
*
* @param string $name
* @return Layout
* @throws \LogicException
*/
public function loadLayout($name = null)
{
if (!$name) {
try {
$name = static::gantry()['configuration'];
} catch (\Exception $e) {
throw new \LogicException('Gantry: Outline has not
been defined yet', 500);
}
}
if (!isset($this->layoutObject) ||
$this->layoutObject->name != $name) {
$layout = Layout::instance($name);
if (!$layout->exists()) {
$layout = Layout::instance('default');
}
// TODO: Optimize
$this->layoutObject = $layout->init();
}
return $this->layoutObject;
}
/**
* Check whether layout has content bock.
*
* @return bool
*/
public function hasContent()
{
$layout = $this->loadLayout();
$content = $layout->referencesByType('system',
'content');
return !empty($content);
}
/**
* Load atoms and assets from the page settings.
*
* @since 5.4.9
*/
public function loadAtoms()
{
if (!isset($this->atoms)) {
$this->atoms = true;
GANTRY_DEBUGGER &&
\Gantry\Debugger::startTimer('atoms', "Preparing
atoms");
$gantry = static::gantry();
/** @var Config $config */
$config = $gantry['config'];
/** @var \Gantry\Framework\Document $document */
$document = $gantry['document'];
$atoms = (array) $config->get('page.head.atoms');
foreach ($atoms as $data) {
$atom = [
'type' => 'atom',
'subtype' => $data['type'],
] + $data;
try {
$block = $this->getContent($atom);
$document->addBlock($block);
} catch (\Exception $e) {
if ($gantry->debug()) {
throw new \RuntimeException("Rendering Atom
'{$atom['subtype']}' failed on error:
{$e->getMessage()}", 500, $e);
}
}
}
$assets = (array) $config->get('page.assets');
if ($assets) {
$atom = [
'id' => 'page-assets',
'title' => 'Page Assets',
'type' => 'atom',
'subtype' => 'assets',
'attributes' => $assets +
['enabled' => 1]
];
try {
$block = $this->getContent($atom);
$document->addBlock($block);
} catch (\Exception $e) {
if ($gantry->debug()) {
throw new \RuntimeException("Rendering CSS/JS
Assets failed on error: {$e->getMessage()}", 500, $e);
}
}
}
GANTRY_DEBUGGER &&
\Gantry\Debugger::stopTimer('atoms');
}
}
/**
* Returns all non-empty segments from the layout.
*
* @return array
*/
public function segments()
{
if (!isset($this->segments)) {
$this->segments = $this->loadLayout()->toArray();
GANTRY_DEBUGGER &&
\Gantry\Debugger::startTimer('segments', "Preparing
layout");
$this->prepareLayout($this->segments);
GANTRY_DEBUGGER &&
\Gantry\Debugger::stopTimer('segments');
}
return $this->segments;
}
/**
* Prepare layout for rendering. Initializes all CSS/JS in particles.
*/
public function prepare()
{
$this->segments();
}
/**
* Returns details of the theme.
*
* @return ThemeDetails
*/
public function details()
{
if (!$this->details) {
$this->details = new ThemeDetails($this->name);
}
return $this->details;
}
/**
* Returns configuration of the theme.
*
* @return array
*/
public function configuration()
{
return (array) $this->details()['configuration'];
}
/**
* Function to convert block sizes into CSS classes.
*
* @param $text
* @return string
*/
public function toGrid($text)
{
if (!$text) {
return '';
}
$number = round($text, 1);
$number = max(5, $number);
$number = (string) ($number == 100 ? 100 : min(95, $number));
static $sizes = array(
'33.3' => 'size-33-3',
'16.7' => 'size-16-7',
'14.3' => 'size-14-3',
'12.5' => 'size-12-5',
'11.1' => 'size-11-1',
'9.1' => 'size-9-1',
'8.3' => 'size-8-3'
);
return isset($sizes[$number]) ? ' ' . $sizes[$number] :
'size-' . (int) $number;
}
/**
* Magic setter method
*
* @param mixed $offset Asset name value
* @param mixed $value Asset value
*/
public function __set($offset, $value)
{
if ($offset == 'title') {
$offset = 'name';
}
$this->details()->offsetSet('details.' . $offset,
$value);
}
/**
* Magic getter method
*
* @param mixed $offset Asset name value
* @return mixed Asset value
*/
public function __get($offset)
{
if ($offset == 'title') {
$offset = 'name';
}
$value = $this->details()->offsetGet('details.' .
$offset);
if ($offset == 'version' && is_int($value)) {
$value .= '.0';
}
return $value;
}
/**
* Magic method to determine if the attribute is set
*
* @param mixed $offset Asset name value
* @return boolean True if the value is set
*/
public function __isset($offset)
{
if ($offset == 'title') {
$offset = 'name';
}
return $this->details()->offsetExists('details.' .
$offset);
}
/**
* Magic method to unset the attribute
*
* @param mixed $offset The name value to unset
*/
public function __unset($offset)
{
if ($offset == 'title') {
$offset = 'name';
}
$this->details()->offsetUnset('details.' .
$offset);
}
/**
* Prepare layout by loading all the positions and particles.
*
* Action is needed before displaying the layout as it recalculates
block widths based on the visible content.
*
* @param array $items
* @param bool $temporary
* @param bool $sticky
* @internal
*/
protected function prepareLayout(array &$items, $temporary = false,
$sticky = false)
{
foreach ($items as $i => &$item) {
// Non-numeric items are meta-data which should be ignored.
if (((string)(int) $i !== (string) $i) || !is_object($item)) {
continue;
}
if (!empty($item->children)) {
$fixed = true;
foreach ($item->children as $child) {
$fixed &= !empty($child->attributes->fixed);
}
$this->prepareLayout($item->children, $fixed,
$temporary);
}
// TODO: remove hard coded types.
switch ($item->type) {
case 'system':
break;
case 'atom':
case 'particle':
case 'position':
case 'spacer':
GANTRY_DEBUGGER &&
\Gantry\Debugger::startTimer($item->id, "Rendering
{$item->id}");
$item->content = $this->renderContent($item,
['prepare_layout' => true]);
// Note that content can also be null (postpone
rendering).
if ($item->content === '') {
unset($items[$i]);
}
GANTRY_DEBUGGER &&
\Gantry\Debugger::stopTimer($item->id);
break;
default:
if ($sticky) {
$item->attributes->sticky = 1;
break;
}
if (empty($item->children)) {
unset($items[$i]);
break;
}
$dynamicSize = 0;
$fixedSize = 0;
$childrenCount = count($item->children);
foreach ($item->children as $child) {
if (!isset($child->attributes->size)) {
$child->attributes->size = 100 /
count($item->children);
}
if (empty($child->attributes->fixed)) {
$dynamicSize += $child->attributes->size;
} else {
$fixedSize += $child->attributes->size;
}
}
$roundSize = round($dynamicSize, 1);
$equalized = isset($this->equalized[$childrenCount])
? $this->equalized[$childrenCount] : 0;
// force-casting string for testing comparison due to
weird PHP behavior that returns wrong result
if ($roundSize != 100 && (string) $roundSize !=
(string) ($equalized * $childrenCount)) {
$fraction = 0;
$multiplier = (100 - $fixedSize) / ($dynamicSize ?:
1);
foreach ($item->children as $child) {
if (!empty($child->attributes->fixed)) {
continue;
}
// Calculate size for the next item by taking
account the rounding error from the last item.
// This will allow us to approximate cumulating
error and fix it when rounding error grows
// over the rounding treshold.
$size = ($child->attributes->size *
$multiplier) + $fraction;
$newSize = round($size);
$fraction = $size - $newSize;
$child->attributes->size = $newSize;
}
}
}
}
}
/**
* Renders individual content block, like particle or position.
*
* Function is used to pre-render content.
*
* @param object|array $item
* @param array $options
* @return string|null
*/
public function renderContent($item, $options = [])
{
$gantry = static::gantry();
$content = $this->getContent($item, $options);
/** @var Document $document */
$document = $gantry['document'];
$document->addBlock($content);
$html = $content->toString();
return !strstr($html, '@@DEFERRED@@') ? $html : null;
}
/**
* Renders individual content block, like particle or position.
*
* Function is used to pre-render content.
*
* @param object|array $item
* @param array $options
* @return ContentBlock
* @since 5.4.3
*/
public function getContent($item, $options = [])
{
if (is_array($item)) {
$item = (object) $item;
}
$gantry = static::gantry();
/** @var Config $global */
$global = $gantry['global'];
$production = (bool) $global->get('production');
$subtype = $item->subtype;
$enabled =
$gantry['config']->get("particles.{$subtype}.enabled",
1);
if (!$enabled) {
return new HtmlBlock;
}
$attributes = isset($item->attributes) ? $item->attributes :
[];
$particle =
$gantry['config']->getJoined("particles.{$subtype}",
$attributes);
$cached = false;
$cacheKey = [];
// Enable particle caching only in production mode.
if ($production && isset($particle['caching'])) {
$caching = $particle['caching'] + ['type'
=> 'dynamic'];
switch ($caching['type']) {
case 'static':
$cached = true;
break;
case 'config_matches':
if
(isset($particle['caching']['values'])) {
$values = (array)
$particle['caching']['values'];
$compare = array_intersect_key($particle, $values);
$cached = ($values === $compare);
}
break;
case 'menu':
/** @var Menu $menu */
$menu = $gantry['menu'];
$cacheId = $menu->getCacheId();
// FIXME: menu caching needs to handle dynamic modules
inside menu: turning it off for now.
if (false && $cacheId !== null) {
$cached = true;
$cacheKey['menu_cache_key'] = $cacheId;
}
break;
}
}
if ($cached) {
$cacheKey['language'] =
$gantry['page']->language;
$cacheKey['attributes'] = $particle;
$cacheKey += (array) $item;
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$key = md5(json_encode($cacheKey));
$filename =
$locator->findResource("gantry-cache://theme/html/{$key}.php",
true, true);
$file = PhpFile::instance($filename);
if ($file->exists()) {
try {
return ContentBlock::fromArray((array)
$file->content());
} catch (\Exception $e) {
// Invalid cache, continue to rendering.
GANTRY_DEBUGGER &&
\Gantry\Debugger::addMessage(sprintf('Failed to load %s %s
cache', $item->type, $item->id), 'debug');
}
}
}
// Create new document context for assets.
$context = $this->getContext(['segment' => $item,
'enabled' => 1, 'particle' => $particle] +
$options);
/** @var Document $document */
$document = $gantry['document'];
$document->push();
$html =
trim($this->render("@nucleus/content/{$item->type}.html.twig",
$context));
$content = $document->pop()->setContent($html);
if (isset($file)) {
// Save HTML and assets into the cache.
GANTRY_DEBUGGER &&
\Gantry\Debugger::addMessage(sprintf('Caching %s %s',
$item->type, $item->id), 'debug');
$file->save($content->toArray());
}
return $content;
}
}
PK���[$�E��
�
#Component/Translator/Translator.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Translator;
use Gantry\Component\File\CompiledYamlFile;
use Gantry\Framework\Gantry;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Translator implements TranslatorInterface
{
protected $default = 'en';
protected $active = 'en';
protected $sections = [];
protected $translations = [];
protected $untranslated = [];
public function translate($string)
{
if (preg_match('|^GANTRY5(_[A-Z0-9]+){2,}$|', $string)) {
list(, $section, $code) = explode('_', $string, 3);
$string = ($this->find($this->active, $section, $string)
?: $this->find($this->default, $section, $string)) ?: $string;
}
if (func_num_args() === 1) {
return $string;
}
$args = func_get_args();
$args[0] = $string;
return call_user_func_array('sprintf', $args);
}
/**
* Set new active language if given and return previous active
language.
*
* @param string $language Language code. If not given, current
language is kept.
* @return string Previously active language.
*/
public function active($language = null)
{
$previous = $this->active;
if ($language) {
$this->active = $language;
}
return $previous;
}
public function untranslated()
{
return $this->untranslated;
}
protected function find($language, $section, $string)
{
if (!isset($this->sections[$language][$section])) {
$translations = $this->load($language, $section);
if (isset($this->translations[$language])) {
$this->translations[$language] += $translations;
} else {
$this->translations[$language] = $translations;
}
$this->sections[$language][$section] =
!empty($translations);
}
if (!isset($this->translations[$language][$string])) {
$this->untranslated[$language][$section][$string] = null;
return null;
}
return $this->translations[$language][$string];
}
protected function load($language, $section)
{
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$section = strtolower($section);
if ($section === 'engine') {
// TODO: add support for other engines than nucleus.
$section = 'nucleus';
}
$filename = 'gantry-admin://translations/' . $language .
'/' . $section . '.yaml';
$file = CompiledYamlFile::instance($filename);
if (!$file->exists() && ($pos = strpos($language,
'-')) > 0) {
$filename = 'gantry-admin://translations/' .
substr($language, 0, $pos) . '/' . $section . '.yaml';
$file = CompiledYamlFile::instance($filename);
}
$cachePath =
$locator->findResource('gantry-cache://translations', true,
true);
$translations = (array)
$file->setCachePath($cachePath)->content();
$file->free();
return $translations;
}
}
PK���[�f��GG,Component/Translator/TranslatorInterface.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Translator;
interface TranslatorInterface
{
/**
* @param string $string
* @return string
*/
public function translate($string);
/**
* Set new active language if given and return previous active
language.
*
* @param string $language Language code. If not given, current
language is kept.
* @return string Previously active language.
*/
public function active($language = null);
}
PK���[�Ϸ�&Component/Twig/Node/TwigNodeAssets.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\Node;
class TwigNodeAssets extends \Twig_Node implements
\Twig_NodeCaptureInterface
{
protected $tagName = 'assets';
public function __construct(\Twig_Node $body = null,
\Twig_Node_Expression $location = null, \Twig_Node_Expression $variables =
null, $lineno = 0, $tag = null)
{
parent::__construct(['body' => $body,
'location' => $location, 'variables' =>
$variables], [], $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param \Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(\Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this)
->write("\$assetFunction =
\$this->env->getFunction('parse_assets')->getCallable();\n")
->write('$assetVariables = ')
->subcompile($this->getNode('variables'))
->raw(";\n")
->write("if (\$assetVariables &&
!is_array(\$assetVariables)) {\n")
->indent()
->write("throw new UnexpectedValueException('{%
{$this->tagName} with x %}: x is not an array');\n")
->outdent()
->write("}\n")
->write('$location = ')
->subcompile($this->getNode('location'))
->raw(";\n")
->write("if (\$location &&
!is_string(\$location)) {\n")
->indent()
->write("throw new UnexpectedValueException('{%
{$this->tagName} in x %}: x is not a string');\n")
->outdent()
->write("}\n")
->write("\$priority =
isset(\$assetVariables['priority']) ?
\$assetVariables['priority'] : 0;\n")
->write("ob_start();\n")
->subcompile($this->getNode('body'))
->write("\$content = ob_get_clean();\n")
->write("\$assetFunction(\$content, \$location,
\$priority);\n");
}
}
PK���[���y��(Component/Twig/Node/TwigNodeMarkdown.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\Node;
class TwigNodeMarkdown extends \Twig_Node implements
\Twig_NodeOutputInterface
{
public function __construct(\Twig_Node $body, $lineno, $tag =
'markdown')
{
parent::__construct(['body' => $body], [], $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->getExtension(\'Gantry\Component\Twig\TwigExtension\')->markdownFunction($content);'
. PHP_EOL);
}
}
PK���[7n^c��)Component/Twig/Node/TwigNodePageblock.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\Node;
class TwigNodePageblock extends \Twig_Node implements
\Twig_NodeCaptureInterface
{
protected $tagName = 'pageblock';
public function __construct(\Twig_Node $body = null,
\Twig_Node_Expression $location = null, \Twig_Node_Expression $variables =
null, $lineno = 0, $tag = null)
{
parent::__construct(['body' => $body,
'location' => $location, 'variables' =>
$variables], [], $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param \Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(\Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this)
->write('$pageblockVariables = ')
->subcompile($this->getNode('variables'))
->raw(";\n")
->write("if (\$pageblockVariables &&
!is_array(\$pageblockVariables)) {\n")
->indent()
->write("throw new UnexpectedValueException('{%
{$this->tagName} with x %}: x is not an array');\n")
->outdent()
->write("}\n")
->write('$location = ')
->subcompile($this->getNode('location'))
->raw(";\n")
->write("if (\$location &&
!is_string(\$location)) {\n")
->indent()
->write("throw new UnexpectedValueException('{%
{$this->tagName} in x %}: x is not a string');\n")
->outdent()
->write("}\n")
->write("\$priority =
isset(\$pageblockVariables['priority']) ?
\$pageblockVariables['priority'] : 0;\n")
->write("ob_start();\n")
->subcompile($this->getNode('body'))
->write("\$content = ob_get_clean();\n")
->write("Gantry\Framework\Gantry::instance()['document']->addHtml(\$content,
\$priority, \$location);\n");
}
}
PK���[�ܽ���'Component/Twig/Node/TwigNodeScripts.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\Node;
class TwigNodeScripts extends TwigNodeAssets
{
protected $tagName = 'scripts';
}
PK���[JtE5��&Component/Twig/Node/TwigNodeStyles.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\Node;
class TwigNodeStyles extends TwigNodeScripts
{
protected $tagName = 'styles';
}
PK���[�$�� &Component/Twig/Node/TwigNodeSwitch.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\Node;
class TwigNodeSwitch extends \Twig_Node
{
public function __construct(\Twig_Node $value, \Twig_Node $cases,
\Twig_Node $default = null, $lineno = 0, $tag = null)
{
parent::__construct(array('value' => $value,
'cases' => $cases, 'default' => $default),
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('switch (')
->subcompile($this->getNode('value'))
->raw(") {\n")
->indent();
foreach ($this->getNode('cases') as $case) {
if (!$case->hasNode('body')) {
continue;
}
foreach ($case->getNode('values') as $value) {
$compiler
->write('case ')
->subcompile($value)
->raw(":\n");
}
$compiler
->write("{\n")
->indent()
->subcompile($case->getNode('body'))
->write("break;\n")
->outdent()
->write("}\n");
}
if ($this->hasNode('default') &&
$this->getNode('default') !== null) {
$compiler
->write("default:\n")
->write("{\n")
->indent()
->subcompile($this->getNode('default'))
->outdent()
->write("}\n");
}
$compiler
->outdent()
->write("}\n");
}
}
PK���[�K��%Component/Twig/Node/TwigNodeThrow.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\Node;
class TwigNodeThrow extends \Twig_Node
{
public function __construct(
$code,
\Twig_Node $message,
$lineno = 0,
$tag = null
)
{
parent::__construct(['message' => $message],
['code' => $code], $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param \Twig_Compiler $compiler A Twig_Compiler instance
* @throws \LogicException
*/
public function compile(\Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$compiler
->write('throw new \RuntimeException(')
->subcompile($this->getNode('message'))
->write(', ')
->write($this->getAttribute('code') ?: 500)
->write(");\n");
}
}
PK���[Bh���(Component/Twig/Node/TwigNodeTryCatch.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\Node;
class TwigNodeTryCatch extends \Twig_Node
{
public function __construct(\Twig_Node $try, \Twig_Node $catch = null,
$lineno = 0, $tag = null)
{
parent::__construct(array('try' => $try,
'catch' => $catch), array(), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param \Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(\Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$compiler
->write('try {')
;
$compiler
->indent()
->subcompile($this->getNode('try'))
;
if ($this->hasNode('catch') && null !==
$this->getNode('catch')) {
$compiler
->outdent()
->write('} catch (\Exception $e) {' .
"\n")
->indent()
->write('if
($context[\'gantry\']->debug()) throw $e;' .
"\n")
->write('GANTRY_DEBUGGER &&
method_exists(\'Gantry\\Debugger\', \'addException\')
&& \Gantry\Debugger::addException($e);' . "\n")
->write('$context[\'e\'] = $e;' .
"\n")
->subcompile($this->getNode('catch'))
;
}
$compiler
->outdent()
->write("}\n");
}
}
PK���[��5��
�
0Component/Twig/TokenParser/TokenParserAssets.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\TokenParser;
use Gantry\Component\Twig\Node\TwigNodeScripts;
/**
* Adds javascript / style assets to head/footer/custom location.
*
* {% assets in 'head' with { priority: 2 } %}
* <script type="text/javascript" src="{{
url('gantry-theme://js/my.js') }}"></script>
* <link rel="stylesheet" href="{{
url('gantry-assets://css/font-awesome.min.css') }}"
type="text/css"/>
* {% endassets -%}
*/
class TokenParserAssets extends \Twig_TokenParser
{
/**
* Parses a token and returns a node.
*
* @param \Twig_Token $token A Twig_Token instance
*
* @return \Twig_Node A Twig_Node instance
*/
public function parse(\Twig_Token $token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
list($location, $variables) = $this->parseArguments($token);
$content = $this->parser->subparse([$this,
'decideBlockEnd'], true);
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
return new TwigNodeScripts($content, $location, $variables,
$lineno, $this->getTag());
}
/**
* @param \Twig_Token $token
* @return array
*/
protected function parseArguments(\Twig_Token $token)
{
$stream = $this->parser->getStream();
$location = null;
if ($stream->nextIf(\Twig_Token::OPERATOR_TYPE, 'in'))
{
$location =
$this->parser->getExpressionParser()->parseExpression();
} else {
$lineno = $token->getLine();
$location = new
\Twig_Node_Expression_Constant('head', $lineno);
}
if ($stream->nextIf(\Twig_Token::NAME_TYPE, 'with')) {
$variables =
$this->parser->getExpressionParser()->parseExpression();
} else {
$lineno = $token->getLine();
$variables = new \Twig_Node_Expression_Array([], $lineno);
$variables->setAttribute('priority', 0);
}
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
return [$location, $variables];
}
public function decideBlockEnd(\Twig_Token $token)
{
return $token->test('endassets');
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'assets';
}
}
PK���[B�$��2Component/Twig/TokenParser/TokenParserMarkdown.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\TokenParser;
use Gantry\Component\Twig\Node\TwigNodeMarkdown;
/**
* Adds ability to inline markdown between tags.
*
* {% markdown %}
* This is **bold** and this _underlined_
*
* 1. This is a bullet list
* 2. This is another item in that same list
* {% endmarkdown %}
*/
class TokenParserMarkdown extends \Twig_TokenParser
{
/**
* {@inheritdoc}
*/
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 TwigNodeMarkdown($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');
}
/**
* {@inheritdoc}
*/
public function getTag()
{
return 'markdown';
}
}
PK���[I��\ \ 3Component/Twig/TokenParser/TokenParserPageblock.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\TokenParser;
use Gantry\Component\Twig\Node\TwigNodePageblock;
/**
* Adds javascript / style assets to head/footer/custom location.
*
* {% pageblock in 'bottom' with { priority: 0 } %}
* <div>Bottom HTML</div>
* {% endpageblock -%}
*/
class TokenParserPageblock extends \Twig_TokenParser
{
/**
* Parses a token and returns a node.
*
* @param \Twig_Token $token A Twig_Token instance
*
* @return \Twig_Node A Twig_Node instance
*/
public function parse(\Twig_Token $token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
list($location, $variables) = $this->parseArguments($token);
$content = $this->parser->subparse([$this,
'decideBlockEnd'], true);
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
return new TwigNodePageblock($content, $location, $variables,
$lineno, $this->getTag());
}
/**
* @param \Twig_Token $token
* @return array
*/
protected function parseArguments(\Twig_Token $token)
{
$stream = $this->parser->getStream();
$lineno = $token->getLine();
$location = new
\Twig_Node_Expression_Constant($stream->expect(\Twig_Token::NAME_TYPE)->getValue(),
$lineno);
if ($stream->nextIf(\Twig_Token::NAME_TYPE, 'with')) {
$variables =
$this->parser->getExpressionParser()->parseExpression();
} else {
$lineno = $token->getLine();
$variables = new \Twig_Node_Expression_Array([], $lineno);
$variables->setAttribute('priority', 0);
}
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
return [$location, $variables];
}
public function decideBlockEnd(\Twig_Token $token)
{
return $token->test('endpageblock');
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'pageblock';
}
}
PK���[
FX���1Component/Twig/TokenParser/TokenParserScripts.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\TokenParser;
/**
* Adds scripts to head/footer/custom location.
*
* {% scripts in 'head' with { priority: 2 } %}
* <script type="text/javascript" src="{{
url('gantry-theme://js/my.js') }}"></script>
* {% endscripts -%}
*/
class TokenParserScripts extends TokenParserAssets
{
public function decideBlockEnd(\Twig_Token $token)
{
return $token->test('endscripts');
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'scripts';
}
}
PK���[�++B��0Component/Twig/TokenParser/TokenParserStyles.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\TokenParser;
/**
* Adds stylesheets to document.
*
* {% styles with { priority: 2 } %}
* <link rel="stylesheet" href="{{
url('gantry-assets://css/font-awesome.min.css') }}"
type="text/css"/>
* {% endstyles -%}
*/
class TokenParserStyles extends TokenParserAssets
{
public function decideBlockEnd(\Twig_Token $token)
{
return $token->test('endstyles');
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'styles';
}
}
PK���[���#��0Component/Twig/TokenParser/TokenParserSwitch.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\TokenParser;
use Gantry\Component\Twig\Node\TwigNodeSwitch;
/**
* Adds ability use elegant switch instead of ungainly if statements
*
* {% switch type %}
* {% case 'foo' %}
* {{ my_data.foo }}
* {% case 'bar' %}
* {{ my_data.bar }}
* {% default %}
* {{ my_data.default }}
* {% endswitch %}
*/
class TokenParserSwitch extends \Twig_TokenParser
{
/**
* {@inheritdoc}
*/
public function parse(\Twig_Token $token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
$name =
$this->parser->getExpressionParser()->parseExpression();
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
// There can be some whitespace between the {% switch %} and first
{% case %} tag.
while ($stream->getCurrent()->getType() ===
\Twig_Token::TEXT_TYPE &&
trim($stream->getCurrent()->getValue()) === '') {
$stream->next();
}
$stream->expect(\Twig_Token::BLOCK_START_TYPE);
$expressionParser = $this->parser->getExpressionParser();
$default = null;
$cases = [];
$end = false;
while (!$end) {
$next = $stream->next();
switch ($next->getValue()) {
case 'case':
$values = [];
while (true) {
$values[] =
$expressionParser->parsePrimaryExpression();
// Multiple allowed values?
if ($stream->test(\Twig_Token::OPERATOR_TYPE,
'or')) {
$stream->next();
} else {
break;
}
}
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
$body = $this->parser->subparse(array($this,
'decideIfFork'));
$cases[] = new \Twig_Node([
'values' => new \Twig_Node($values),
'body' => $body
]);
break;
case 'default':
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
$default = $this->parser->subparse(array($this,
'decideIfEnd'));
break;
case 'endswitch':
$end = true;
break;
default:
throw new \Twig_Error_Syntax(sprintf('Unexpected
end of template. Twig was looking for the following tags "case",
"default", or "endswitch" to close the
"switch" block started at line %d)', $lineno), -1);
}
}
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
return new TwigNodeSwitch($name, new \Twig_Node($cases), $default,
$lineno, $this->getTag());
}
/**
* Decide if current token marks switch logic.
*
* @param \Twig_Token $token
* @return bool
*/
public function decideIfFork(\Twig_Token $token)
{
return $token->test(array('case', 'default',
'endswitch'));
}
/**
* Decide if current token marks end of swtich block.
*
* @param \Twig_Token $token
* @return bool
*/
public function decideIfEnd(\Twig_Token $token)
{
return $token->test(array('endswitch'));
}
/**
* {@inheritdoc}
*/
public function getTag()
{
return 'switch';
}
}
PK���[�ʱtt/Component/Twig/TokenParser/TokenParserThrow.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\TokenParser;
use Gantry\Component\Twig\Node\TwigNodeThrow;
/**
* Handles try/catch in template file.
*
* <pre>
* {% throw 404 'Not Found' %}
* </pre>
*/
class TokenParserThrow extends \Twig_TokenParser
{
/**
* Parses a token and returns a node.
*
* @param \Twig_Token $token A Twig_Token instance
*
* @return \Twig_Node A Twig_Node instance
*/
public function parse(\Twig_Token $token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
$code =
$stream->expect(\Twig_Token::NUMBER_TYPE)->getValue();
$message =
$this->parser->getExpressionParser()->parseExpression();
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
return new TwigNodeThrow($code, $message, $lineno,
$this->getTag());
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'throw';
}
}
PK���[�TLL2Component/Twig/TokenParser/TokenParserTryCatch.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig\TokenParser;
use Gantry\Component\Twig\Node\TwigNodeTryCatch;
/**
* Handles try/catch in template file.
*
* <pre>
* {% try %}
* <li>{{ user.get('name') }}</li>
* {% catch %}
* {{ e.message }}
* {% endcatch %}
* </pre>
*/
class TokenParserTryCatch extends \Twig_TokenParser
{
/**
* Parses a token and returns a node.
*
* @param \Twig_Token $token A Twig_Token instance
*
* @return \Twig_Node A Twig_Node instance
*/
public function parse(\Twig_Token $token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
$try = $this->parser->subparse([$this,
'decideCatch']);
$stream->next();
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
$catch = $this->parser->subparse([$this,
'decideEnd']);
$stream->next();
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
return new TwigNodeTryCatch($try, $catch, $lineno,
$this->getTag());
}
public function decideCatch(\Twig_Token $token)
{
return $token->test(array('catch'));
}
public function decideEnd(\Twig_Token $token)
{
return $token->test(array('endtry')) ||
$token->test(array('endcatch'));
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'try';
}
}
PK���[�
�&Component/Twig/TwigCacheFilesystem.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig;
/**
* Class TwigCacheFilesystem
* @package Gantry\Component\Twig
*
* Replaces \Twig_Cache_Filesystem, needed for being able to change PHP
versions on fly.
*/
class TwigCacheFilesystem implements \Twig_CacheInterface
{
const FORCE_BYTECODE_INVALIDATION = 1;
private $directory;
private $options;
/**
* @param $directory string The root cache directory
* @param $options int A set of options
*/
public function __construct($directory, $options = 0)
{
$this->directory = rtrim($directory,
'\/').'/';
$this->options = $options;
}
/**
* {@inheritdoc}
*/
public function generateKey($name, $className)
{
$hash = hash('sha256', $className . '-' .
PHP_VERSION);
return
$this->directory.$hash[0].$hash[1].'/'.$hash.'.php';
}
/**
* {@inheritdoc}
*/
public function load($key)
{
@include_once $key;
}
/**
* {@inheritdoc}
*/
public function write($key, $content)
{
$dir = dirname($key);
if (!is_dir($dir)) {
if (false === @mkdir($dir, 0777, true) &&
!is_dir($dir)) {
throw new \RuntimeException(sprintf('Unable to create
the cache directory (%s).', $dir));
}
} elseif (!is_writable($dir)) {
throw new \RuntimeException(sprintf('Unable to write in
the cache directory (%s).', $dir));
}
$tmpFile = tempnam($dir, basename($key));
if (false !== @file_put_contents($tmpFile, $content) &&
@rename($tmpFile, $key)) {
@chmod($key, 0666 & ~umask());
if (self::FORCE_BYTECODE_INVALIDATION == ($this->options
& self::FORCE_BYTECODE_INVALIDATION)) {
// Compile cached file into bytecode cache
if (function_exists('opcache_invalidate')) {
// Silence error in case if `opcache.restrict_api`
directive is set.
@opcache_invalidate($key, true);
} elseif (function_exists('apc_compile_file')) {
@apc_compile_file($key);
}
}
return;
}
throw new \RuntimeException(sprintf('Failed to write cache
file "%s".', $key));
}
/**
* {@inheritdoc}
*/
public function getTimestamp($key)
{
if (!file_exists($key)) {
return 0;
}
return (int) @filemtime($key);
}
}
PK���[K�
k�Q�Q
Component/Twig/TwigExtension.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Twig;
use Gantry\Component\Content\Document\HtmlDocument;
use Gantry\Component\Gantry\GantryTrait;
use Gantry\Component\Translator\TranslatorInterface;
use Gantry\Component\Twig\TokenParser\TokenParserPageblock;
use Gantry\Component\Twig\TokenParser\TokenParserAssets;
use Gantry\Component\Twig\TokenParser\TokenParserScripts;
use Gantry\Component\Twig\TokenParser\TokenParserStyles;
use Gantry\Component\Twig\TokenParser\TokenParserTryCatch;
use Gantry\Component\Twig\TokenParser\TokenParserMarkdown;
use Gantry\Component\Twig\TokenParser\TokenParserSwitch;
use Gantry\Component\Twig\TokenParser\TokenParserThrow;
use Gantry\Framework\Gantry;
use Gantry\Framework\Markdown\Parsedown;
use Gantry\Framework\Markdown\ParsedownExtra;
use Gantry\Framework\Request;
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccess;
class TwigExtension extends \Twig_Extension implements
\Twig_Extension_GlobalsInterface
{
use GantryTrait;
/**
* Register some standard globals
*
* @return array
*/
public function getGlobals()
{
return [
'gantry' => static::gantry(),
];
}
/**
* Return a list of all filters.
*
* @return array
*/
public function getFilters()
{
$filters = [
new \Twig_SimpleFilter('html', [$this,
'htmlFilter']),
new \Twig_SimpleFilter('url', [$this,
'urlFunc']),
new \Twig_SimpleFilter('trans_key', [$this,
'transKeyFilter']),
new \Twig_SimpleFilter('trans', [$this,
'transFilter']),
new \Twig_SimpleFilter('repeat', [$this,
'repeatFilter']),
new \Twig_SimpleFilter('values', [$this,
'valuesFilter']),
new \Twig_SimpleFilter('base64',
'base64_encode'),
new \Twig_SimpleFilter('imagesize', [$this,
'imageSize']),
new \Twig_SimpleFilter('truncate_text', [$this,
'truncateText']),
new \Twig_SimpleFilter('attribute_array', [$this,
'attributeArrayFilter'], ['is_safe' =>
['html']]),
];
if (1 || GANTRY5_PLATFORM !== 'grav') {
$filters = array_merge($filters, [
new \Twig_SimpleFilter('fieldName', [$this,
'fieldNameFilter']),
new \Twig_SimpleFilter('json_decode', [$this,
'jsonDecodeFilter']),
new \Twig_SimpleFilter('truncate_html', [$this,
'truncateHtml']),
new \Twig_SimpleFilter('markdown', [$this,
'markdownFunction'], ['is_safe' =>
['html']]),
new \Twig_SimpleFilter('nicetime', [$this,
'nicetimeFilter']),
// Casting values
new \Twig_SimpleFilter('string', [$this,
'stringFilter']),
new \Twig_SimpleFilter('int', [$this,
'intFilter'], ['is_safe' => ['all']]),
new \Twig_SimpleFilter('bool', [$this,
'boolFilter']),
new \Twig_SimpleFilter('float', [$this,
'floatFilter'], ['is_safe' => ['all']]),
new \Twig_SimpleFilter('array', [$this,
'arrayFilter']),
]);
}
return $filters;
}
/**
* Return a list of all functions.
*
* @return array
*/
public function getFunctions()
{
$functions = [
new \Twig_SimpleFunction('nested', [$this,
'nestedFunc']),
new \Twig_SimpleFunction('parse_assets', [$this,
'parseAssetsFunc']),
new \Twig_SimpleFunction('colorContrast', [$this,
'colorContrastFunc']),
new \Twig_SimpleFunction('get_cookie', [$this,
'getCookie']),
new \Twig_SimpleFunction('preg_match', [$this,
'pregMatch']),
new \Twig_SimpleFunction('imagesize', [$this,
'imageSize']),
new \Twig_SimpleFunction('is_selected', [$this,
'is_selectedFunc']),
new \Twig_SimpleFunction('url', [$this,
'urlFunc']),
];
if (1 || GANTRY5_PLATFORM !== 'grav') {
$functions = array_merge($functions, [
new \Twig_SimpleFunction('array', [$this,
'arrayFilter']),
new \Twig_SimpleFunction('json_decode', [$this,
'jsonDecodeFilter']),
]);
}
return $functions;
}
/**
* @return array
*/
public function getTokenParsers()
{
return [
new TokenParserPageblock(),
new TokenParserAssets(),
new TokenParserScripts(),
new TokenParserStyles(),
new TokenParserThrow(),
new TokenParserTryCatch(),
new TokenParserMarkdown(),
new TokenParserSwitch()
];
}
/**
* Filters field name by changing dot notation into array notation.
*
* @param string $str
* @return string
*/
public function fieldNameFilter($str)
{
$path = explode('.', $str);
return array_shift($path) . ($path ? '[' .
implode('][', $path) . ']' : '');
}
/**
* Translate by using key, default on original string.
*
* @param $str
* @return string
*/
public function transKeyFilter($str)
{
$params = \func_get_args();
array_shift($params);
$key = preg_replace('|[^A-Z0-9]+|', '_',
strtoupper(implode('_', $params)));
$translation = $this->transFilter($key);
return $translation === $key ? $str : $translation;
}
/**
* Translate string.
*
* @param string $str
* @return string
*/
public function transFilter($str)
{
/** @var TranslatorInterface $translator */
static $translator;
$params = \func_get_args();
if (!$translator) {
$translator = self::gantry()['translator'];
}
return \call_user_func_array([$translator, 'translate'],
$params);
}
/**
* Repeat string x times.
*
* @param string $str
* @param int $count
* @return string
*/
public function repeatFilter($str, $count)
{
return str_repeat($str, max(0, (int) $count));
}
/**
* Decodes string from JSON.
*
* @param string $str
* @param bool $assoc
* @param int $depth
* @param int $options
* @return array
*/
public function jsonDecodeFilter($str, $assoc = false, $depth = 512,
$options = 0)
{
return json_decode(html_entity_decode($str), $assoc, $depth,
$options);
}
public function imageSize($src, $attrib = true, $remote = false)
{
// TODO: need to better handle absolute and relative paths
//$url =
Gantry::instance()['document']->url(trim((string) $src),
false, false);
$width = $height = null;
$sizes = ['width' => $width, 'height' =>
$height];
$attr = '';
if (@is_file($src) || $remote) {
try {
list($width, $height,, $attr) = @getimagesize($src);
} catch (\Exception $e) {}
$sizes['width'] = $width;
$sizes['height'] = $height;
}
return $attrib ? $attr : $sizes;
}
/**
* Reindexes values in array.
*
* @param array $array
* @return array
*/
public function valuesFilter(array $array)
{
return array_values($array);
}
/**
* Casts input to string.
*
* @param mixed $input
* @return string
*/
public function stringFilter($input)
{
return (string) $input;
}
/**
* Casts input to int.
*
* @param mixed $input
* @return int
*/
public function intFilter($input)
{
return (int) $input;
}
/**
* Casts input to bool.
*
* @param mixed $input
* @return bool
*/
public function boolFilter($input)
{
return (bool) $input;
}
/**
* Casts input to float.
*
* @param mixed $input
* @return float
*/
public function floatFilter($input)
{
return (float) $input;
}
/**
* Casts input to array.
*
* @param mixed $input
* @return array
*/
public function arrayFilter($input)
{
return (array) $input;
}
/**
* Takes array of attribute keys and values and converts it to properly
escaped HTML attributes.
*
* @example ['data-id' => 'id',
'data-key' => 'key'] => '
data-id="id" data-key="key"'
* @example [['data-id' => 'id'],
['data-key' => 'key']] => '
data-id="id" data-key="key"'
*
* @param string|string[] $input
* @return string
*/
public function attributeArrayFilter($input)
{
if (\is_string($input)) {
return $input;
}
$array = [];
foreach ((array) $input as $key => $value) {
if (\is_array($value)) {
foreach ((array) $value as $key2 => $value2) {
$array[] = HtmlDocument::escape($key2) .
'="' . HtmlDocument::escape($value2, 'html_attr')
. '"';
}
} elseif ($key) {
$array[] = HtmlDocument::escape($key) . '="'
. HtmlDocument::escape($value, 'html_attr') . '"';
}
}
return $array ? ' ' . implode(' ', $array) :
'';
}
public function is_selectedFunc($a, $b)
{
$b = (array) $b;
array_walk(
$b,
function (&$item) {
if (\is_bool($item)) {
$item = (int) $item;
}
$item = (string) $item;
}
);
return \in_array((string) $a, $b, true);
}
/**
* Truncate text by number of characters but can cut off words. Removes
html tags.
*
* @param string $string
* @param int $limit Max number of characters.
*
* @return string
*/
public function truncateText($string, $limit = 150)
{
$platform = Gantry::instance()['platform'];
return $platform->truncate($string, (int) $limit, false);
}
/**
* Truncate text by number of characters but can cut off words.
*
* @param string $string
* @param int $limit Max number of characters.
*
* @return string
*/
public function truncateHtml($string, $limit = 150)
{
$platform = Gantry::instance()['platform'];
return $platform->truncate($string, (int) $limit, true);
}
/**
* @param string $string
* @param bool $block Block or Line processing
* @param array $settings
* @return mixed|string
*/
public function markdownFunction($string, $block = true, array
$settings = null)
{
// Initialize the preferred variant of Parsedown
if (!empty($settings['extra'])) {
$parsedown = new ParsedownExtra($settings);
} else {
$parsedown = new Parsedown($settings);
}
if ($block) {
$string = $parsedown->text($string);
} else {
$string = $parsedown->line($string);
}
return $string;
}
/**
* Get value by using dot notation for nested arrays/objects.
*
* @example {{ nested(array,
'this.is.my.nested.variable')|json_encode }}
*
* @param array $items Array of items.
* @param string $name Dot separated path to the requested
value.
* @param mixed $default Default value (or null).
* @param string $separator Separator, defaults to '.'
* @return mixed Value.
*/
public function nestedFunc($items, $name, $default = null, $separator =
'.')
{
if ($items instanceof NestedArrayAccess) {
return $items->get($name, $default, $separator);
}
$path = explode($separator, $name);
$current = $items;
foreach ($path as $field) {
if (\is_object($current) &&
isset($current->{$field})) {
$current = $current->{$field};
} elseif (\is_array($current) &&
isset($current[$field])) {
$current = $current[$field];
} else {
return $default;
}
}
return $current;
}
/**
* Return URL to the resource.
*
* @example {{
url('theme://images/logo.png')|default('http://www.placehold.it/150x100/f4f4f4')
}}
*
* @param string $input Resource to be located.
* @param bool $domain True to include domain name.
* @param int $timestamp_age Append timestamp to files that are less
than x seconds old. Defaults to a week.
* Use value <= 0 to disable the
feature.
* @return string|null Returns url to the resource or null if
resource was not found.
*/
public function urlFunc($input, $domain = false, $timestamp_age = null)
{
$gantry = Gantry::instance();
return $gantry['document']->url(trim((string) $input),
$domain, $timestamp_age);
}
/**
* Filter stream URLs from HTML input.
*
* @param string $str HTML input to be filtered.
* @param bool $domain True to include domain name.
* @param int $timestamp_age Append timestamp to files that are less
than x seconds old. Defaults to a week.
* Use value <= 0 to disable the
feature.
* @return string Returns modified HTML.
*/
public function htmlFilter($str, $domain = false, $timestamp_age =
null)
{
$gantry = Gantry::instance();
return $gantry['document']->urlFilter($str, $domain,
$timestamp_age);
}
/**
* @param \libXMLError $error
* @param string $input
* @throws \RuntimeException
*/
protected function dealXmlError(\libXMLError $error, $input)
{
switch ($error->level) {
case LIBXML_ERR_WARNING:
$level = 1;
$message = "DOM Warning {$error->code}: ";
break;
case LIBXML_ERR_ERROR:
$level = 2;
$message = "DOM Error {$error->code}: ";
break;
case LIBXML_ERR_FATAL:
$level = 3;
$message = "Fatal DOM Error {$error->code}: ";
break;
default:
$level = 3;
$message = "Unknown DOM Error {$error->code}:
";
}
$message .= "{$error->message} while
parsing:\n{$input}\n";
if ($level <= 2 && !Gantry::instance()->debug()) {
return;
}
throw new \RuntimeException($message, 500);
}
/**
* Move supported document head elements into platform document object,
return all
* unsupported tags in a string.
*
* @param string $input
* @param string $location
* @param int $priority
* @return string
*/
public function parseAssetsFunc($input, $location = 'head',
$priority = 0)
{
if ($location === 'head') {
$scope = 'head';
$html = "<!doctype
html>\n<html><head>{$input}</head><body></body></html>";
} else {
$scope = 'body';
$html = "<!doctype
html>\n<html><head></head><body>{$input}</body></html>";
}
libxml_clear_errors();
$internal = libxml_use_internal_errors(true);
$doc = new \DOMDocument();
$doc->loadHTML($html);
foreach (libxml_get_errors() as $error) {
$this->dealXmlError($error, $html);
}
libxml_clear_errors();
libxml_use_internal_errors($internal);
$raw = [];
/** @var \DomElement $element */
foreach
($doc->getElementsByTagName($scope)->item(0)->childNodes as
$element) {
if (empty($element->tagName)) {
continue;
}
$result = ['tag' => $element->tagName,
'content' => $element->textContent];
foreach ($element->attributes as $attribute) {
$result[$attribute->name] = $attribute->value;
}
$success =
Gantry::instance()['document']->addHeaderTag($result,
$location, (int) $priority);
if (!$success) {
$raw[] = $doc->saveHTML($element);
}
}
return implode("\n", $raw);
}
public function colorContrastFunc($value)
{
$value = str_replace(' ', '', $value);
$rgb = new \stdClass;
$opacity = 1;
if (0 !== strpos($value, 'rgb')) {
$value = str_replace('#', '', $value);
if (\strlen($value) === 3) {
$h0 = str_repeat(substr($value, 0, 1), 2);
$h1 = str_repeat(substr($value, 1, 1), 2);
$h2 = str_repeat(substr($value, 2, 1), 2);
$value = $h0 . $h1 . $h2;
}
$rgb->r = hexdec(substr($value, 0, 2));
$rgb->g = hexdec(substr($value, 2, 2));
$rgb->b = hexdec(substr($value, 4, 2));
} else {
preg_match("/(\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*(1\\.|0?\\.?[0-9]?+))?/uim",
$value, $matches);
$rgb->r = $matches[1];
$rgb->g = $matches[2];
$rgb->b = $matches[3];
$opacity = isset($matches[4]) ? $matches[4] : 1;
$opacity = substr($opacity, 0, 1) === '.' ?
'0' . $opacity : $opacity;
}
$yiq = ((($rgb->r * 299) + ($rgb->g * 587) + ($rgb->b *
114)) / 1000) >= 128;
$contrast = $yiq || (!$opacity || (float) $opacity < 0.35);
return $contrast;
}
/**
* Displays a facebook style 'time ago' formatted date/time.
*
* @param string|int $date
* @param bool $long_strings
*
* @return string
*/
public function nicetimeFilter($date, $long_strings = true)
{
static $lengths = [60, 60, 24, 7, 4.35, 12, 10];
static $periods_long = [
'GANTRY5_ENGINE_NICETIME_SECOND',
'GANTRY5_ENGINE_NICETIME_MINUTE',
'GANTRY5_ENGINE_NICETIME_HOUR',
'GANTRY5_ENGINE_NICETIME_DAY',
'GANTRY5_ENGINE_NICETIME_WEEK',
'GANTRY5_ENGINE_NICETIME_MONTH',
'GANTRY5_ENGINE_NICETIME_YEAR',
'GANTRY5_ENGINE_NICETIME_DECADE'
];
static $periods_short = [
'GANTRY5_ENGINE_NICETIME_SEC',
'GANTRY5_ENGINE_NICETIME_MIN',
'GANTRY5_ENGINE_NICETIME_HR',
'GANTRY5_ENGINE_NICETIME_DAY',
'GANTRY5_ENGINE_NICETIME_WK',
'GANTRY5_ENGINE_NICETIME_MO',
'GANTRY5_ENGINE_NICETIME_YR',
'GANTRY5_ENGINE_NICETIME_DEC'
];
if (empty($date)) {
return
$this->transFilter('GANTRY5_ENGINE_NICETIME_NO_DATE_PROVIDED');
}
$periods = $long_strings ? $periods_long : $periods_short;
$now = time();
// check if unix timestamp
if ((string)(int)$date === (string)$date) {
$unix_date = (int)$date;
} else {
$unix_date = strtotime($date);
}
// check validity of date
if (!$unix_date) {
return
$this->transFilter('GANTRY5_ENGINE_NICETIME_BAD_DATE');
}
// is it future date or past date
if ($now > $unix_date) {
$difference = $now - $unix_date;
$tense =
$this->transFilter('GANTRY5_ENGINE_NICETIME_AGO');
} else if ($now === $unix_date) {
$difference = $now - $unix_date;
$tense =
$this->transFilter('GANTRY5_ENGINE_NICETIME_JUST_NOW');
} else {
$difference = $unix_date - $now;
$tense =
$this->transFilter('GANTRY5_ENGINE_NICETIME_FROM_NOW');
}
for ($j = 0; $difference >= $lengths[$j] && $j <
\count($lengths) - 1; $j++) {
$difference /= $lengths[$j];
}
$period = $periods[$j];
$difference = round($difference);
if ($difference !== 1) {
$period .= '_PLURAL';
}
$period = $this->transFilter($period);
if ($now === $unix_date) {
return $tense;
}
return "{$difference} {$period} {$tense}";
}
public function getCookie($name)
{
$gantry = Gantry::instance();
/** @var Request $request */
$request = $gantry['request'];
return $request->cookie[$name];
}
public function pregMatch($pattern, $subject, &$matches = [])
{
preg_match($pattern, $subject, $matches);
return $matches ?: false;
}
}
PK���[��6���Component/Url/Url.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Url;
class Url
{
/**
* UTF8 aware parse_url().
*
* @param string $url
* @param bool $queryArray
* @return array|bool
*/
public static function parse($url, $queryArray = false)
{
$encodedUrl = preg_replace_callback(
'%[^:/@?&=#]+%usD',
function ($matches) { return rawurlencode($matches[0]); },
$url
);
// PHP versions below 5.4.7 have troubles with URLs without scheme,
so lets help by fixing that.
// TODO: This is not needed in PHP >= 5.4.7, but for now we need
to test if the function works.
if ('/' === $encodedUrl[0] && false !==
strpos($encodedUrl, '://')) {
$schemeless = true;
// Fix the path so that parse_url() will not return false.
$parts = parse_url('fake://fake.com' . $encodedUrl);
// Remove the fake values.
unset($parts['scheme'], $parts['host']);
} else {
$parts = parse_url($encodedUrl);
}
if (!$parts) {
return false;
}
// PHP versions below 5.4.7 do not understand schemeless URLs
starting with // either.
if (isset($schemeless) && !isset($parts['host'])
&& 0 === strpos($encodedUrl, '//')) {
// Path is stored in format: //[host]/[path], so let's fix
it.
list($parts['host'], $path) = explode('/',
substr($parts['path'], 2), 2);
$parts['path'] = "/{$path}";
}
foreach($parts as $name => $value) {
$parts[$name] = rawurldecode($value);
}
// Return query string also as an array if requested.
if ($queryArray) {
$parts['vars'] = isset($parts['query']) ?
static::parseQuery($parts['query']) : [];
}
return $parts;
}
/**
* Parse query string and return array.
*
* @param $query
* @return mixed
*/
public static function parseQuery($query)
{
parse_str($query, $vars);
return $vars;
}
/**
* Build parsed URL array.
*
* @param array $parsed_url
* @return string
*/
public static function build(array $parsed_url)
{
// Build query string from variables if they are set.
if (isset($parsed_url['vars'])) {
$parsed_url['query'] =
static::buildQuery($parsed_url['vars']);
}
// Build individual parts of the url.
$scheme = isset($parsed_url['scheme']) ?
$parsed_url['scheme'] . '://' : '';
$host = isset($parsed_url['host']) ?
$parsed_url['host'] : '';
$port = isset($parsed_url['port']) ? ':' .
$parsed_url['port'] : '';
$user = isset($parsed_url['user']) ?
$parsed_url['user'] : '';
$pass = isset($parsed_url['pass']) ? ':' .
$parsed_url['pass'] : '';
$pass = ($user || $pass) ? "{$pass}@" : '';
$path = isset($parsed_url['path']) ?
$parsed_url['path'] : '';
$query = isset($parsed_url['query']) ? '?' .
$parsed_url['query'] : '';
$fragment = isset($parsed_url['fragment']) ?
'#' . $parsed_url['fragment'] : '';
$scheme = $host && !$scheme ? '//' : $scheme;
return
"{$scheme}{$user}{$pass}{$host}{$port}{$path}{$query}{$fragment}";
}
/**
* Build query string from variables.
*
* @param array $vars
* @return null|string
*/
public static function buildQuery(array $vars)
{
$list = [];
foreach ($vars as $key => $var) {
$list[] = $key . '=' . rawurlencode($var);
}
return $list ? implode('&', $list) : null;
}
}
PK���[�H��AA!Component/Whoops/SystemFacade.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Component\Whoops;
class SystemFacade extends \Whoops\Util\SystemFacade
{
protected $registeredPatterns;
protected $whoopsErrorHandler;
protected $whoopsExceptionHandler;
protected $whoopsShutdownHandler;
protected $platformExceptionHandler;
/**
* @param array|string $patterns List or a single regex pattern to
match for silencing errors in particular files.
*/
public function __construct($patterns = [])
{
$this->registeredPatterns = array_map(
function ($pattern) {
return["pattern" => $pattern];
},
(array) $patterns
);
}
/**
* @param callable $handler
* @param int|string $types
*
* @return callable|null
*/
public function setErrorHandler(callable $handler, $types =
'use-php-defaults')
{
// Workaround for PHP 5.5
if ($types === 'use-php-defaults') {
$types = E_ALL | E_STRICT;
}
$this->whoopsErrorHandler = $handler;
return parent::setErrorHandler([$this, 'handleError'],
$types);
}
/**
* @param callable $function
*
* @return void
*/
public function registerShutdownFunction(callable $function)
{
$this->whoopsShutdownHandler = $function;
register_shutdown_function([$this, 'handleShutdown']);
}
/**
* @param callable $handler
*
* @return callable|null
*/
public function setExceptionHandler(callable $handler)
{
$this->whoopsExceptionHandler = $handler;
$this->platformExceptionHandler =
parent::setExceptionHandler([$this, 'handleException']);
return $this->platformExceptionHandler;
}
/**
* Converts generic PHP errors to \ErrorException instances, before
passing them off to be handled.
*
* This method MUST be compatible with set_error_handler.
*
* @param int $level
* @param string $message
* @param string $file
* @param int $line
*
* @return bool
* @throws \ErrorException
*/
public function handleError($level, $message, $file = null, $line =
null)
{
$handler = $this->whoopsErrorHandler;
if (!$this->registeredPatterns) {
// Just forward to parent function is there aren't no
registered patterns.
return $handler($level, $message, $file, $line);
}
// If there are registered patterns, only handle errors if error
matches one of the patterns.
if ($level & error_reporting()) {
foreach ($this->registeredPatterns as $entry) {
$pathMatches = $file &&
preg_match($entry["pattern"], $file);
if ($pathMatches) {
return $handler($level, $message, $file, $line);
}
}
}
// Propagate error to the next handler, allows error_get_last() to
work on silenced errors.
return false;
}
/**
* Handles an exception, ultimately generating a Whoops error page.
*
* @param \Throwable $exception
* @return void
*/
public function handleException($exception)
{
$handler = $this->whoopsExceptionHandler;
// If there are registered patterns, only handle errors if error
matches one of the patterns.
if ($this->registeredPatterns) {
foreach ($this->registeredPatterns as $entry) {
$file = $exception->getFile();
$pathMatches = $file &&
preg_match($entry["pattern"], $file);
if ($pathMatches) {
$handler($exception);
return;
}
}
}
// Propagate error to the next handler.
if ($this->platformExceptionHandler) {
call_user_func_array($this->platformExceptionHandler,
[&$exception]);
}
}
/**
* Special case to deal with Fatal errors and the like.
*/
public function handleShutdown()
{
$handler = $this->whoopsShutdownHandler;
$error = $this->getLastError();
// Ignore core warnings and errors.
if ($error && !($error['type'] &
(E_CORE_WARNING | E_CORE_ERROR))) {
$handler();
}
}
}
PK���[JH��CCFramework/Assignments.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Framework;
use Gantry\Component\Assignments\AbstractAssignments;
use Gantry\Joomla\CacheHelper;
use Gantry\Joomla\StyleHelper;
use Joomla\Utilities\ArrayHelper;
class Assignments extends AbstractAssignments
{
protected $platform = 'Joomla';
/**
* Load all assignments.
*
* @return array
*/
public function loadAssignments()
{
$app = \JFactory::getApplication();
if (!$app->isSite()) {
return [];
}
// Get current template, style id and rules.
$template = $app->getTemplate();
$active = $app->getMenu()->getActive();
if ($active) {
$style = (int) $active->template_style_id;
$rules = [$active->menutype => [$active->id =>
true]];
} else {
$style = 0;
$rules = [];
}
// Load saved assignments.
$assignments = parent::loadAssignments();
// Add missing template styles from Joomla.
$styles = StyleHelper::loadStyles($template);
$assignments += array_fill_keys(array_keys($styles), []);
foreach ($assignments as $id => &$assignment) {
// Add current menu item if it has been assigned to the style.
$assignment['menu'] = $style === $id ? $rules : [];
// Always add the current template style.
$assignment['style'] = ['id' => [$id
=> true]];
}
return $assignments;
}
/**
* Save assignments for the configuration.
*
* @param array $data
*/
public function save(array $data)
{
$data += ['assignment' => 0, 'menu' =>
[]];
// Joomla stores language and menu assignments by its own.
$this->saveAssignment($data['assignment']);
$this->saveMenu($data['menu']);
unset($data['assignment'], $data['menu'],
$data['style']);
// Continue saving rest of the assignments.
parent::save($data);
}
public function types()
{
return ['menu', 'style'];
}
public function saveMenu($data)
{
$active = [];
foreach ($data as $menutype => $items) {
$active += array_filter($items, function($value) {return $value
> 0; });
}
$active = array_keys($active);
// Detect disabled template.
$extension = \JTable::getInstance('Extension');
$template = Gantry::instance()['theme.name'];
if ($extension->load(array('enabled' => 0,
'type' => 'template', 'element' =>
$template, 'client_id' => 0))) {
throw new
\RuntimeException(\JText::_('COM_TEMPLATES_ERROR_SAVE_DISABLED_TEMPLATE'));
}
\JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_templates/tables');
$style = \JTable::getInstance('Style',
'TemplatesTable');
if (!$style->load($this->configuration) ||
$style->client_id != 0) {
throw new \RuntimeException('Template style does not
exist');
}
$user = \JFactory::getUser();
$n = 0;
if ($user->authorise('core.edit',
'com_menus')) {
$db = \JFactory::getDbo();
$user = \JFactory::getUser();
if (!empty($active)) {
ArrayHelper::toInteger($active);
// Update the mapping for menu items that this style IS
assigned to.
$query = $db->getQuery(true)
->update('#__menu')
->set('template_style_id = ' . (int)
$style->id)
->where('id IN (' . implode(',',
$active) . ')')
->where('template_style_id != ' . (int)
$style->id)
->where('checked_out IN (0,' . (int)
$user->id . ')');
$db->setQuery($query);
$db->execute();
$n += $db->getAffectedRows();
}
// Remove style mappings for menu items this style is NOT
assigned to.
// If unassigned then all existing maps will be removed.
$query = $db->getQuery(true)
->update('#__menu')
->set('template_style_id = 0');
if (!empty($active)) {
$query->where('id NOT IN (' .
implode(',', $active) . ')');
}
$query->where('template_style_id = ' . (int)
$style->id)
->where('checked_out IN (0,' . (int)
$user->id . ')');
$db->setQuery($query);
$db->execute();
$n += $db->getAffectedRows();
}
// Clean the cache.
CacheHelper::cleanTemplates();
return ($n > 0);
}
public function getAssignment()
{
$style = StyleHelper::getStyle($this->configuration);
return $style->home;
}
public function saveAssignment($value)
{
$options = $this->assignmentOptions();
if (!isset($options[$value])) {
throw new \RuntimeException('Invalid value for default
assignment!', 400);
}
$style = StyleHelper::getStyle($this->configuration);
$style->home = $value;
if (!$style->check() || !$style->store()) {
throw new \RuntimeException($style->getError());
}
// Clean the cache.
CacheHelper::cleanTemplates();
}
public function assignmentOptions()
{
if ((string)(int) $this->configuration !== (string)
$this->configuration) {
return [];
}
$languages = \JHtml::_('contentlanguage.existing');
$options = ['- Make Default -', 'All
Languages'];
foreach ($languages as $language) {
$options[$language->value] = $language->text;
}
return $options;
}
}
PK���[�����$�$Framework/Atoms.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework;
use Gantry\Component\Config\BlueprintForm;
use Gantry\Component\Config\Config;
use Gantry\Component\File\CompiledYamlFile;
use RocketTheme\Toolbox\ArrayTraits\ArrayAccess;
use RocketTheme\Toolbox\ArrayTraits\Export;
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
use RocketTheme\Toolbox\ArrayTraits\Iterator;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Atoms implements \ArrayAccess, \Iterator, ExportInterface
{
use ArrayAccess, Iterator, Export;
/**
* @var string
*/
protected $name;
/**
* @var array
*/
protected $items;
/**
* @var array
*/
protected $ids;
/**
* @var array|static[]
*/
protected static $instances;
protected $inherit = false;
/**
* @param string $outline
* @return static
*/
public static function instance($outline)
{
if (!isset(static::$instances[$outline])) {
$file =
CompiledYamlFile::instance("gantry-theme://config/{$outline}/page/head.yaml");
$head = $file->content();
static::$instances[$outline] = new
static(isset($head['atoms']) ? $head['atoms'] : [],
$outline);
$file->free();
static::$instances[$outline]->init();
}
return static::$instances[$outline];
}
/**
* Atoms constructor.
* @param array $atoms
* @param string $name
*/
public function __construct(array $atoms = [], $name = null)
{
$this->name = $name;
$this->items = array_filter($atoms);
$this->inherit =
file_exists('gantry-admin://blueprints/layout/inheritance/atom.yaml');
foreach ($this->items as &$item) {
if (!empty($item['id'])) {
$this->ids[$item['id']] = $item;
}
}
}
public function init()
{
foreach ($this->items as &$item) {
if (!empty($item['inherit']['outline'])
&& !empty($item['inherit']['atom'])) {
$inherited =
static::instance($item['inherit']['outline']);
$test =
$inherited->id($item['inherit']['atom']);
if (isset($test['attributes'])) {
$item['attributes'] =
$test['attributes'];
} else {
unset($item['inherit']);
}
}
}
return $this;
}
/**
* @return $this
*/
public function update()
{
foreach ($this->items as &$item) {
if (empty($item['id'])) {
$item['id'] = $this->createId($item);
}
if (!empty($item['inherit']['outline'])
&& !empty($item['inherit']['atom'])) {
unset($item['attributes']);
} else {
unset($item['inherit']);
}
}
return $this;
}
/**
* @param string $outline
* @return $this
*/
public function inheritAll($outline)
{
foreach ($this->items as &$item) {
if (!empty($item['id'])) {
$item['inherit'] = [
'outline' => $outline,
'atom' => $item['id'],
'include' => ['attributes']
];
}
}
return $this;
}
/**
* @param string $old
* @param string $new
* @param array $ids
* @return $this
*/
public function updateInheritance($old, $new = null, $ids = null)
{
$this->init();
foreach ($this->items as &$item) {
if (!empty($item['inherit']['outline'])
&& $item['inherit']['outline'] == $old
&& isset($item['inherit']['atom'])) {
if ($new && ($ids === null ||
isset($ids[$item['inherit']['atom']]))) {
$item['inherit']['outline'] = $new;
} else {
unset($item['inherit']);
}
}
}
return $this;
}
public function save()
{
if ($this->name) {
/** @var UniformResourceLocator $locator */
$locator = Gantry::instance()['locator'];
$loadPath =
$locator->findResource("gantry-theme://config/{$this->name}/page/head.yaml");
$savePath =
$locator->findResource("gantry-theme://config/{$this->name}/page/head.yaml",
true, true);
if ($loadPath && $savePath) {
$file = CompiledYamlFile::instance($loadPath);
$head = $file->content();
$head['atoms'] =
$this->update()->toArray();
$file->free();
$file = CompiledYamlFile::instance($savePath);
$file->save($head);
$file->free();
}
}
}
/**
* @param string $id
* @return array
*/
public function id($id)
{
return isset($this->ids[$id]) ? $this->ids[$id] : [];
}
/**
* @param string $type
* @return array
*/
public function type($type)
{
$list = [];
foreach ($this->items as $item) {
if ($item['type'] === $type) {
$list[] = $item;
}
}
return $list;
}
/**
* @param string $type
* @param array $data
* @return Config
*/
public function createAtom($type, array $data = [])
{
$self = $this;
$callable = function () use ($self, $type) {
return $self->getBlueprint($type);
};
// Create configuration from the data.
$item = new Config($data, $callable);
$item->def('id', null);
$item->def('type', $type);
if (!isset($item['title'])) {
$item->def('title',
$item->blueprint()->get('name'));
}
$item->def('attributes', []);
$item->def('inherit', []);
return $item;
}
/**
* @param string $type
* @return BlueprintForm
*/
public function getBlueprint($type)
{
$blueprint = BlueprintForm::instance($type,
'gantry-blueprints://particles');
if ($this->inherit) {
$blueprint->set('form/fields/_inherit',
['type' => 'gantry.inherit']);
}
return $blueprint;
}
/**
* @param string $type
* @param string $id
* @param bool $force
* @return BlueprintForm|null
*/
public function getInheritanceBlueprint($type, $id = null, $force =
false)
{
if (!$this->inherit) {
return null;
}
$inheriting = $id ? $this->getInheritingOutlines($id) : [];
$list = $this->getOutlines($type, false);
if ($force || (empty($inheriting) && $list)) {
$inheritance =
BlueprintForm::instance('layout/inheritance/atom.yaml',
'gantry-admin://blueprints');
$inheritance->set('form/fields/outline/filter',
array_keys($list));
$inheritance->set('form/fields/atom/atom', $type);
} elseif (!empty($inheriting)) {
// Already inherited by other outlines.
$inheritance =
BlueprintForm::instance('layout/inheritance/messages/inherited.yaml',
'gantry-admin://blueprints');
$inheritance->set(
'form/fields/_note/content',
sprintf($inheritance->get('form/fields/_note/content'),
'atom', ' <ul><li>' .
implode('</li> <li>', $inheriting) .
'</li></ul>')
);
} elseif ($this->name === 'default') {
// Base outline.
$inheritance =
BlueprintForm::instance('layout/inheritance/messages/default.yaml',
'gantry-admin://blueprints');
} else {
// Nothing to inherit from.
$inheritance =
BlueprintForm::instance('layout/inheritance/messages/empty.yaml',
'gantry-admin://blueprints');
}
return $inheritance;
}
/**
* @param string $id
* @return array
*/
public function getInheritingOutlines($id = null)
{
/** @var Outlines $outlines */
$outlines = Gantry::instance()['outlines'];
return $outlines->getInheritingOutlinesWithAtom($this->name,
$id);
}
/**
* @param string $type
* @param bool $includeInherited
* @return array
*/
public function getOutlines($type, $includeInherited = true)
{
if ($this->name !== 'default') {
/** @var Outlines $outlines */
$outlines = Gantry::instance()['outlines'];
$list = $outlines->getOutlinesWithAtom($type,
$includeInherited);
unset($list[$this->name]);
} else {
$list = [];
}
return $list;
}
/**
* @param array $item
* @return string
*/
protected function createId(array &$item)
{
$type = $item['type'];
while ($num = rand(1000, 9999)) {
if (!isset($this->ids["{$type}-{$num}"])) {
break;
}
}
$id = "{$type}-{$num}";
$this->ids[$id] = $item;
return $id;
}
}
PK���["��{�$�$Framework/Base/Gantry.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework\Base;
use Gantry\Component\Config\Config;
use Gantry\Component\System\Messages;
use Gantry\Framework\Document;
use Gantry\Framework\Menu;
use Gantry\Framework\Outlines;
use Gantry\Framework\Page;
use Gantry\Framework\Platform;
use Gantry\Framework\Positions;
use Gantry\Framework\Request;
use Gantry\Framework\Services\ConfigServiceProvider;
use Gantry\Framework\Services\StreamsServiceProvider;
use Gantry\Framework\Site;
use Gantry\Framework\Translator;
use RocketTheme\Toolbox\DI\Container;
use RocketTheme\Toolbox\Event\Event;
use RocketTheme\Toolbox\Event\EventDispatcher;
abstract class Gantry extends Container
{
/**
* @var static
*/
protected static $instance;
protected $wrapper;
public static function instance()
{
if (!self::$instance) {
self::$instance = static::init();
if (!defined('GANTRY5_DEBUG')) {
define('GANTRY5_DEBUG',
self::$instance->debug());
}
}
return self::$instance;
}
public static function restart()
{
self::$instance = null;
return static::instance();
}
/**
* Returns true if debug mode has been enabled.
*
* @return boolean
*/
public function debug()
{
return $this['global']->get('debug', false);
}
/**
* Returns true if we are in administration.
*
* @return boolean
*/
public function admin()
{
return defined('GANTRYADMIN_PATH');
}
/**
* @return string
*/
public function siteUrl()
{
$gantry = Gantry::instance();
return $gantry['document']->siteUrl();
}
/**
* @param string $location
* @return array
*/
public function styles($location = 'head')
{
return $this['document']->getStyles($location);
}
/**
* @param string $location
* @return array
*/
public function scripts($location = 'head')
{
return $this['document']->getScripts($location);
}
/**
* Load Javascript framework / extension in platform independent way.
*
* @param string $framework
* @return bool
*/
public function load($framework)
{
return $this['document']->addFramework($framework);
}
/**
* Lock the variable against modification and return the value.
*
* @param string $id
* @return mixed
*/
public function lock($id)
{
$value = $this[$id];
try {
// Create a dummy service.
$this[$id] = function () use ($value) {
return $value;
};
} catch (\RuntimeException $e) {
// Services are already locked, so ignore the error.
}
// Lock the service and return value.
return $this[$id];
}
/**
* Fires an event with optional parameters.
*
* @param string $eventName
* @param Event $event
* @return Event
*/
public function fireEvent($eventName, Event $event = null)
{
/** @var EventDispatcher $events */
$events = $this['events'];
return $events->dispatch($eventName, $event);
}
public function route($path)
{
$routes = $this->offsetGet('routes');
$route = isset($routes[$path]) ? $routes[$path] : $routes[1];
if (!$route) {
// TODO: need to implement back to root in Prime..
return $this->offsetGet('base_url');
}
$path = implode('/', array_filter(func_get_args(),
function($var) { return isset($var) && $var !== ''; }));
// rawurlencode() the whole path, but keep the slashes.
$path = preg_replace(['|%2F|', '|%25|'],
['/', '%'], rawurlencode($path));
return preg_replace('|/+|', '/', '/'
. $this->offsetGet('base_url') . sprintf($route, $path));
}
public function authorize($action, $id = null)
{
return $this['platform']->authorize($action, $id);
}
public function wrapper($value = null)
{
if ($value !== null ) {
$this->wrapper = $value;
}
return $this->wrapper;
}
protected static function init()
{
/** @var Gantry $instance */
$instance = new static();
if (GANTRY_DEBUGGER) {
$instance['debugger'] = \Gantry\Debugger::instance();
}
$instance['loader'] = \Gantry5\Loader::get();
$instance->register(new ConfigServiceProvider);
$instance->register(new StreamsServiceProvider);
$instance['request'] = function () {
return new Request;
};
$instance['events'] = function () {
return new EventDispatcher;
};
$instance['platform'] = function ($c) {
return new Platform($c);
};
$instance['translator'] = function () {
return new Translator;
};
$instance['site'] = function () {
return new Site;
};
$instance['menu'] = function () {
return new Menu;
};
$instance['messages'] = function () {
return new Messages;
};
$instance['page'] = function ($c) {
return new Page($c);
};
$instance['document'] = function () {
return new Document;
};
// Make sure that nobody modifies the original collection by making
it a factory.
$instance['outlines'] = $instance->factory(function
($c) {
static $collection;
if (!$collection) {
$collection = (new Outlines($c))->load();
}
return $collection->copy();
});
// @deprecated 5.3
$instance['configurations'] =
$instance->factory(function ($c) {
GANTRY_DEBUGGER &&
\Gantry\Debugger::addMessage("Depredated call:
gantry.configurations");
static $collection;
if (!$collection) {
$collection = (new Outlines($c))->load();
}
return $collection->copy();
});
$instance['positions'] = $instance->factory(function
($c) {
static $collection;
if (!$collection) {
$collection = (new Positions($c))->load();
}
return $collection->copy();
});
$instance['global'] = function ($c) {
$data = $c->loadGlobal() + [
'debug' => false,
'production' => true,
'use_media_folder' => false,
'asset_timestamps' => true,
'asset_timestamps_period' => 7,
'compile_yaml' => true,
'compile_twig' => true,
'offline_message' => ''
];
return new Config($data);
};
return $instance;
}
/**
* Check if Gantry is compatible with your theme / extension.
*
* This function can be used to make sure that user has installed
Gantry version
* that has been tested to work with your extension. All existing
functions should
* be backwards compatible, but each release can add some new
functionality, which
* you may want to use.
*
* <code>
* if ($gantry->isCompatible('5.0.1')) {
* // You can do it in the new way.
* } else {
* // Revert to the old way to display an error message.
* }
* </code>
*
* @param string $version Minimum required version.
*
* @return boolean Yes, if it is safe to use Gantry Framework.
*/
public function isCompatible($version)
{
// If requested version is smaller than 5.0-rc, it's not
compatible.
if (version_compare($version, '5.0-rc',
'<')) {
return false;
}
// Development version support.
if ($version === '5.3' || static::isDev()) {
return true;
}
// Check if future version is needed.
if (version_compare($version, GANTRY5_VERSION, '>')) {
return false;
}
return true;
}
/**
* Check if Gantry is running from a Git repository or is a CI build.
*
* Developers tend to do their work directly in the Git repositories
instead of
* creating and installing new builds after every change. This function
can be
* used to check the condition and make sure we do not break users
repository
* by replacing files during upgrade.
*
* @return boolean True if Git repository or CI build is detected.
*/
public function isDev()
{
if ('@version@' == GANTRY5_VERSION) {
return true;
}
if ('dev-' === substr(GANTRY5_VERSION, 0, 4)) {
return true;
}
return false;
}
/**
* @return array
*/
protected function loadGlobal()
{
return [];
}
}
PK���[B�s�MMFramework/Base/Page.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework\Base;
abstract class Page
{
protected $container;
protected $config;
public function __construct($container)
{
$this->container = $container;
$this->config = $container['config'];
}
public function doctype()
{
return $this->config->get('page.doctype',
'html');
}
abstract public function url(array $args = []);
public function preset()
{
/** @var Theme $theme */
$theme = $this->container['theme'];
return 'g-' . preg_replace('/[^a-z0-9-]/',
'', $theme->type());
}
public function htmlAttributes()
{
return
$this->getAttributes($this->config->get('page.html'));
}
public function bodyAttributes($attributes = [])
{
return
$this->getAttributes($this->config->get('page.body.attribs'),
$attributes);
}
protected function getAttributes($params, $extra = [])
{
$params = array_merge_recursive($params, $extra);
$list = [];
foreach ($params as $param => $value) {
if (!$value) { continue; }
if (!is_array($value) || !count(array_filter($value,
'is_array'))) {
$value = array_filter(array_unique((array) $value));
$list[] = $param . '="' . implode('
', $value) . '"';
} else {
$values = new \RecursiveIteratorIterator(new
\RecursiveArrayIterator($value));
foreach ($values as $iparam => $ivalue) {
$ivalue = array_filter(array_unique((array) $ivalue));
$list[] = $iparam . '="' .
implode(' ', $ivalue) . '"';
}
}
}
return $list ? ' ' . implode(' ', $list) :
'';
}
}
PK���[qyX~��Framework/Base/Platform.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework\Base;
use Gantry\Component\Filesystem\Folder;
use RocketTheme\Toolbox\ArrayTraits\Export;
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccess;
use RocketTheme\Toolbox\DI\Container;
/**
* The Platform Configuration class contains configuration information.
*
* @author RocketTheme
* @license MIT
*/
abstract class Platform
{
use NestedArrayAccess, Export;
protected $name;
protected $features = [];
protected $settings_key;
protected $items;
protected $container;
public function __construct(Container $container)
{
$this->container = $container;
//Make sure that cache folder exists, otherwise it will be removed
from the lookup.
$cachePath = $this->getCachePath();
Folder::create($cachePath);
$this->items = [
'streams' => [
// Cached files.
'gantry-cache' => [
'type' => 'Stream',
'force' => true,
'prefixes' => ['' =>
[$cachePath]]
],
// Container for all frontend themes.
'gantry-themes' => [
'type' => 'ReadOnlyStream',
'prefixes' => $this->getThemesPaths()
],
// Selected frontend theme.
'gantry-theme' => [
'type' => 'ReadOnlyStream',
'prefixes' => $this->getThemePaths()
],
// System defined media files.
'gantry-assets' => [
'type' => 'ReadOnlyStream',
'prefixes' => $this->getAssetsPaths()
],
// User defined media files.
'gantry-media' => [
'type' => 'ReadOnlyStream',
'prefixes' => $this->getMediaPaths()
],
// Container for all Gantry engines.
'gantry-engines' => [
'type' => 'ReadOnlyStream',
'prefixes' => $this->getEnginesPaths()
],
// Gantry engine used to render the selected theme.
'gantry-engine' => [
'type' => 'ReadOnlyStream',
'prefixes' => $this->getEnginePaths()
],
// Layout definitions for the blueprints.
'gantry-layouts' => [
'type' => 'ReadOnlyStream',
'prefixes' => ['' =>
['gantry-theme://layouts', 'gantry-engine://layouts']]
],
// Gantry particles.
'gantry-particles' => [
'type' => 'ReadOnlyStream',
'prefixes' => ['' =>
['gantry-theme://particles',
'gantry-engine://particles']]
],
// Gantry administration.
'gantry-admin' => [
'type' => 'ReadOnlyStream',
'prefixes' => []
],
// Blueprints for the configuration.
'gantry-blueprints' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' =>
['gantry-theme://blueprints',
'gantry-engine://blueprints'],
'particles' =>
['gantry-particles://']
]
],
// Configuration from the selected theme.
'gantry-config' => [
'type' => 'ReadOnlyStream',
'prefixes' => ['' =>
['gantry-theme://config']]
]
]
];
}
abstract public function getCachePath();
abstract public function getThemesPaths();
abstract public function getAssetsPaths();
abstract public function getMediaPaths();
public function init()
{
return $this;
}
public function has($feature)
{
return !empty($this->features[$feature]);
}
public function getThemePaths()
{
return ['' => []];
}
public function getEnginePaths($name = 'nucleus')
{
return ['' => ['gantry-theme://engine',
"gantry-engines://{$name}"]];
}
public function getEnginesPaths()
{
return ['' => []];
}
public function errorHandlerPaths()
{
return [];
}
/**
* Get preview url for individual theme.
*
* @param string $theme
* @return string|null
*/
abstract public function getThemePreviewUrl($theme);
/**
* Get administrator url for individual theme.
*
* @param string $theme
* @return string|null
*/
abstract public function getThemeAdminUrl($theme);
public function settings()
{
return null;
}
public function settings_key()
{
return $this->settings_key;
}
public function listModules()
{
return false;
}
public function getName()
{
return $this->name;
}
public function getEditor($name, $content = '', $width =
null, $height = null)
{
return null;
}
public function filter($text)
{
return $text;
}
public function finalize()
{
$gantry = Gantry::instance();
$gantry['document']->registerAssets();
}
public function call()
{
$args = func_get_args();
$callable = array_shift($args);
return is_callable($callable) ? call_user_func_array($callable,
$args) : null;
}
public function authorize($action)
{
return true;
}
/**
* @param array|string $dependencies
* @return bool|null
* @since 5.4.3
*/
public function checkDependencies($dependencies)
{
if (is_string($dependencies) && $dependencies !==
$this->name) {
return false;
}
if (isset($dependencies['platform'])) {
if (is_string($dependencies['platform']) &&
$dependencies['platform'] !== $this->name) {
return false;
}
if
(!isset($dependencies['platform'][$this->name])) {
return false;
}
}
return true;
}
}
PK���[3�S��Framework/Base/Site.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework\Base;
class Site
{
}
PK���[�1L�GGFramework/Base/Theme.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework\Base;
use Gantry\Component\Theme\AbstractTheme;
use Gantry\Component\Theme\ThemeTrait;
/**
* @deprecated 5.1.5
*/
abstract class Theme extends AbstractTheme
{
use ThemeTrait;
}
PK���[�.��Framework/Configurations.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework;
/**
* @deprecated 5.1.1
*/
class Configurations extends Outlines
{
}
PK���[4y,ccFramework/Document.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Framework;
use Gantry\Component\Content\Document\HtmlDocument;
class Document extends HtmlDocument
{
protected static $availableFrameworks = [
'jquery' => 'registerJquery',
'jquery.framework' => 'registerJquery',
'jquery.ui.core' => 'registerJqueryUiCore',
'jquery.ui.sortable' =>
'registerJqueryUiSortable',
'bootstrap.2' => 'registerBootstrap2',
'mootools' => 'registerMootools',
'mootools.framework' => 'registerMootools',
'mootools.core' => 'registerMootools',
'mootools.more' => 'registerMootoolsMore',
'lightcase' => 'registerLightcase',
'lightcase.init' => 'registerLightcaseInit',
];
public static function registerAssets()
{
static::registerFrameworks();
static::registerStyles();
static::registerScripts();
}
/**
* NOTE: In PHP this function can be called either from Gantry DI
container or statically.
*
* @param bool $addDomain
* @return string
*/
public static function domain($addDomain = false)
{
if (!$addDomain) {
return '';
}
$absolute = \JUri::root(false);
$relative = \JUri::root(true);
return substr($absolute, 0, -strlen($relative));
}
public static function rootUri()
{
return rtrim(\JUri::root(true), '/') ?: '/';
}
public static function errorPage($new = null)
{
static $error = false;
if (isset($new)) {
$error = (bool) $new;
}
return $error;
}
protected static function registerStyles()
{
if (static::errorPage()) {
return;
}
$doc = \JFactory::getDocument();
$styles = static::$stack[0]->getStyles();
foreach ($styles as $style) {
switch ($style[':type']) {
case 'file':
$doc->addStyleSheet($style['href'],
$style['type'], $style['media'],
$style['element']);
break;
case 'inline':
$doc->addStyleDeclaration($style['content'],
$style['type']);
break;
}
}
}
protected static function registerScripts()
{
if (static::errorPage()) {
return;
}
$doc = \JFactory::getDocument();
$scripts = static::$stack[0]->getScripts();
foreach ($scripts as $script) {
switch ($script[':type']) {
case 'file':
$doc->addScript($script['src'],
$script['type'], $script['defer'],
$script['async']);
break;
case 'inline':
$doc->addScriptDeclaration($script['content'],
$script['type']);
break;
}
}
}
protected static function registerJquery()
{
if (!static::errorPage()) {
\JHtml::_('jquery.framework');
return;
}
// Workaround for error document type.
static::addHeaderTag(
[
'tag' => 'script',
'src' => \JUri::getInstance()->base(true) .
'/media/jui/js/jquery.min.js'
],
'head',
100
);
static::addHeaderTag(
[
'tag' => 'script',
'src' => \JUri::getInstance()->base(true) .
'/media/jui/js/jquery-noconflict.js'
],
'head',
100
);
static::addHeaderTag(
[
'tag' => 'script',
'src' => \JUri::getInstance()->base(true) .
'/media/jui/js/jquery-migrate.min.js'
],
'head',
100
);
}
protected static function registerJqueryUiCore()
{
if (!static::errorPage()) {
\JHtml::_('jquery.ui', ['core']);
return;
}
// Workaround for error document type.
static::registerJquery();
static::addHeaderTag(
[
'tag' => 'script',
'src' => \JUri::getInstance()->base(true) .
'/media/jui/js/jquery.ui.core.min.js'
],
'head',
100
);
}
protected static function registerJqueryUiSortable()
{
if (!static::errorPage()) {
\JHtml::_('jquery.ui', ['sortable']);
return;
}
// Workaround for error document type.
static::registerJqueryUiCore();
static::addHeaderTag(
[
'tag' => 'script',
'src' => \JUri::getInstance()->base(true) .
'/media/jui/js/jquery.ui.sortable.min.js'
],
'head',
100
);
}
protected static function registerBootstrap2()
{
Gantry::instance()['theme']->joomla(true);
if (!static::errorPage()) {
\JHtml::_('bootstrap.framework');
return;
}
// Workaround for error document type.
static::registerJquery();
static::addHeaderTag(
[
'tag' => 'script',
'src' => \JUri::getInstance()->base(true) .
'/media/jui/js/bootstrap.min.js'
],
'head',
100
);
}
protected static function registerMootools()
{
if (!static::errorPage()) {
\JHtml::_('behavior.framework');
return;
}
// Workaround for error document type.
static::addHeaderTag(
[
'tag' => 'script',
'src' => \JUri::getInstance()->base(true) .
'/media/system/js/mootools-core.js'
],
'head',
99
);
static::addHeaderTag(
[
'tag' => 'script',
'src' => \JUri::getInstance()->base(true) .
'/media/system/js/core.js'
],
'head',
99
);
}
protected static function registerMootoolsMore()
{
if (!static::errorPage()) {
\JHtml::_('behavior.framework', true);
return;
}
// Workaround for error document type.
static::registerMootools();
static::addHeaderTag(
[
'tag' => 'script',
'src' => \JUri::getInstance()->base(true) .
'/media/system/js/mootools-more.js'
],
'head',
99
);
}
/**
* Override to support index.php?Itemid=xxx.
*
* @param array $matches
* @return string
* @internal
*/
public static function linkHandler(array $matches)
{
$url = trim($matches[3]);
if (strpos($url, 'index.php?') !== 0) {
list($domain, $timestamp_age) = static::$urlFilterParams;
$url = static::url(trim($matches[3]), $domain, $timestamp_age);
}
return "{$matches[1]}{$matches[2]}=\"{$url}\"";
}
}
PK���[�NEFramework/Exception.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework;
class Exception extends \RuntimeException
{
protected $responseCodes = [
200 => '200 OK',
400 => '400 Bad Request',
401 => '401 Unauthorized',
403 => '403 Forbidden',
404 => '404 Not Found',
410 => '410 Gone',
500 => '500 Internal Server Error',
501 => '501 Not Implemented',
503 => '503 Service Temporarily Unavailable'
];
public function getResponseCode() {
return isset($this->responseCodes[$this->code]) ? (int)
$this->code : 500;
}
public function getResponseStatus() {
return $this->responseCodes[$this->getResponseCode()];
}
}
PK���[��(�+�+Framework/Exporter.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Framework;
use Gantry\Component\Layout\Layout;
use Gantry\Framework\Services\ConfigServiceProvider;
use Gantry\Joomla\Category\CategoryFinder;
use Gantry\Joomla\Content\ContentFinder;
use Gantry\Joomla\Module\ModuleFinder;
use Gantry\Joomla\StyleHelper;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Exporter
{
protected $files = [];
public function all()
{
$theme = Gantry::instance()['theme']->details();
return [
'export' => [
'gantry' => [
'version' => GANTRY5_VERSION !==
'@version@' ? GANTRY5_VERSION : 'GIT',
'format' => 1
],
'platform' => [
'name' => 'joomla',
'version' => JVERSION
],
'theme' => [
'name' =>
$theme->get('name'),
'title' =>
$theme->get('details.name'),
'version' =>
$theme->get('details.version'),
'date' =>
$theme->get('details.date'),
'author' =>
$theme->get('details.author'),
'copyright' =>
$theme->get('details.copyright'),
'license' =>
$theme->get('details.license'),
]
],
'outlines' => $this->outlines(),
'positions' => $this->positions(),
'menus' => $this->menus(),
'content' => $this->articles(),
'categories' => $this->categories(),
'files' => $this->files,
];
}
public function outlines()
{
$gantry = Gantry::instance();
$styles = StyleHelper::loadStyles($gantry['theme.name']);
$list = [
'default' => ['title' =>
'Default'],
'_error' => ['title' =>
'Error'],
'_offline' => ['title' =>
'Offline'],
'_body_only' => ['title' =>
'Body Only'],
];
$inheritance = [];
foreach ($styles as $style) {
$name = $base =
strtolower(trim(preg_replace('|[^a-z\d_-]+|ui', '_',
$style->title), '_'));
$i = 0;
while (isset($list[$name])) {
$i++;
$name = "{$base}-{$i}";
};
$inheritance[$style->id] = $name;
$list[$name] = [
'id' => (int) $style->id,
'title' => $style->title,
'home' => $style->home,
];
if (!$style->home) {
unset($list[$name]['home']);
}
}
foreach ($list as $name => &$style) {
$id = isset($style['id']) ? $style['id'] :
$name;
$config = ConfigServiceProvider::load($gantry, $id, false,
false);
// Update layout inheritance.
$layout = Layout::instance($id);
$layout->name = $name;
foreach ($inheritance as $from => $to) {
$layout->updateInheritance($from, $to);
}
$style['preset'] =
$layout->preset['name'];
$config['index'] = $layout->buildIndex();
$config['layout'] = $layout->export();
// Update atom inheritance.
$atoms = $config->get('page.head.atoms');
if (is_array($atoms)) {
$atoms = new Atoms($atoms);
foreach ($inheritance as $from => $to) {
$atoms->updateInheritance($from, $to);
}
$config->set('page.head.atoms',
$atoms->update()->toArray());
}
// Add assignments.
if (is_numeric($id)) {
$assignments = $this->getOutlineAssignments($id);
if ($assignments) {
$config->set('assignments',
$this->getOutlineAssignments($id));
}
}
$style['config'] = $config->toArray();
}
return $list;
}
public function positions($all = true)
{
$gantry = Gantry::instance();
$positions = $gantry['outlines']->positions();
$positions['debug'] = 'Debug';
$finder = new ModuleFinder();
if (!$all) {
$finder->particle();
}
$modules = $finder->find()->export();
$list = [];
foreach ($modules as $position => &$items) {
if (!isset($positions[$position])) {
continue;
}
foreach ($items as &$item) {
$func = 'module' .
$item['options']['type'];
if (method_exists($this, $func)) {
$item = $this->{$func}($item);
}
}
$list[$position] = [
'title' => $positions[$position],
'items' => $items,
];
}
return $list;
}
public function menus()
{
$gantry = Gantry::instance();
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select('id, menutype, title, description')
->from('#__menu_types');
$db->setQuery($query);
$menus = $db->loadObjectList('id');
$list = [];
foreach ($menus as $menu) {
$items =
$gantry['menu']->instance(['menu' =>
$menu->menutype])->items(false);
array_walk(
$items,
function (&$item) {
$item['id'] = (int) $item['id'];
if (in_array($item['type'],
['component', 'alias'])) {
$item['type'] =
"joomla.{$item['type']}";
}
unset($item['alias'],
$item['path'], $item['parent_id'],
$item['level']);
}
);
$list[$menu->menutype] = [
'id' => (int) $menu->id,
'title' => $menu->title,
'description' => $menu->description,
'items' => $items
];
}
return $list;
}
public function articles()
{
$finder = new ContentFinder();
$articles = $finder->limit(0)->find();
$list = [];
foreach ($articles as $article) {
$exported = $article->toArray();
// Convert images to use streams.
$exported['introtext'] =
$this->urlFilter($exported['introtext']);
$exported['fulltext'] =
$this->urlFilter($exported['fulltext']);
$list[$article->id . '-' . $article->alias] =
$exported;
}
return $list;
}
public function categories()
{
$finder = new CategoryFinder();
$categories = $finder->limit(0)->find();
$list = [];
foreach ($categories as $category) {
$list[$category->id] = $category->toArray();
}
return $list;
}
/**
* List all the rules available.
*
* @param string $configuration
* @return array
*/
public function getOutlineAssignments($configuration)
{
require_once JPATH_ADMINISTRATOR .
'/components/com_menus/helpers/menus.php';
$app = \JApplicationCms::getInstance('site');
$menu = $app->getMenu();
$data = \MenusHelper::getMenuLinks();
$items = [];
foreach ($data as $item) {
foreach ($item->links as $link) {
if ($link->template_style_id == $configuration) {
$items[$menu->getItem($link->value)->route] =
1;
}
}
}
if ($items) {
return ['page' => [$items]];
}
return [];
}
/**
* Filter stream URLs from HTML.
*
* @param string $html HTML input to be filtered.
* @return string Returns modified HTML.
*/
public function urlFilter($html)
{
// Tokenize all PRE and CODE tags to avoid modifying any
src|href|url in them
$tokens = [];
$html =
preg_replace_callback('#<(pre|code).*?>.*?<\\/\\1>#is',
function($matches) use (&$tokens) {
$token = uniqid('__g5_token');
$tokens['#' . $token . '#'] = $matches[0];
return $token;
}, $html);
$html =
preg_replace_callback('^(\s)(src|href)="(.*?)"^',
[$this, 'linkHandler'], $html);
$html = preg_replace_callback('^(\s)url\((.*?)\)^',
[$this, 'urlHandler'], $html);
$html = preg_replace(array_keys($tokens), array_values($tokens),
$html); // restore tokens
return $html;
}
public function url($url)
{
// Only process local urls.
if ($url === '' || $url[0] === '/' || $url[0]
=== '#') {
return $url;
}
/** @var UniformResourceLocator $locator */
$locator = Gantry::instance()['locator'];
// Handle URIs.
if (strpos($url, '://')) {
if ($locator->isStream($url)) {
// File is a stream, include it to files list.
list ($stream, $path) = explode('://', $url);
$this->files[$stream][$path] = $url;
}
return $url;
}
// Try to convert local paths to streams.
$paths = $locator->getPaths();
$found = false;
$stream = $path = '';
foreach ($paths as $stream => $prefixes) {
foreach ($prefixes as $prefix => $paths) {
foreach ($paths as $path) {
if (is_string($path) && strpos($url, $path) ===
0) {
$path = ($prefix ? "{$prefix}/" :
'') . substr($url, strlen($path) + 1);
$found = true;
break 3;
}
}
}
}
if ($found) {
$url = "{$stream}://{$path}";
$this->files[$stream][$path] = $url;
}
return $url;
}
/**
* @param array $matches
* @return string
* @internal
*/
public function linkHandler(array $matches)
{
$url = $this->url(trim($matches[3]));
return "{$matches[1]}{$matches[2]}=\"{$url}\"";
}
/**
* @param array $matches
* @return string
* @internal
*/
public function urlHandler(array $matches)
{
$url = $this->url(trim($matches[2], '"\''));
return "{$matches[1]}url({$url})";
}
protected function moduleMod_Custom(array $data)
{
// Convert to particle...
$data['type'] = 'particle';
$data['joomla'] = $data['options'];
$data['options'] = [
'type' => 'custom',
'attributes' => [
'enabled' =>
$data['joomla']['published'],
'html' =>
$this->urlFilter($data['joomla']['content']),
'filter' =>
$data['joomla']['params']['prepare_content']
]
];
unset($data['joomla']['content'],
$data['joomla']['params']['prepare_content']);
return $data;
}
}
PK���[��D���Framework/Gantry.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Framework;
class Gantry extends Base\Gantry
{
/**
* @return boolean
*/
public function debug()
{
return JDEBUG;
}
/**
* @return boolean
*/
public function admin()
{
return \JFactory::getApplication()->isAdmin();
}
/**
* @param string $location
* @param bool $force
* @return array
*/
public function styles($location = 'head', $force = false)
{
// Do not display head, Joomla will take care of it (most of the
time).
return (!$force && $location == 'head') ? [] :
parent::styles($location);
}
/**
* @param string $location
* @param bool $force
* @return array
*/
public function scripts($location = 'head', $force = false)
{
// Do not display head, Joomla will take care of it (most of the
time).
return (!$force && $location == 'head') ? [] :
parent::scripts($location);
}
/**
* @return array
*/
protected function loadGlobal()
{
$global = null;
// Trigger the event.
$dispatcher = \JEventDispatcher::getInstance();
$dispatcher->trigger('onGantryGlobalConfig',
['global' => &$global]);
return $global;
}
}
PK���["�����
Framework/Markdown/Parsedown.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework\Markdown;
class Parsedown extends \Parsedown
{
use ParsedownTrait;
/**
* Parsedown constructor.
*
* @param array $defaults
*/
public function __construct(array $defaults = null)
{
$this->init($defaults ?: []);
}
}
PK���[S�kn��%Framework/Markdown/ParsedownExtra.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework\Markdown;
class ParsedownExtra extends \ParsedownExtra
{
use ParsedownTrait;
/**
* ParsedownExtra constructor.
*
* @param array $defaults
* @throws \Exception
*/
public function __construct(array $defaults = null)
{
parent::__construct();
$this->init($defaults ?: []);
}
}
PK���[TD���%Framework/Markdown/ParsedownTrait.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework\Markdown;
use Gantry\Framework\Gantry;
trait ParsedownTrait
{
protected $special_chars;
protected $twig_link_regex =
'/\!*\[(?:.*)\]\((\{([\{%#])\s*(.*?)\s*(?:\2|\})\})\)/';
/**
* Initialization function to setup key variables needed by the
MarkdownGravLinkTrait
*
* @param $defaults
*/
protected function init(array $defaults)
{
$defaults += [
'auto_line_breaks' => false,
'auto_url_links' => false,
'escape_markup' => false,
'special_chars' => false
];
$this->BlockTypes['{'][] = 'TwigTag';
$this->special_chars = ['>' => 'gt',
'<' => 'lt', '"' =>
'quot'];
$this->setBreaksEnabled($defaults['auto_line_breaks']);
$this->setUrlsLinked($defaults['auto_url_links']);
$this->setMarkupEscaped($defaults['escape_markup']);
$this->setSpecialChars($defaults['special_chars']);
}
/**
* Setter for special chars
*
* @param $special_chars
*
* @return $this
*/
public function setSpecialChars($special_chars)
{
$this->special_chars = $special_chars;
return $this;
}
/**
* Ensure Twig tags are treated as block level items with no
<p></p> tags
*
* @param array $line
* @return array|null
*/
protected function blockTwigTag($line)
{
if (preg_match('/(?:{{|{%|{#)(.*)(?:}}|%}|#})/',
$line['body'], $matches)) {
return ['markup' => $line['body']];
}
return null;
}
protected function inlineSpecialCharacter($excerpt)
{
if ($excerpt['text'][0] === '&' &&
!preg_match('/^&#?\w+;/', $excerpt['text'])) {
return [
'markup' => '&',
'extent' => 1,
];
}
if (isset($this->special_chars[$excerpt['text'][0]]))
{
return [
'markup' => '&' .
$this->special_chars[$excerpt['text'][0]] . ';',
'extent' => 1,
];
}
return null;
}
protected function inlineImage($excerpt)
{
if (preg_match($this->twig_link_regex,
$excerpt['text'], $matches)) {
$excerpt['text'] = str_replace($matches[1],
'/', $excerpt['text']);
$excerpt = parent::inlineImage($excerpt);
$excerpt['element']['attributes']['src'] =
$matches[1];
$excerpt['extent'] = $excerpt['extent'] +
\strlen($matches[1]) - 1;
return $excerpt;
}
$excerpt['type'] = 'image';
$excerpt = parent::inlineImage($excerpt);
// if this is an image process it
if
(isset($excerpt['element']['attributes']['src']))
{
$gantry = Gantry::instance();
$excerpt['element']['attributes']['src'] =
$gantry['document']->url($excerpt['element']['attributes']['src']);
}
return $excerpt;
}
protected function inlineLink($excerpt)
{
if (!isset($excerpt['type'])) {
$excerpt['type'] = 'link';
}
// do some trickery to get around Parsedown requirement for valid
URL if its Twig in there
if (preg_match($this->twig_link_regex,
$excerpt['text'], $matches)) {
$excerpt['text'] = str_replace($matches[1],
'/', $excerpt['text']);
$excerpt = parent::inlineLink($excerpt);
$excerpt['element']['attributes']['href'] =
$matches[1];
$excerpt['extent'] = $excerpt['extent'] +
\strlen($matches[1]) - 1;
return $excerpt;
}
$excerpt = parent::inlineLink($excerpt);
// if this is a link
if
(isset($excerpt['element']['attributes']['href']))
{
$gantry = Gantry::instance();
$excerpt['element']['attributes']['href'] =
$gantry['document']->url($excerpt['element']['attributes']['href']);
}
return $excerpt;
}
}
PK���[��.@2@2Framework/Menu.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Framework;
use Gantry\Component\Config\Config;
use Gantry\Component\Gantry\GantryTrait;
use Gantry\Component\Menu\AbstractMenu;
use Gantry\Component\Menu\Item;
class Menu extends AbstractMenu
{
use GantryTrait;
/**
* @var \JApplicationCms
*/
protected $app;
/**
* @var \JMenu
*/
protected $menu;
public function __construct()
{
$this->app = \JApplicationCms::getInstance('site');
$lang = \JFactory::getLanguage();
$tag = \JLanguageMultilang::isEnabled() ? $lang->getTag() :
'*';
$this->menu = $this->app->getMenu();
$this->default = $this->menu->getDefault($tag);
$this->active = $this->menu->getActive();
}
public function init(&$params)
{
parent::init($params);
if (!empty($params['admin'])) {
/** @var \JTableMenuType $table */
$menuType = \JTable::getInstance('MenuType');
$menuType->load(['menutype' =>
$params['menu']]);
$config = $this->config();
$config->set('settings.title',
$menuType->title);
$config->set('settings.description',
$menuType->description);
}
}
/**
* Return list of menus.
*
* @return array
* @throws \RuntimeException
*/
public function getMenus()
{
static $items;
if ($items === null) {
require_once JPATH_ADMINISTRATOR .
'/components/com_menus/helpers/menus.php';
$items = (array) \MenusHelper::getMenuTypes();
}
return $items;
}
public function getGroupedItems()
{
$groups = array();
// Get the menu items.
$items = \MenusHelper::getMenuLinks();
// Build the groups arrays.
foreach ($items as $item) {
// Initialize the group.
$groups[$item->menutype] = [];
// Build the options array.
foreach ($item->links as $link) {
$groups[$item->menutype][$link->value] = [
'spacing' => str_repeat('
', max(0, $link->level-1)),
'label' => $link->text
];
}
}
return $groups;
}
/**
* Return default menu.
*
* @return string|null
*/
public function getDefaultMenuName()
{
return $this->default ? $this->default->menutype : null;
}
/**
* Returns true if the platform implements a Default menu.
*
* @return boolean
*/
public function hasDefaultMenu()
{
return true;
}
/**
* Return active menu.
*
* @return string|null
*/
public function getActiveMenuName()
{
return $this->active ? $this->active->menutype : null;
}
/**
* Returns true if the platform implements an Active menu.
*
* @return boolean
*/
public function hasActiveMenu()
{
return true;
}
/**
* @return string|null
*/
public function getCacheId()
{
if (!\JFactory::getUser()->guest) {
return null;
}
return $this->active ? $this->active->id : 0;
}
public function isActive($item)
{
$tree = $this->base->tree;
if (in_array($item->id, $tree)) {
return true;
} elseif ($item->type == 'alias') {
$aliasToId = $item->link_id;
if (count($tree) > 0 && $aliasToId ==
$tree[count($tree) - 1]) {
return (bool) $this->params['highlightAlias'];
} elseif (in_array($aliasToId, $tree)) {
return (bool)
$this->params['highlightParentAlias'];
}
}
return false;
}
public function isCurrent($item)
{
return $item->id == $this->active->id
|| ($item->type == 'alias' &&
$item->params->get('aliasoptions') ==
$this->active->id);
}
/**
* Get menu items from the platform.
*
* @param array $params
* @return array List of routes to the pages.
*/
protected function getItemsFromPlatform($params)
{
$attributes = ['menutype'];
$values = [$params['menu']];
// Items are already filtered by access and language, in admin we
need to work around that.
if (\JFactory::getApplication()->isAdmin()) {
$attributes[] = 'access';
$values[] = null;
$attributes[] = 'language';
$values[] = null;
}
return $this->menu->getItems($attributes, $values);
}
/**
* Get base menu item.
*
* If itemid is not specified or does not exist, return active menu
item.
* If there is no active menu item, fall back to home page for the
current language.
* If there is no home page, return null.
*
* @param int $itemid
*
* @return object|null
*/
protected function calcBase($itemid = null)
{
$menu = $this->app->getMenu();
// Get base menu item.
$base = $itemid ? $menu->getItem($itemid) : null;
if (!$base) {
// Use active menu item or fall back to default menu item.
$base = $this->active ?: $this->default;
}
// Return base menu item.
return $base;
}
/**
* Get a list of the menu items.
*
* Logic was originally copied from Joomla 3.4 mod_menu/helper.php
(joomla-cms/staging, 2014-11-12).
* We should keep the contents of the function similar to Joomla in
order to review it against any changes.
*
* @param array $params
* @param array $items
*/
public function getList(array $params, array $items)
{
// Get base menu item for this menu (defaults to active menu item).
$this->base = $this->calcBase($params['base']);
// Make sure that the menu item exists.
if (!$this->base &&
!\JFactory::getApplication()->isAdmin()) {
return;
}
$levels = \JFactory::getUser()->getAuthorisedViewLevels();
asort($levels);
// FIXME: need to create collection class to gather the sibling
data, otherwise caching cannot work.
//$key = 'gantry_menu_items.' . json_encode($params) .
'.' . json_encode($levels) . '.' .
$this->base->id;
//$cache = \JFactory::getCache('mod_menu', '');
//try {
// $this->items = $cache->get($key);
//} catch (\Exception $e) {
// $this->items = false;
//}
if (1) {
$tree = isset($this->base->tree) ?
$this->base->tree : [];
$start = $params['startLevel'];
$max = $params['maxLevels'];
$end = $max ? $start + $max - 1 : 0;
$menuItems = $this->getItemsFromPlatform($params);
$itemMap = [];
foreach ($items as $path => &$itemRef) {
if (isset($itemRef['id']) &&
is_numeric($itemRef['id'])) {
$itemRef['path'] = $path;
$itemMap[$itemRef['id']] = &$itemRef;
}
}
foreach ($menuItems as $menuItem) {
if (($start && $start > $menuItem->level)
|| ($end && $menuItem->level > $end)
|| ($start > 1 &&
!in_array($menuItem->tree[$start - 2], $tree))) {
continue;
}
// These params always come from Joomla and cannot be
overridden.
$itemParams = [
'id' => $menuItem->id,
'type' => $menuItem->type,
'alias' => $menuItem->alias,
'path' => $menuItem->route,
'link' => $menuItem->link,
'link_title' =>
$menuItem->params->get('menu-anchor_title', ''),
'rel' =>
$menuItem->params->get('menu-anchor_rel', ''),
'enabled' => (bool)
$menuItem->params->get('menu_show', 1),
];
// Rest of the items will come from saved configuration.
if (isset($itemMap[$menuItem->id])) {
// ID found, use it.
$itemParams += $itemMap[$menuItem->id];
// Store new path for the menu item into path map.
if ($itemParams['path'] !==
$itemMap[$menuItem->id]['path']) {
if (!$this->pathMap) {
$this->pathMap = new Config([]);
}
$this->pathMap->set(preg_replace('|/|u',
'/children/', $itemMap[$menuItem->id]['path']) .
'/path', $itemParams['path'], '/');
}
} elseif (isset($items[$menuItem->route])) {
// ID not found, try to use route.
$itemParams += $items[$menuItem->route];
}
// Get default target from Joomla.
switch ($menuItem->browserNav)
{
default:
case 0:
// Target window: Parent.
$target = '_self';
break;
case 1:
case 2:
// Target window: New with navigation.
$target = '_blank';
break;
}
// And if not available in configuration, default to
Joomla.
$itemParams += [
'title' => $menuItem->title,
'anchor_class' =>
$menuItem->params->get('menu-anchor_css', ''),
'image' =>
$menuItem->params->get('menu_image', ''),
'icon_only' =>
!$menuItem->params->get('menu_text', 1),
'target' => $target
];
$item = new Item($this, $menuItem->route, $itemParams);
$this->add($item);
$link = $item->link;
switch ($item->type) {
case 'separator':
case 'heading':
// These types have no link.
$link = null;
break;
case 'url':
if ((strpos($item->link, 'index.php?')
=== 0) && (strpos($item->link, 'Itemid=') === false))
{
// If this is an internal Joomla link, ensure
the Itemid is set.
$link = $item->link .
'&Itemid=' . $item->id;
}
break;
case 'alias':
// If this is an alias use the item id stored in
the parameters to make the link.
$link = 'index.php?Itemid=' .
$menuItem->params->get('aliasoptions', 0);
break;
default:
$app = $this->app;
$router = $app::getRouter();
if ($router->getMode() == JROUTER_MODE_SEF) {
$link = 'index.php?Itemid=' .
$item->id;
if
(isset($menuItem->query['format']) &&
$app->get('sef_suffix')) {
$link .= '&format=' .
$menuItem->query['format'];
}
} else {
$link .= '&Itemid=' .
$item->id;
}
break;
}
if (!$link) {
$item->url(false);
} elseif (strcasecmp(substr($link, 0, 4), 'http')
&& (strpos($link, 'index.php?') !== false)) {
$item->url(\JRoute::_($link, false,
$menuItem->params->get('secure')));
} else {
$item->url(\JRoute::_($link, false));
}
if ($item->type == 'url') {
// Moved from modules/mod_menu/tmpl/default_url.php,
not sure why Joomla had application logic in there.
// Keep compatibility to Joomla menu module, but we
need non-encoded version of the url.
$item->url(
htmlspecialchars_decode(\JFilterOutput::ampReplace(htmlspecialchars($item->link,
ENT_COMPAT|ENT_SUBSTITUTE, 'UTF-8')))
);
}
}
// FIXME: need to create collection class to gather the sibling
data, otherwise caching cannot work.
// $cache->store($this->items, $key);
}
}
}
PK���[�~���!�!Framework/Outlines.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Framework;
use Gantry\Admin\ThemeList;
use Gantry\Component\Filesystem\Folder;
use Gantry\Component\Outline\OutlineCollection;
use Gantry\Joomla\StyleHelper;
use Gantry\Joomla\TemplateInstaller;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Outlines extends OutlineCollection
{
protected $createId;
public function preset($id)
{
if (is_numeric($id)) {
$style = StyleHelper::getStyle($id);
$params = json_decode($style->params, true);
$id = isset($params['preset']) ?
$params['preset'] : 'default';
}
return $id;
}
public function current($template = null)
{
if (!is_object($template)) {
// Get the template style.
$template = \JFactory::getApplication()->getTemplate(true);
}
$preset = $template->params->get('preset',
'default');
$outline = $template->params->get('configuration',
!empty($template->id) ? $template->id : null);
GANTRY_DEBUGGER &&
\Gantry\Debugger::addMessage('Template Style:') &&
\Gantry\Debugger::addMessage($template);
if (JDEBUG && !$outline) {
static $shown = false;
if (!$shown) {
$shown = true;
\JFactory::getApplication()->enqueueMessage('[DEBUG]
JApplicationSite::getTemplate() was overridden with no specified Gantry 5
outline.', 'notice');
}
}
/** @var UniformResourceLocator $locator */
$locator = $this->container['locator'];
return ($outline &&
is_dir($locator("{$this->path}/{$outline}"))) ? $outline :
$preset;
}
/**
* @param string $path
* @return $this
*/
public function load($path = 'gantry-config://')
{
$this->path = $path;
$gantry = $this->container;
$theme = isset($gantry['theme.name']) ?
$gantry['theme.name'] : null;
$styles = ThemeList::getStyles($theme);
$installer = new
TemplateInstaller($this->container['theme.name']);
$title = $installer->getStyleName('%s - ');
$outlines = [];
foreach ($styles as $style) {
$preset = isset($style->params['preset']) ?
$style->params['preset'] : null;
$outline = isset($style->params['configuration'])
? $style->params['configuration'] : $preset;
if ($outline && $outline != $style->id) {
// New style generated by Joomla.
StyleHelper::copy($style, $outline, $style->id);
}
$outlines[$style->id] = preg_replace('|^' .
preg_quote($title) . '|', '', $style->style);
}
asort($outlines);
$this->items = $this->addDefaults($outlines);
return $this;
}
/**
* @param string|null $id
* @param string $title
* @param string|array $preset
* @return string
* @throws \RuntimeException
*/
public function create($id, $title = null, $preset = null)
{
if ($this->createId) {
// Workaround Joomla wanting to use different logic for style
duplication.
$new = parent::create($this->createId, $title, $preset);
$this->createId = null;
return $new;
}
$title = $title ? "%s - {$title}" : '%s -
Untitled';
$installer = new
TemplateInstaller($this->container['theme.name']);
$title = $installer->getStyleName($title);
$style = $installer->addStyle($title);
$error = $style->getError();
if ($error) {
throw new \RuntimeException($error, 400);
}
$presetId = (string)
(isset($preset['preset']['name']) ?
$preset['preset']['name'] : ($preset ?:
'default'));
StyleHelper::update($style->id, $presetId);
// Create configuration folder.
$id = parent::create($style->id, $title, $preset);
if ($id != $style->id) {
throw new \RuntimeException(sprintf("Creating outline:
folder '%s' already exists!", $style->id));
}
return $style->id;
}
public function duplicate($id, $title = null, $inherit = false)
{
if (!$this->canDuplicate($id)) {
throw new \RuntimeException("Outline '$id'
cannot be duplicated", 400);
}
// Handle special case of duplicating system outlines.
if ((string)(int) $id !== (string) $id) {
return parent::duplicate($id, $title, $inherit);
}
// Use Joomla logic to duplicate the style.
$model = StyleHelper::loadModel();
$pks = [$id];
if (!$model->duplicate($pks)) {
throw new \RuntimeException($model->getError(), 400);
}
// Seek the newly generated style ID since Joomla doesn't
return one on duplication.
$theme = $this->container['theme.name'];
$styles = ThemeList::getStyles($theme, true);
$style = end($styles);
if ($title) {
// Change the title.
$installer = new TemplateInstaller($theme);
$title = $installer->getStyleName("%s -
{$title}");
$this->rename($style->id, $title);
} else {
$title = $style->style;
}
$this->createId = $style->id;
return parent::duplicate($id, $title, $inherit);
}
public function rename($id, $title)
{
$model = StyleHelper::loadModel();
$item = $model->getTable();
$item->load($id);
if (!$item->id) {
throw new \RuntimeException('Outline not found',
404);
}
$theme = $this->container['theme.name'];
$installer = new TemplateInstaller($theme);
$title = $title ? "%s - {$title}" : '%s -
Untitled';
$title = $installer->getStyleName($title);
$item->title = $title;
if (!$item->check()) {
throw new \RuntimeException($item->getError(), 400);
}
if (!$item->store()) {
throw new \RuntimeException($item->getError(), 500);
}
if (isset($this->items[$id])) {
$this->items[$id] = $title;
}
return $id;
}
public function delete($id, $deleteModel = true)
{
if (!$this->canDelete($id)) {
throw new \RuntimeException("Outline '$id'
cannot be deleted", 400);
}
$model = StyleHelper::loadModel();
$item = $model->getTable();
$item->load($id);
try {
foreach ($this->getInheritingOutlines($id) as $outline =>
$title) {
$this->layout($outline)->updateInheritance($id)->save()->saveIndex();
}
foreach ($this->getInheritingOutlinesWithAtom($id) as
$outline => $title) {
Atoms::instance($outline)->updateInheritance($id)->save();
}
if ($deleteModel && !$model->delete($id)) {
$error = $model->getError();
// Well, Joomla can always send enqueue message instead!
if (!$error) {
$messages =
\JFactory::getApplication()->getMessageQueue();
$message = reset($messages);
$error = $message ? $message['message'] :
'Unknown error';
}
throw new \RuntimeException($error);
}
} catch (\Exception $e) {
throw new \RuntimeException('Deleting outline failed:
' . $e->getMessage(), 400, $e);
}
// Remove configuration directory.
$gantry = $this->container;
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$path =
$locator->findResource("{$this->path}/{$item->id}",
true, true);
if ($path) {
if (file_exists($path)) {
Folder::delete($path);
}
}
unset($this->items[$item->id]);
}
/**
* @param string $id
* @return boolean
*/
public function canDelete($id)
{
$model = StyleHelper::loadModel();
$item = $model->getTable();
$item->load($id);
return !$item->id || $item->home ? false : true;
}
/**
* @param string $id
* @return boolean
*/
public function isDefault($id)
{
$model = StyleHelper::loadModel();
$item = $model->getTable();
$item->load($id);
return (bool) $item->home;
}
}
PK���[�%jȌ�Framework/Page.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Framework;
class Page extends Base\Page
{
public $home;
public $outline;
public $language;
public $direction;
// Joomla specific properties.
public $theme;
public $baseUrl;
public $title;
public $description;
public function __construct($container)
{
parent::__construct($container);
$app = \JFactory::getApplication();
$document = \JFactory::getDocument();
$input = $app->input;
$this->tmpl = $input->getCmd('tmpl',
'');
$this->option = $input->getCmd('option',
'');
$this->view = $input->getCmd('view',
'');
$this->layout = $input->getCmd('layout',
'');
$this->task = $input->getCmd('task',
'');
$this->itemid = $input->getInt('Itemid', 0);
$this->printing = $input->getCmd('print',
'');
$this->class = '';
if ($this->itemid) {
$menuItem = $app->getMenu()->getActive();
if ($menuItem && $menuItem->id) {
$this->home = (bool) $menuItem->home;
$this->class =
$menuItem->params->get('pageclass_sfx', '');
}
}
$templateParams = $app->getTemplate(true);
$this->outline = Gantry::instance()['configuration'];
$this->sitename = $app->get('sitename');
$this->theme = $templateParams->template;
$this->baseUrl = \JUri::base(true);
$this->title = $document->title;
$this->description = $document->description;
// Document has lower case language code, which causes issues with
some JS scripts (Snipcart). Use tag instead.
$code = explode('-', $document->getLanguage(), 2);
$language = array_shift($code);
$country = strtoupper(array_shift($code));
$this->language = $language . ($country ? '-' .
$country : '');
$this->direction = $document->direction;
}
public function url(array $args = [])
{
$url = \JUri::getInstance();
foreach ($args as $key => $val) {
$url->setVar($key, $val);
}
return $url->toString();
}
public function htmlAttributes()
{
$attributes = [
'lang' => $this->language,
'dir' => $this->direction
]
+ (array) $this->config->get('page.html', []);
return $this->getAttributes($attributes);
}
public function bodyAttributes($attributes = [])
{
if ($this->tmpl == 'component') {
$classes = ['contentpane', 'modal'];
} else {
$classes = ['site', $this->option,
"view-{$this->view}"];
$classes[] = $this->layout ? 'layout-' .
$this->layout : 'no-layout';
$classes[] = $this->task ? 'task-' .
$this->task : 'no-task';
}
$classes[] = 'dir-' . $this->direction;
if ($this->class) $classes[] = $this->class;
if ($this->printing) $classes[] = 'print-mode';
if ($this->itemid) $classes[] = 'itemid-' .
$this->itemid;
if ($this->outline) $classes[] = 'outline-' .
$this->outline;
$baseAttributes = (array)
$this->config->get('page.body.attribs', []);
if (!empty($baseAttributes['class'])) {
$baseAttributes['class'] = array_merge((array)
$baseAttributes['class'], $classes);
} else {
$baseAttributes['class'] = $classes;
}
return $this->getAttributes($baseAttributes, $attributes);
}
}
PK���["��υB�BFramework/Platform.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Framework;
use Gantry\Admin\ThemeList;
use Gantry\Component\Filesystem\Folder;
use Gantry\Framework\Base\Platform as BasePlatform;
use Gantry\Joomla\Category\CategoryFinder;
use Gantry\Joomla\Content\Content;
use Gantry\Joomla\Content\ContentFinder;
/**
* The Platform Configuration class contains configuration information.
*
* @author RocketTheme
* @license MIT
*/
class Platform extends BasePlatform
{
public $no_base_layout = false;
public $module_wrapper = '<div
class="platform-content">%s</div>';
public $component_wrapper = '<div class="platform-content
row-fluid"><div
class="span12">%s</div></div>';
protected $name = 'joomla';
protected $features = ['modules' => true];
protected $settings_key = 'return';
protected $modules;
public function setModuleWrapper($html)
{
$this->module_wrapper = $html;
}
public function setComponentWrapper($html)
{
$this->component_wrapper = $html;
}
public function init()
{
// Support linked sample data.
$theme = isset($this->container['theme.name']) ?
$this->container['theme.name'] : null;
if ($theme && is_dir(JPATH_ROOT .
"/media/gantry5/themes/{$theme}/media-shared")) {
$custom = JPATH_ROOT .
"/media/gantry5/themes/{$theme}/custom";
if (!is_dir($custom)) {
// First run -- copy configuration into a single location.
$shared = JPATH_ROOT .
"/media/gantry5/themes/{$theme}/template-shared";
$demo = JPATH_ROOT .
"/media/gantry5/themes/{$theme}/template-demo";
try {
Folder::create($custom);
} catch (\Exception $e) {
throw new \RuntimeException(sprintf("Failed to
create folder '%s'.", $custom), 500, $e);
}
if (is_dir("{$shared}/custom/config")) {
Folder::copy("{$shared}/custom/config",
"{$custom}/config");
}
if (is_dir("{$demo}/custom/config")) {
Folder::copy("{$demo}/custom/config",
"{$custom}/config");
}
}
array_unshift($this->items['streams']['gantry-theme']['prefixes'][''],
"media/gantry5/themes/{$theme}/template-shared");
array_unshift($this->items['streams']['gantry-theme']['prefixes'][''],
"media/gantry5/themes/{$theme}/template-demo");
array_unshift($this->items['streams']['gantry-theme']['prefixes'][''],
"media/gantry5/themes/{$theme}/custom");
}
return parent::init();
}
public function getCachePath()
{
$path = \JFactory::getConfig()->get('cache_path',
JPATH_SITE . '/cache');
if (!is_dir($path)) {
throw new \RuntimeException('Joomla cache path does not
exist!');
}
return $path . '/gantry5';
}
public function getThemesPaths()
{
return ['' => ['templates']];
}
public function getMediaPaths()
{
$paths = ['images'];
// Support linked sample data.
$theme = isset($this->container['theme.name']) ?
$this->container['theme.name'] : null;
if ($theme && is_dir(JPATH_ROOT .
"/media/gantry5/themes/{$theme}/media-shared")) {
array_unshift($paths,
"media/gantry5/themes/{$theme}/media-shared");
array_unshift($paths,
"media/gantry5/themes/{$theme}/media-demo");
}
if
($this->container['global']->get('use_media_folder',
false)) {
array_push($paths, 'gantry-theme://images');
} else {
array_unshift($paths, 'gantry-theme://images');
}
return ['' => $paths];
}
public function getEnginesPaths()
{
if (is_link(GANTRY5_ROOT . '/media/gantry5/engines')) {
// Development environment.
return ['' =>
["media/gantry5/engines/{$this->name}",
'media/gantry5/engines/common']];
}
return ['' => ['media/gantry5/engines']];
}
public function getAssetsPaths()
{
if (is_link(GANTRY5_ROOT . '/media/gantry5/assets')) {
// Development environment.
return ['' => ['gantry-theme://',
"media/gantry5/assets/{$this->name}",
'media/gantry5/assets/common']];
}
return ['' => ['gantry-theme://',
'media/gantry5/assets']];
}
/**
* Get preview url for individual theme.
*
* @param string $theme
* @return string
*/
public function getThemePreviewUrl($theme)
{
return (string)(int) $theme === (string) $theme ?
\JUri::root(false) . 'index.php?templateStyle=' . $theme : null;
}
/**
* Get administrator url for individual theme.
*
* @param string $theme
* @return string
*/
public function getThemeAdminUrl($theme)
{
$token = \JSession::getFormToken();
return
\JRoute::_("index.php?option=com_gantry5&view=configurations/default/styles&theme={$theme}&{$token}=1"
, false);
}
public function filter($text)
{
\JPluginHelper::importPlugin('content');
return \JHtml::_('content.prepare', $text, '',
'mod_custom.content');
}
public function countModules($position)
{
$document = \JFactory::getDocument();
return ($document instanceof \JDocumentHTML) ?
$document->countModules($position) : 0;
}
public function getModules($position)
{
// TODO:
return [];
}
public function displayModule($id, $attribs = [])
{
$document = \JFactory::getDocument();
if (!$document instanceof \JDocumentHTML) {
return '';
}
$module = is_object($id) ? $id : $this->getModule($id);
// Make sure that module really exists.
if (!is_object($module)) {
return '';
}
$isGantry = \strpos($module->module, 'gantry5') !==
false;
$content = isset($module->content) ? $module->content : null;
$renderer = $document->loadRenderer('module');
$html = trim($renderer->render($module, $attribs));
// Add frontend editing feature as it has only been defined for
module positions.
$app = \JFactory::getApplication();
$user = \JFactory::getUser();
$frontEditing = ($app->isSite() &&
$app->get('frontediting', 1) && !$user->guest);
$menusEditing = ($app->get('frontediting', 1) == 2)
&& $user->authorise('core.edit',
'com_menus');
if (!$isGantry && $frontEditing && $html &&
$user->authorise('module.edit.frontend',
'com_modules.module.' . $module->id)) {
$displayData = [
'moduleHtml' => &$html,
'module' => $module,
'position' =>
isset($attribs['position']) ? $attribs['position'] :
$module->position,
'menusediting' => $menusEditing
];
\JLayoutHelper::render('joomla.edit.frontediting_modules',
$displayData);
}
// Work around Joomla "issue" which corrupts content of
custom html module (last checked J! 3.6.5).
$module->content = $content;
if ($html && !$isGantry) {
$this->container['theme']->joomla(true);
return sprintf($this->module_wrapper, $html);
}
return $html;
}
public function displayModules($position, $attribs = [])
{
$document = \JFactory::getDocument();
if (!$document instanceof \JDocumentHTML) {
return '';
}
$html = '';
foreach (\JModuleHelper::getModules($position) as $module) {
$html .= $this->displayModule($module, $attribs);
}
return $html;
}
public function displaySystemMessages($params = [])
{
// We cannot use JDocument renderer here as it fires too early to
display any messages.
return '<jdoc:include type="message" />';
}
public function displayContent($content, $params = [])
{
$document = \JFactory::getDocument();
if (!$document instanceof \JDocumentHTML) {
return $content;
}
$renderer = $document->loadRenderer('component');
$html = trim($renderer->render(null, $params, $content ?:
$document->getBuffer('component')));
$isGantry =
\strpos(\JFactory::getApplication()->input->getCmd('option'),
'gantry5') !== false;
if ($html && !$isGantry) {
$this->container['theme']->joomla(true);
return sprintf($this->component_wrapper, $html);
}
return $html;
}
public function getModule($id)
{
$modules = $this->getModuleList();
return $id && isset($modules[$id]) ? $modules[$id] : null;
}
protected function &getModuleList()
{
if ($this->modules === null) {
$modules = \JModuleHelper::getModuleList();
$this->modules = [];
foreach ($modules as $module) {
$this->modules[$module->id] = $module;
}
}
return $this->modules;
}
public function listModules()
{
$db = \JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('a.id, a.title, a.position, a.module,
a.published AS enabled')
->from('#__modules AS a');
// Join on the asset groups table.
$query->select('ag.title AS access')
->join('LEFT', '#__viewlevels AS ag ON ag.id
= a.access')
->where('a.published >= 0')
->where('a.client_id = 0')
->order('a.position, a.module, a.ordering');
$db->setQuery($query);
try {
$result = $db->loadObjectList();
} catch (\RuntimeException $e) {
return false;
}
return $result;
}
public function getEditor($name, $content = '', $width =
null, $height = null)
{
$conf = \JFactory::getConfig();
$editor = \JEditor::getInstance($conf->get('editor'));
if (!$height) {
$height = 250;
}
return $editor->display($name, $content, $width, $height, 50, 8,
false, null, null, null, ['html_height' => $height]);
}
public function errorHandlerPaths()
{
return ['|gantry5|'];
}
public function settings()
{
if (!$this->authorize('platform.settings.manage')) {
return '';
}
return
\JRoute::_('index.php?option=com_config&view=component&component=com_gantry5',
false);
}
public function update()
{
return
\JRoute::_('index.php?option=com_installer&view=update',
false);
}
public function updates()
{
if (!$this->authorize('updates.manage')) {
return [];
}
$styles = ThemeList::getThemes();
$extension_ids = array_unique(array_map(
function($item) {
return (int) $item->extension_id;
},
$styles));
$extension_ids = $extension_ids ? implode(',',
$extension_ids) : '-1';
$db = \JFactory::getDbo();
$query = $db->getQuery(true);
$query
->select('*')
->from('#__updates')
->where("element='pkg_gantry5' OR
extension_id IN ($extension_ids)");
$db->setQuery($query);
$updates = $db->loadObjectList();
$list = [];
foreach ($updates as $update) {
if ($update->element === 'pkg_gantry5') {
// Rename Gantry 5 package.
$update->name = 'Gantry';
// Ignore git and CI installs and if the Gantry version is
the same or higher than in the updates.
if (version_compare(GANTRY5_VERSION, 0) < 0 ||
version_compare($update->version, GANTRY5_VERSION) <= 0) {
continue;
}
} else {
// Check if templates need to be updated.
$version = isset($styles[$update->element]) ?
$styles[$update->element]->get('details.version') : null;
if (version_compare($version, 0) < 0 ||
version_compare($update->version, $version) <= 0) {
continue;
}
}
$list[] = $update->name . ' ' .
$update->version;
}
return $list;
}
public function factory()
{
$args = func_get_args();
$method = ['JFactory', 'get'. ucfirst((string)
array_shift($args))];
return method_exists($method[0], $method[1]) ?
call_user_func_array($method, $args) : null;
}
public function instance()
{
$args = func_get_args();
$class = ucfirst((string) array_shift($args));
if (!$class) {
return null;
}
if (class_exists('J'. $class)) {
$class = 'J'. $class;
}
$method = [$class, 'getInstance'];
return method_exists($method[0], $method[1]) ?
call_user_func_array($method, $args) : null;
}
public function route()
{
return call_user_func_array(['JRoute', '_'],
func_get_args());
}
public function html()
{
$args = func_get_args();
if (isset($args[0]) && method_exists('JHtml',
$args[0])) {
return call_user_func_array(['JHtml',
array_shift($args)], $args);
}
return call_user_func_array(['JHtml', '_'],
$args);
}
public function article($keys)
{
return Content::getInstance($keys);
}
public function finder($domain, $options = null)
{
$options = (array) $options;
switch ($domain) {
case 'article':
case 'articles':
case 'content':
$finder = new ContentFinder($options);
return \JFactory::getApplication()->isSite() ?
$finder->authorised() : $finder;
case 'category':
case 'categories':
$finder = (new
CategoryFinder($options))->extension('content');
return \JFactory::getApplication()->isSite() ?
$finder->authorised() : $finder;
}
return null;
}
public function truncate($text, $length, $html = false)
{
return \JHtml::_('string.truncate', $text, $length, true,
$html);
}
public function authorize($action, $id = null)
{
$user = \JFactory::getUser();
switch ($action) {
case 'platform.settings.manage':
return $user->authorise('core.admin',
'com_templates') || $user->authorise('core.admin',
'com_gantry5');
case 'menu.manage':
return $user->authorise('core.manage',
'com_menus') &&
$user->authorise('core.edit', 'com_menus');
case 'menu.edit':
if ($id) {
$db = \JFactory::getDbo();
$userId = \JFactory::getUser()->id;
// Verify that no items are checked out.
$query = $db->getQuery(true)
->select('id')
->from('#__menu')
->where('menutype=' .
$db->quote($id))
->where('checked_out !=' . (int)
$userId)
->where('checked_out !=0');
$db->setQuery($query);
if ($db->loadRowList()) {
return false;
}
// Verify that no module for this menu are checked out.
$query->clear()
->select('id')
->from('#__modules')
->where('module=' .
$db->quote('mod_menu'))
->where('params LIKE ' .
$db->quote('%"menutype":' . json_encode($id) .
'%'))
->where('checked_out !=' . (int)
$userId)
->where('checked_out !=0');
$db->setQuery($query);
if ($db->loadRowList()) {
return false;
}
}
return $user->authorise('core.edit',
'com_menus');
case 'updates.manage':
return $user->authorise('core.manage',
'com_installer');
case 'outline.create':
return $user->authorise('core.create',
'com_templates');
case 'outline.delete':
return $user->authorise('core.delete',
'com_templates');
case 'outline.rename':
return $user->authorise('core.edit',
'com_templates');
case 'outline.assign':
return $user->authorise('core.edit.state',
'com_templates') &&
$user->authorise('core.edit', 'com_menu');
case 'outline.edit':
return true;
}
return true;
}
}
PK���[�8��Framework/Positions.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework;
use Gantry\Component\Position\Positions as BasePositions;
class Positions extends BasePositions
{
}
PK���[�l�$��Framework/Request.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework;
use Gantry\Component\Request\Request as BaseRequest;
class Request extends BaseRequest {}
PK���[#Q�ii,Framework/Services/ConfigServiceProvider.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework\Services;
use Gantry\Component\Config\CompiledBlueprints;
use Gantry\Component\Config\CompiledConfig;
use Gantry\Component\Config\ConfigFileFinder;
use Gantry\Framework\Atoms;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class ConfigServiceProvider implements ServiceProviderInterface
{
public function register(Container $gantry)
{
$gantry['blueprints'] = function($c) {
GANTRY_DEBUGGER &&
\Gantry\Debugger::startTimer('blueprints', 'Loading
blueprints');
$blueprints = static::blueprints($c);
GANTRY_DEBUGGER &&
\Gantry\Debugger::stopTimer('blueprints');
return $blueprints;
};
$gantry['config'] = function($c) {
// Make sure configuration has been set.
if (!isset($c['configuration'])) {
throw new \LogicException('Gantry: Please set current
configuration before using $gantry["config"]', 500);
}
GANTRY_DEBUGGER &&
\Gantry\Debugger::startTimer('config', 'Loading
configuration');
// Get the current configuration and lock the value from
modification.
$outline = $c->lock('configuration');
$config = static::load($c, $outline);
GANTRY_DEBUGGER &&
\Gantry\Debugger::setConfig($config)->stopTimer('config');
return $config;
};
}
public static function blueprints(Container $container)
{
/** @var UniformResourceLocator $locator */
$locator = $container['locator'];
$cache =
$locator->findResource('gantry-cache://theme/compiled/blueprints',
true, true);
$files = [];
$paths =
$locator->findResources('gantry-particles://');
$files += (new
ConfigFileFinder)->setBase('particles')->locateFiles($paths);
$paths =
$locator->findResources('gantry-blueprints://');
$files += (new ConfigFileFinder)->locateFiles($paths);
$config = new CompiledBlueprints($cache, $files, GANTRY5_ROOT);
return $config->load();
}
public static function load(Container $container, $name =
'default', $combine = true, $withDefaults = true)
{
/** @var UniformResourceLocator $locator */
$locator = $container['locator'];
$combine = $combine && $name !== 'default';
// Merge current configuration with the default.
$uris = $combine ? ["gantry-config://{$name}",
'gantry-config://default'] :
["gantry-config://{$name}"];
$paths = [];
foreach ($uris as $uri) {
$paths = array_merge($paths, $locator->findResources($uri));
}
// Locate all configuration files to be compiled.
$files = (new ConfigFileFinder)->locateFiles($paths);
$cache =
$locator->findResource('gantry-cache://theme/compiled/config',
true, true);
if (!$cache) {
throw new \RuntimeException('Who just removed Gantry 5
cache folder? Try reloading the page if it fixes the issue');
}
$compiled = new CompiledConfig($cache, $files, GANTRY5_ROOT);
$compiled->setBlueprints(function() use ($container) {
return $container['blueprints'];
});
$config = $compiled->load($withDefaults);
// Set atom inheritance.
$atoms = $config->get('page.head.atoms');
if (is_array($atoms)) {
$config->set('page.head.atoms', (new
Atoms($atoms))->init()->toArray());
}
return $config;
}
}
PK���[��d��+Framework/Services/ErrorServiceProvider.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework\Services;
use Gantry\Component\Whoops\SystemFacade;
use Gantry\Framework\Platform;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use Whoops\Handler\JsonResponseHandler;
use Whoops\Handler\PrettyPageHandler;
use Whoops\Run;
use Whoops\Util\Misc;
class ErrorServiceProvider implements ServiceProviderInterface
{
protected $format;
public function __construct($format = 'html')
{
$this->format = $format;
}
public function register(Container $container)
{
/** @var UniformResourceLocator $locator */
$locator = $container['locator'];
/** @var Platform $platform */
$platform = $container['platform'];
// Setup Whoops-based error handler
$system = new SystemFacade($platform->errorHandlerPaths());
$errors = new Run($system);
$error_page = new PrettyPageHandler;
$error_page->setPageTitle('Crikey! There was an
error...');
$error_page->setEditor('sublime');
foreach
($locator->findResources('gantry-assets://css/whoops.css') as
$path) {
$error_page->addResourcePath(dirname($path));
}
$error_page->addCustomCss('whoops.css');
$errors->pushHandler($error_page);
$jsonRequest = $this->format === 'json' || ($_SERVER
&& isset($_SERVER['HTTP_ACCEPT']) &&
$_SERVER['HTTP_ACCEPT'] == 'application/json');
if (Misc::isAjaxRequest() || $jsonRequest) {
$json_handler = new JsonResponseHandler;
//$json_handler->setJsonApi(true);
$errors->pushHandler($json_handler);
}
$errors->register();
$container['errors'] = $errors;
if (GANTRY_DEBUGGER &&
method_exists('Gantry\Debugger', 'setErrorHandler')) {
\Gantry\Debugger::setErrorHandler();
}
}
}
PK���[�I>44-Framework/Services/StreamsServiceProvider.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license Dual License: MIT or GNU/GPLv2 and later
*
* http://opensource.org/licenses/MIT
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Gantry Framework code that extends GPL code is considered GNU/GPLv2 and
later
*/
namespace Gantry\Framework\Services;
use Gantry\Component\Filesystem\Streams;
use Pimple\Container;
use RocketTheme\Toolbox\DI\ServiceProviderInterface;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class StreamsServiceProvider implements ServiceProviderInterface
{
public function register(Container $gantry)
{
$sp = $this;
$gantry['locator'] = function() use ($sp) {
return new UniformResourceLocator(GANTRY5_ROOT);
};
$gantry['streams'] = function($c) use ($sp) {
$schemes = (array)
$c['platform']->init()->get('streams');
/** @var UniformResourceLocator $locator */
$locator = $c['locator'];
$streams = new Streams($locator);
$streams->add($schemes);
GANTRY_DEBUGGER &&
method_exists('Gantry\Debugger', 'setLocator')
&& \Gantry\Debugger::setLocator($locator);
return $streams;
};
}
}
PK���[�ɿ�mmFramework/Site.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Framework;
class Site
{
public function __construct()
{
$document = \JFactory::getDocument();
if ($document instanceof \JDocumentHTML) {
$this->theme = $document->template;
$this->url = $document->baseurl;
$this->title = $document->title;
$this->description = $document->description;
}
}
}
PK���[7*3���Framework/Theme.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Framework;
use Gantry\Component\Theme\AbstractTheme;
use Gantry\Component\Theme\ThemeTrait;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* Class Theme
* @package Gantry\Framework
*/
class Theme extends AbstractTheme
{
use ThemeTrait;
/**
* @var bool
*/
protected $joomla = false;
/**
* If parameter is set to true, loads bootstrap. Returns true if
bootstrap has been loaded.
*
* @param bool|null $enable
* @return bool
*/
public function joomla($enable = null)
{
if ($enable && !$this->joomla) {
$this->joomla = true;
// Workaround for Joomla! not loading bootstrap when it needs
it.
$this->gantry()->load('bootstrap.2');
}
return $this->joomla;
}
/**
* @see AbstractTheme::extendTwig()
*
* @param \Twig_Environment $twig
* @param \Twig_LoaderInterface $loader
* @return \Twig_Environment
*/
public function extendTwig(\Twig_Environment $twig,
\Twig_LoaderInterface $loader = null)
{
parent::extendTwig($twig, $loader);
/** @var \Twig_Extension_Core $core */
$core = $twig->getExtension('Twig_Extension_Core');
// Get user timezone and if not set, use Joomla default.
$timezone = \JFactory::getUser()->getParam('timezone',
\JFactory::getConfig()->get('offset', 'UTC'));
$core->setTimezone(new \DateTimeZone($timezone));
// Set locale for dates and numbers.
$core->setDateFormat(\JText::_('DATE_FORMAT_LC2'),
\JText::_('GANTRY5_X_DAYS'));
$core->setNumberFormat(0,
\JText::_('DECIMALS_SEPARATOR'),
\JText::_('THOUSANDS_SEPARATOR'));
$filter = new \Twig_SimpleFilter('date', [$this,
'twig_dateFilter'], array('needs_environment' =>
true));
$twig->addFilter($filter);
return $twig;
}
/**
* Converts a date to the given format.
*
* <pre>
* {{ post.published_at|date("m/d/Y") }}
* </pre>
*
* @param \Twig_Environment $env
* @param \DateTime|\DateTimeInterface|\DateInterval|string $date A
date
* @param string|null $format
The target format, null to use the default
* @param \DateTimeZone|string|null|false $timezone
The target timezone, null to use the default, false to leave unchanged
*
* @return string The formatted date
*/
public function twig_dateFilter(\Twig_Environment $env, $date, $format
= null, $timezone = null)
{
if (null === $format) {
$formats =
$env->getExtension('Twig_Extension_Core')->getDateFormat();
$format = $date instanceof \DateInterval ? $formats[1] :
$formats[0];
}
if ($date instanceof \DateInterval) {
return $date->format($format);
}
if (!($date instanceof \JDate)) {
// Create localized JDate object.
$twig_date = \twig_date_converter($env, $date, $timezone);
$date = new \JDate($twig_date->getTimestamp());
$date->setTimezone($twig_date->getTimezone());
} elseif ($timezone) {
$date->setTimezone($timezone);
}
return $date->format($format, true);
}
/**
* @see AbstractTheme::getContext()
*
* @param array $context
* @return array
*/
public function getContext(array $context)
{
$gantry = static::gantry();
$context = parent::getContext($context);
$context['site'] = $gantry['site'];
$context['joomla'] = $gantry['platform'];
return $context;
}
/**
* @see AbstractTheme::init()
*/
protected function init()
{
parent::init();
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$lang = \JFactory::getLanguage();
// FIXME: Do not hardcode this file.
$lang->load('files_gantry5_nucleus', JPATH_SITE);
if (\JFactory::getApplication()->isSite()) {
// Load our custom positions file as frontend requires the
strings to be there.
$filename =
$locator("gantry-theme://language/en-GB/en-GB.tpl_{$this->name}_positions.ini");
if ($filename) {
$lang->load("tpl_{$this->name}_positions",
\dirname(\dirname(\dirname($filename))), 'en-GB');
}
// Load template language files, including overrides.
$paths =
$locator->findResources('gantry-theme://language');
foreach (array_reverse($paths) as $path) {
$lang->load("tpl_{$this->name}",
\dirname($path));
}
}
$doc = \JFactory::getDocument();
if ($doc instanceof \JDocumentHtml) {
$doc->setHtml5(true);
}
$this->language = $doc->language;
$this->direction = $doc->direction;
$this->url = \JUri::root(true) . '/templates/' .
$this->name;
\JPluginHelper::importPlugin('gantry5');
// Trigger the onGantryThemeInit event.
$dispatcher = \JEventDispatcher::getInstance();
$dispatcher->trigger('onGantry5ThemeInit',
['theme' => $this]);
}
/**
* Get list of twig paths.
*
* @return array
*/
public static function getTwigPaths()
{
/** @var UniformResourceLocator $locator */
$locator = static::gantry()['locator'];
return
$locator->mergeResources(['gantry-theme://twig',
'gantry-engine://twig']);
}
/**
* @see AbstractTheme::setTwigLoaderPaths()
*
* @param \Twig_LoaderInterface $loader
* @return \Twig_Loader_Filesystem
*/
protected function setTwigLoaderPaths(\Twig_LoaderInterface $loader)
{
$loader = parent::setTwigLoaderPaths($loader);
if ($loader) {
$loader->setPaths($this->getTwigPaths());
}
return $loader;
}
}
PK���["ݲc�E�EFramework/ThemeInstaller.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Framework;
use Gantry\Component\Layout\Layout;
use Gantry\Component\Theme\ThemeInstaller as AbstractInstaller;
use Gantry\Joomla\Manifest;
use RocketTheme\Toolbox\File\YamlFile;
class ThemeInstaller extends AbstractInstaller
{
protected $extension;
protected $manifest;
public function __construct($extension = null)
{
parent::__construct();
jimport('joomla.filesystem.folder');
\JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_templates/tables');
if ($extension instanceof \JInstallerAdapterTemplate) {
$this->setInstaller($extension);
} elseif ($extension) {
$this->loadExtension($extension);
}
}
public function setInstaller(\JInstallerAdapterTemplate $install)
{
// We need access to a protected variable $install->extension.
$reflectionClass = new \ReflectionClass($install);
$property =
$reflectionClass->getProperty('extension');
$property->setAccessible(true);
$this->extension = $property->getValue($install);
$this->name = $this->extension->name;
$this->manifest = new Manifest($this->extension->name,
$install->getManifest());
return $this;
}
public function loadExtension($id)
{
if ((string) intval($id) !== (string) $id) {
$id = ['type' => 'template',
'element' => (string) $id, 'client_id' => 0];
}
$this->extension = \JTable::getInstance('extension');
$this->extension->load($id);
$this->name = $this->extension->name;
}
public function getPath()
{
return JPATH_SITE . '/templates/' .
$this->extension->name;
}
public function getStyleName($title)
{
return \JText::sprintf($title,
\JText::_($this->extension->name));
}
public function getStyle($name = null)
{
if (is_numeric($name)) {
$field = 'id';
} else {
$field = 'title';
$name = $this->getStyleName($name);
}
$style = $this->createStyle();
$style->load([
'template' => $this->extension->element,
'client_id' => $this->extension->client_id,
$field => $name
]);
return $style;
}
public function getDefaultStyle()
{
$style = \JTable::getInstance('Style',
'TemplatesTable');
$style->load(['home' => 1, 'client_id'
=> 0]);
return $style;
}
/**
* @param string $type
* @return \JTableMenu
*/
public function getMenu($type)
{
/** @var \JTableMenuType $table */
$table = \JTable::getInstance('MenuType');
$table->load(['menutype' => $type]);
return $table;
}
public function createSampleData()
{
$this->updateStyle('JLIB_INSTALLER_DEFAULT_STYLE', [],
1);
$this->installMenus();
}
public function render($template, $context = [])
{
$token = \JSession::getFormToken();
$manifest = $this->getManifest();
$context += [
'description' => $this->translate((string)
$manifest->get('description')),
'version' => (string)
$manifest->get('version'),
'date' => (string)
$manifest->get('creationDate'),
'author' => [
'name' => (string)
$manifest->get('author'),
'email' => (string)
$manifest->get('authorEmail'),
'url' => (string)
$manifest->get('authorUrl')
],
'copyright' => (string)
$manifest->get('copyright'),
'license' => (string)
$manifest->get('license'),
'install_url' =>
\JRoute::_("index.php?option=com_gantry5&view=install&theme={$this->name}&{$token}=1",
false),
'edit_url' =>
\JRoute::_("index.php?option=com_gantry5&view=configurations/default/styles&theme={$this->name}&{$token}=1",
false),
];
return parent::render($template, $context);
}
public function createStyle()
{
$style = \JTable::getInstance('Style',
'TemplatesTable');
$style->reset();
$style->template = $this->extension->element;
$style->client_id = $this->extension->client_id;
return $style;
}
public function addStyle($title, array $configuration = [], $home = 0)
{
// Make sure language debug is turned off.
$lang = \JFactory::getLanguage();
$debug = $lang->setDebug(false);
// Translate title.
$title = $this->getStyleName($title);
// Turn language debug back on.
$lang->setDebug($debug);
$data = [
'home' => (int) $home,
'title' => $title,
'params' => json_encode($configuration),
];
$style = $this->createStyle();
$style->save($data);
if ($home) {
$this->actions[] = ['action' =>
'default_style_assigned', 'text' =>
\JText::sprintf('GANTRY5_INSTALLER_ACTION_DEFAULT_STYLE_ASSIGNED',
$title)];
}
return $style;
}
public function updateStyle($name, array $configuration, $home = null)
{
$style = $this->getStyle($name);
if ($style->id) {
$home = ($home !== null ? $home : $style->home);
$params = (array) json_decode($style->params, true);
$data = [
'params' => json_encode($configuration +
$params),
'home' => $home
];
if ($home && !$style->home) {
$this->actions[] = ['action' =>
'default_style_assigned', 'text' =>
\JText::sprintf('GANTRY5_INSTALLER_ACTION_DEFAULT_STYLE_ASSIGNED',
$style->title)];
}
$style->save($data);
}
return $style;
}
public function assignHomeStyle($style)
{
// Update the mapping for menu items that this style IS assigned
to.
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->update('#__menu')
->set('template_style_id=' . (int) $style->id)
->where('home=1')
->where('client_id=0');
$db->setQuery($query);
$db->execute();
if ($db->getAffectedRows()) {
$this->actions[] = ['action' =>
'home_style_assigned', 'text' =>
\JText::sprintf('GANTRY5_INSTALLER_ACTION_HOME_STYLE_ASSIGNED',
$style->title)];
}
}
/**
* @param string $folder
* @param array $params
* @return string|bool
*/
public function createOutline($folder, array $params = [])
{
if (!$folder) {
throw new \RuntimeException('Cannot create outline without
folder name');
}
$this->initialize();
$created = false;
$params += [
'preset' => null,
'title' => null
];
$title = $params['title'] ?: ucwords(trim(strtr($folder,
['_' => ' '])));
$preset = $params['preset'] ?: 'default';
if ($folder[0] !== '_') {
$title = $this->getStyleName($title !== 'Default'
? "%s - {$title}" : 'JLIB_INSTALLER_DEFAULT_STYLE');
$style = $this->getStyle($title);
if (!$style->id) {
// Only add style if it doesn't exist.
$style = $this->addStyle($title, ['preset'
=> $preset]);
$created = true;
}
$id = $style->id;
} else {
$id = $folder;
}
$target = $folder !== 'default' ? $id : $folder;
// Copy configuration for the new layout.
if (($this->copyCustom($folder, $target) || $created) &&
isset($style)) {
// Update layout and save it.
$layout = Layout::load($target, $preset);
$layout->save()->saveIndex();
if ($id !== $target) {
// Default outline: Inherit everything from the base.
$layout->inheritAll()->name = $id;
$layout->save()->saveIndex();
$this->actions[] = ['action' =>
'base_outline_created', 'text' =>
$this->translate('GANTRY5_INSTALLER_ACTION_BASE_OUTLINE_CREATED',
$title)];
}
if ($created) {
$this->actions[] = ['action' =>
'outline_created', 'text' =>
$this->translate('GANTRY5_INSTALLER_ACTION_OUTLINE_CREATED',
$title)];
} else {
$this->actions[] = ['action' =>
'outline_updated', 'text' =>
$this->translate('GANTRY5_INSTALLER_ACTION_OUTLINE_UPDATED',
$title)];
}
// Update preset in Joomla table.
$this->updateStyle($title, ['preset' =>
$layout['preset']['name']]);
}
return $id;
}
/**
* @param array $item [menutype, title, alias, link,
template_style_id, params]
* @param int $parent_id Parent menu id.
* @param bool $load True if updating existing items.
* @return int
* @throws \Exception
*/
public function addMenuItem(array $item, $parent_id = 1, $load = false)
{
$component_id = $this->getComponent();
$table = \JTable::getInstance('menu');
$date = new \JDate();
$update = false;
// Defaults for the item.
$item += [
'menutype' => 'mainmenu',
'title' => 'Home',
'alias' => 'gantry5',
'note' => '',
'link' =>
'index.php?option=com_gantry5&view=custom',
'type' => 'component',
'published' => 1,
'parent_id' => $parent_id,
'component_id' => $component_id,
'checked_out' => 0,
'checked_out_time' => $date->toSql(),
'browserNav' => 0,
'access' => 1,
'img' => '',
'template_style_id' => 0,
'params' => '{}',
'home' => 0,
'language' => '*',
'client_id' => 0
];
if (in_array($item['type'], ['separator',
'heading'])) {
$item['link'] = '';
}
if ($item['type'] !== 'component') {
$item['component_id'] = 0;
}
if ($load) {
$update = $table->load([
'menutype' => $item['menutype'],
'alias' => $item['alias'],
'parent_id' => $item['parent_id']
]);
}
$table->setLocation($parent_id, 'last-child');
if (!$table->bind($item) || !$table->check() ||
!$table->store()) {
throw new \Exception($table->getError());
}
/** @var \JCache|\JCacheController $cache */
$cache = \JFactory::getCache();
$cache->clean('mod_menu');
$menu = \JTable::getInstance('menuType');
$menu->load(['menutype' =>
$item['menutype']]);
if
(!isset($this->actions["menu_{$item['menutype']}_created"]))
{
$postfix = $item['home'] ? '_HOME' :
'';
if ($update) {
$this->actions[] = ['action' =>
'menu_item_updated', 'text' =>
\JText::sprintf('GANTRY5_INSTALLER_ACTION_MENU_ITEM_UPDATED' .
$postfix, $table->title, $table->path, $menu->title)];
} else {
$this->actions[] = ['action' =>
'menu_item_created', 'text' =>
\JText::sprintf('GANTRY5_INSTALLER_ACTION_MENU_ITEM_CREATED' .
$postfix, $table->title, $table->path, $menu->title)];
}
} elseif ($item['home']) {
$this->actions[] = ['action' =>
'menu_item_updated', 'text' =>
\JText::sprintf('GANTRY5_INSTALLER_ACTION_MENU_ITEM_HOME',
$table->title, $table->path, $menu->title)];
}
return $table->id;
}
public function installMenus(array $menus = null, $parent = 1)
{
if ($menus === null) {
$path = $this->getPath();
$file = YamlFile::instance($path .
'/install/menus.yaml');
$menus = (array) $file->content();
$file->free();
}
foreach ($menus as $menutype => $menu) {
$title = !empty($menu['title']) ?
$menu['title'] : ucfirst($menutype);
$description = !empty($menu['description']) ?
$menu['description'] : '';
$exists = $this->getMenu($menutype)->id;
// If $parent = 0, do dry run.
if ((int) $parent && !$exists) {
$this->deleteMenu($menutype, true);
$this->createMenu($menutype, $title, $description);
}
if (!empty($menu['items'])) {
$this->addMenuItems($menutype, $menu['items'],
(int) $parent);
}
}
}
/**
* @param string $type
* @param string $title
* @param string $description
* @throws \Exception
*/
public function createMenu($type, $title, $description)
{
/** @var \JTableMenuType $table */
$table = \JTable::getInstance('MenuType');
$data = array(
'menutype' => $type,
'title' => $title,
'description' => $description
);
if (!$table->bind($data) || !$table->check()) {
// Menu already exists, do nothing
return;
}
if (!$table->store()) {
throw new \Exception($table->getError());
}
$this->actions["menu_{$type}_created"] =
['action' => 'menu_created', 'text' =>
\JText::sprintf('GANTRY5_INSTALLER_ACTION_MENU_CREATED',
$title)];
}
/**
* @param string $type
* @param bool $force
*/
public function deleteMenu($type, $force = false)
{
if ($force) {
$this->unsetHome($type);
}
$table = \JTable::getInstance('MenuType');
$table->load(array('menutype' => $type));
if ($table->id) {
$success = $table->delete();
if (!$success) {
\JFactory::getApplication()->enqueueMessage($table->getError(),
'error');
} else {
$this->actions["menu_{$type}_deleted"] =
['action' => 'menu_delete', 'text' =>
\JText::_('GANTRY5_INSTALLER_ACTION_MENU_DELETED',
$table->title)];
}
}
/** @var \JCache|\JCacheController $cache */
$cache = \JFactory::getCache();
$cache->clean('mod_menu');
}
public function unsetHome($type)
{
// Update the mapping for menu items that this style IS assigned
to.
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->update('#__menu')
->set('home=0')
->where('menutype=' . $db->quote($type))
->where('client_id=0');
$db->setQuery($query);
$db->execute();
}
/**
* @deprecated 5.3.2
*/
public function cleanup()
{
$this->initialize();
$this->finalize();
}
public function finalize()
{
parent::finalize();
$gantry = Gantry::instance();
/** @var Outlines $outlines */
$outlines = $gantry['outlines'];
$name = $this->extension->name;
// Update positions in manifest file.
$positions = $outlines->positions();
$manifest = new Manifest($name);
$manifest->setPositions(array_keys($positions));
$manifest->save();
}
protected function addMenuItems($menutype, array $items, $parent)
{
foreach ($items as $alias => $item) {
$item = (array) $item;
$item += [
'menutype' => $menutype,
'title' => ucfirst($alias),
'alias' => $alias
];
$outline = isset($item['outline']) ?
$item['outline'] : (isset($item['layout']) ?
$item['layout'] : null);
$params = $this->getOutline($outline);
if (!is_array($params)) {
$params = [
'preset' =>
isset($item['preset']) ? $item['preset'] :
(isset($item['layout']) ? $item['layout'] : null),
'title' => isset($item['style'])
? $item['style'] : null
];
}
$id = $outline ? $this->createOutline($outline, $params) :
0;
$item['template_style_id'] = (string)(int) $id ===
(string) $id ? $id : 0;
// If $parent = 0, do dry run.
$itemId = $parent ? $this->addMenuItem($item, $parent, true)
: 0;
if (!empty($item['items'])) {
$this->addMenuItems($menutype, $item['items'],
$itemId);
}
}
}
protected function getInstallerScript()
{
if (!$this->script) {
$className = $this->extension->name .
'InstallerScript';
if (!class_exists($className)) {
$manifest = new Manifest($this->extension->name);
$file = $manifest->getScriptFile();
$path = "{$this->getPath()}/{$file}";
if ($file && is_file($path)) {
require_once $path;
}
}
if (class_exists($className)) {
$this->script = new $className;
}
}
return $this->script;
}
protected function getManifest()
{
if (!$this->manifest) {
$this->manifest = new
Manifest($this->extension->name);
}
return $this->manifest;
}
protected function getComponent()
{
static $component_id;
if (!$component_id) {
// Get Gantry component id.
$component_id =
\JComponentHelper::getComponent('com_gantry5')->id;
}
return $component_id;
}
}
PK���[��g\\Framework/Translator.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Framework;
use Gantry\Component\Translator\Translator as BaseTranslator;
class Translator extends BaseTranslator
{
public function translate($string)
{
if (\func_num_args() === 1) {
return \JText::_($string);
}
$args = \func_get_args();
return \call_user_func_array(['JText',
'sprintf'], $args);
}
}
PK���[J�s33&Joomla/Assignments/AssignmentsMenu.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla\Assignments;
use Gantry\Component\Assignments\AssignmentsInterface;
class AssignmentsMenu implements AssignmentsInterface
{
public $type = 'menu';
public $priority = 1;
/**
* Returns list of rules which apply to the current page.
*
* @return array
*/
public function getRules()
{
$rules = [];
$app = \JFactory::getApplication();
if ($app->isSite()) {
$active = $app->getMenu()->getActive();
if ($active) {
$menutype = $active->menutype;
$id = $active->id;
$rules = [$menutype => [$id => $this->priority]];
}
}
return $rules;
}
/**
* List all the rules available.
*
* @param string $configuration
* @return array
*/
public function listRules($configuration)
{
require_once JPATH_ADMINISTRATOR .
'/components/com_menus/helpers/menus.php';
$data = \MenusHelper::getMenuLinks();
$userid = \JFactory::getUser()->id;
$list = [];
foreach ($data as $menu) {
$items = [];
foreach ($menu->links as $link) {
$items[] = [
'name' => $link->value,
'field' => ['id',
'link' . $link->value],
'value' => $link->template_style_id ==
$configuration,
'disabled' => $link->type !=
'component' || $link->checked_out &&
$link->checked_out != $userid,
'label' => str_repeat('—',
max(0, $link->level-1)) . ' ' . $link->text
];
}
$group = [
'label' => $menu->title ?:
$menu->menutype,
'items' => $items
];
$list[$menu->menutype] = $group;
}
return $list;
}
}
PK���[=�|���'Joomla/Assignments/AssignmentsStyle.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla\Assignments;
use Gantry\Component\Assignments\AssignmentsInterface;
use Gantry\Framework\Gantry;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class AssignmentsStyle implements AssignmentsInterface
{
public $type = 'style';
public $priority = 2;
/**
* Returns list of rules which apply to the current page.
*
* @return array
*/
public function getRules()
{
static $rules;
if (!isset($rules)) {
$rules = [];
$template = \JFactory::getApplication()->getTemplate(true);
$theme = $template->template;
$outline =
$template->params->get('configuration',
!empty($template->id) ? $template->id :
$template->params->get('preset', null));
if (JDEBUG) {
GANTRY_DEBUGGER &&
\Gantry\Debugger::addMessage('Template Style:',
'debug') && \Gantry\Debugger::addMessage($template,
'debug');
if (!$outline) {
\JFactory::getApplication()->enqueueMessage('JApplicationSite::getTemplate()
was overridden with no specified Gantry 5 outline.',
'debug');
}
}
/** @var UniformResourceLocator $locator */
$locator = Gantry::instance()['locator'];
if ($outline &&
is_dir($locator("gantry-themes://{$theme}/custom/config/{$outline}")))
{
$rules = ['id' => [$outline =>
$this->priority]];
}
}
return $rules;
}
/**
* List all the rules available.
*
* @param string $configuration
* @return array
*/
public function listRules($configuration)
{
return [];
}
}
PK���[��Joomla/CacheHelper.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla;
class CacheHelper
{
public static function cleanTemplates()
{
self::cleanByType('com_templates');
self::cleanByType('_system');
}
public static function cleanMenu()
{
self::cleanByType('mod_menu');
self::cleanByType('_system');
}
public static function cleanPlugin()
{
self::cleanByType('_system', 0);
self::cleanByType('_system', 1);
self::cleanByType('com_plugins', 0);
self::cleanByType('com_plugins', 1);
}
private static function cleanByType($group = null, $client_id = 0,
$event = 'onContentCleanCache')
{
$conf = \JFactory::getConfig();
$dispatcher = \JEventDispatcher::getInstance();
$options = array(
'defaultgroup' => $group,
'cachebase' => ($client_id) ? JPATH_ADMINISTRATOR
. '/cache' : $conf->get('cache_path', JPATH_SITE .
'/cache'),
'result' => true
);
try {
$cache = \JCache::getInstance('callback', $options);
$cache->clean();
} catch (\Exception $e) { // TODO: Joomla 3.7 uses JCacheException
$options['result'] = false;
}
// Trigger the onContentCleanCache event.
$dispatcher->trigger($event, $options);
}
}
PK���[*����Joomla/Category/Category.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla\Category;
use Gantry\Framework\Gantry;
use Gantry\Joomla\Object\AbstractObject;
class Category extends AbstractObject
{
static protected $instances = [];
static protected $table = 'Category';
static protected $order = 'lft';
public function initialize()
{
if (!parent::initialize()) {
return false;
}
$this->params = json_decode($this->params);
$this->metadata = json_decode($this->metadata);
return true;
}
public function parent()
{
if ($this->alias != $this->path)
{
$parent = Category::getInstance($this->parent_id);
}
return isset($parent) && $parent->extension ==
$this->extension ? $parent : null;
}
public function parents()
{
$parent = $this->parent();
return $parent ? array_merge($parent->parents(), [$parent]) :
[];
}
public function route()
{
require_once JPATH_SITE .
'/components/com_content/helpers/route.php';
return
\JRoute::_(\ContentHelperRoute::getCategoryRoute($this->id .
':' . $this->alias), false);
}
public function render($file)
{
return Gantry::instance()['theme']->render($file,
['category' => $this]);
}
public function compile($string)
{
return Gantry::instance()['theme']->compile($string,
['category' => $this]);
}
public function toArray()
{
return $this->getProperties(true);
}
}
PK���[&��w;;"Joomla/Category/CategoryFinder.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla\Category;
use Gantry\Joomla\Object\Finder;
class CategoryFinder extends Finder
{
protected $table = '#__categories';
protected $extension = 'com_content';
protected $readonly = true;
/**
* Makes all created objects as readonly.
*
* @return $this
*/
public function readonly($readonly = true)
{
$this->readonly = (bool)$readonly;
return $this;
}
public function find($object = true)
{
$ids = parent::find();
if (!$object) {
return $ids;
}
return Category::getInstances($ids, $this->readonly);
}
public function id($ids, $levels = 0)
{
if ($ids && $levels) {
$ids = (array) $ids;
$db = $this->db;
array_walk($ids, function (&$item) use ($db) { $item =
$db->quote($item); });
$idList = implode(',', $ids);
// Create a subquery for the subcategory list
$subQuery = $this->db->getQuery(true)
->select('sub.id')
->from('#__categories AS sub')
->join('INNER', '#__categories AS this ON
sub.lft > this.lft AND sub.rgt < this.rgt')
->where("this.id IN ({$idList})");
if (is_numeric($levels)) {
$subQuery->where('sub.level <= this.level +
' . (int) $levels);
}
// Add the subquery to the main query
$this->query->where("(a.id IN ({$idList}) OR a.id IN
({$subQuery->__toString()}))");
} else {
$this->where('a.id', 'IN', $ids);
}
return $this;
}
public function language($language = true)
{
if (!$language) {
return $this;
}
if ($language === true || is_numeric($language)) {
$language = \JFactory::getLanguage()->getTag();
}
return $this->where('a.language', 'IN',
[$language, '*']);
}
public function published($published = 1)
{
if (!is_array($published)) {
$published = (array) intval($published);
}
return $this->where('a.published', 'IN',
$published);
}
public function authorised($authorised = true)
{
if (!$authorised) {
return $this;
}
// Ignore unpublished categories.
$unpublished = $this->getUnpublished($this->extension);
if ($unpublished) {
$this->where('a.id', 'NOT IN',
$unpublished);
}
// Check authorization.
$user = \JFactory::getUser();
$groups = $user->getAuthorisedViewLevels();
return $this->where('a.access', 'IN',
$groups);
}
public function extension($extension)
{
$this->extension = static::getExtension($extension);
return $this->where('a.extension', '=',
$this->extension);
}
public static function getExtension($extension)
{
static $map = [
'article' => 'com_content',
'articles' => 'com_content',
'content' => 'com_content',
];
if (isset($map[$extension])) {
$extension = $map[$extension];
}
return $extension;
}
public static function getUnpublished($extension)
{
static $list;
if ($list === null) {
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select('cat.id AS id')
->from('#__categories AS cat')
->join('LEFT', '#__categories AS parent
ON cat.lft BETWEEN parent.lft AND parent.rgt')
->where('parent.extension = ' .
$db->quote(static::getExtension($extension)))
->where('parent.published != 1 AND cat.published
< 1')
->group('cat.id');
$db->setQuery($query);
$list = $db->loadColumn();
}
return $list;
}
}
PK���[��-��Joomla/Content/Content.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla\Content;
use Gantry\Framework\Gantry;
use Gantry\Joomla\Category\Category;
use Gantry\Joomla\Object\AbstractObject;
class Content extends AbstractObject
{
static protected $instances = [];
static protected $table = 'Content';
static protected $order = 'id';
public function initialize()
{
if (!parent::initialize()) {
return false;
}
$this->images = json_decode($this->images);
$this->urls = json_decode($this->urls);
$this->attribs = json_decode($this->attribs);
$this->metadata = json_decode($this->metadata);
$nullDate = \JFactory::getDbo()->getNullDate();
if ($this->modified === $nullDate) {
$this->modified = $this->created;
}
if ($this->publish_up === $nullDate) {
$this->publish_up = $this->created;
}
return true;
}
public function author()
{
return \JUser::getInstance($this->created_by);
}
public function category()
{
return Category::getInstance($this->catid);
}
public function categories()
{
$category = $this->category();
return array_merge($category->parents(), [$category]);
}
public function text()
{
return $this->introtext . ' ' . $this->fulltext;
}
public function preparedText()
{
return \JHtml::_('content.prepare', $this->text());
}
public function preparedIntroText()
{
return \JHtml::_('content.prepare', $this->introtext);
}
public function readmore()
{
return (bool)strlen($this->fulltext);
}
public function route()
{
require_once JPATH_SITE .
'/components/com_content/helpers/route.php';
$category = $this->category();
return \JRoute::_(\ContentHelperRoute::getArticleRoute($this->id
. ':' . $this->alias, $category->id . ':' .
$category->alias), false);
}
public function edit()
{
$user = \JFactory::getUser();
$asset = "com_content.article.{$this->id}";
if ($user->authorise('core.edit', $asset) ||
$user->authorise('core.edit.own', $asset)) {
return
"index.php?option=com_content&task=article.edit&a_id={$this->id}&tmpl=component";
}
return false;
}
public function render($file)
{
return Gantry::instance()['theme']->render($file,
['article' => $this]);
}
public function compile($string)
{
return Gantry::instance()['theme']->compile($string,
['article' => $this]);
}
public function toArray()
{
return $this->getProperties(true) + [
'category' => [
'alias' => $this->category()->alias,
'title' => $this->category()->title
],
'author' => [
'username' => $this->author()->username,
'fullname' => $this->author()->name
],
];
}
}
PK���[=3���
Joomla/Content/ContentFinder.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla\Content;
use Gantry\Joomla\Category\Category;
use Gantry\Joomla\Category\CategoryFinder;
use Gantry\Joomla\Object\Collection;
use Gantry\Joomla\Object\Finder;
class ContentFinder extends Finder
{
protected $table = '#__content';
protected $readonly = true;
protected $state = [];
/**
* Makes all created objects as readonly.
*
* @return $this
*/
public function readonly($readonly = true)
{
$this->readonly = (bool)$readonly;
return $this;
}
public function find($object = true)
{
$ids = parent::find();
if (!$object) {
return $ids;
}
return Content::getInstances($ids, $this->readonly);
}
public function id($ids, $include = true)
{
return $this->addToGroup('a.id', $ids, $include);
}
public function author($ids, $include = true)
{
return $this->addToGroup('a.created_by', $ids,
$include);
}
public function category($ids, $include = true)
{
if ($ids instanceof Collection) {
$ids = $ids->toArray();
} else {
$ids = (array)$ids;
}
array_walk($ids, function (&$item) { $item = $item instanceof
Category ? $item->id : (int) $item; });
return $this->addToGroup('a.catid', $ids, $include);
}
public function featured($featured = true)
{
$featured = intval((bool)$featured);
$this->where('a.featured', '=', $featured);
return $this;
}
public function language($language = true)
{
if (!$language) {
return $this;
}
if ($language === true || is_numeric($language)) {
$language = \JFactory::getLanguage()->getTag();
}
return $this->where('a.language', 'IN',
[$language, '*']);
}
public function published($published = 1)
{
if (!is_array($published)) {
$published = (array) intval($published);
}
return $this->where('a.state', 'IN',
$published);
}
public function authorised($authorised = true)
{
if (!$authorised) {
return $this;
}
$unpublished = CategoryFinder::getUnpublished('content');
if ($unpublished) {
$this->where('a.catid', 'NOT IN',
$unpublished);
}
$user = \JFactory::getUser();
// Define null and now dates
$nullDate = $this->db->quote($this->db->getNullDate());
$nowDate =
$this->db->quote(\JFactory::getDate()->toSql());
// Filter by start and end dates.
if (!$user->authorise('core.edit.state',
'com_content') &&
!$user->authorise('core.edit', 'com_content')) {
$this->query
->where("(a.publish_up = {$nullDate} OR
a.publish_up <= {$nowDate})")
->where("(a.publish_down = {$nullDate} OR
a.publish_down >= {$nowDate})")
->where("a.state >= 1")
;
}
$groups = $user->getAuthorisedViewLevels();
$this->query->join('INNER', '#__categories AS
c ON c.id = a.catid');
return $this->where('a.access', 'IN',
$groups)->where('c.access', 'IN', $groups);
}
protected function addToGroup($key, $ids, $include = true)
{
$op = $include ? 'IN' : 'NOT IN';
if (isset($this->state[$key][$op])) {
$this->state[$key][$op] =
array_merge($this->state[$key][$op], $ids);
} else {
$this->state[$key][$op] = $ids;
}
return $this;
}
protected function prepare()
{
foreach ($this->state as $key => $list) {
foreach ($list as $op => $group) {
$this->where($key, $op, array_unique($group));
}
}
}
}
PK���[�v!��Joomla/Manifest.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla;
/**
* Joomla manifest file modifier.
*/
class Manifest
{
protected $theme;
protected $path;
protected $xml;
/**
* @param string $theme
* @param \SimpleXMLElement $manifest
* @throws \RuntimeException
*/
public function __construct($theme, \SimpleXMLElement $manifest = null)
{
$this->theme = $theme;
$this->path = JPATH_SITE .
"/templates/{$theme}/templateDetails.xml";
if (!is_file($this->path)) {
throw new \RuntimeException(sprintf('Template %s does not
exist.', $theme));
}
$this->xml = $manifest ?: simplexml_load_file($this->path);
}
/**
* @param string $variable
* @return string
*/
public function get($variable)
{
return (string) $this->xml->{$variable};
}
/**
* @return \SimpleXMLElement
*/
public function getXml()
{
return $this->xml;
}
public function getScriptFile()
{
return (string) $this->xml->scriptfile;
}
public function setPositions(array $positions)
{
sort($positions);
// Get the positions.
$target =
current($this->xml->xpath('//positions'));
$xml = "<positions>\n <position>" .
implode("</position>\n <position>",
$positions) . "</position>\n </positions>";
$insert = new \SimpleXMLElement($xml);
// Replace all positions.
$targetDom = dom_import_simplexml($target);
$insertDom =
$targetDom->ownerDocument->importNode(dom_import_simplexml($insert),
true);
$targetDom->parentNode->replaceChild($insertDom, $targetDom);
}
public function save()
{
// Do not save manifest if template has been symbolically linked.
if (is_link(dirname($this->path))) {
return;
}
if (!$this->xml->asXML($this->path)) {
throw new \RuntimeException(sprintf('Saving manifest for
%s template failed', $this->theme));
}
}
}
PK���[�]k���Joomla/Module/Module.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla\Module;
use Gantry\Framework\Gantry;
use Gantry\Joomla\Object\AbstractObject;
use RocketTheme\Toolbox\ArrayTraits\Export;
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
\JTable::addIncludePath(JPATH_LIBRARIES . '/legacy/table/');
class Module extends AbstractObject implements ExportInterface
{
use Export;
static protected $instances = [];
static protected $table = 'Module';
static protected $order = 'id';
protected $_assignments;
public function assignments($assignments = null)
{
if (is_array($assignments)) {
$this->_assignments = array_map('intval',
array_values($assignments));
} elseif (!isset($this->_assignments)) {
$db = \JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('menuid')->from('#__modules_menu')->where('moduleid
= ' . $this->id);
$db->setQuery($query);
$this->_assignments = array_map('intval', (array)
$db->loadColumn());
}
return $this->_assignments;
}
public function initialize()
{
if (!parent::initialize()) {
return false;
}
$this->params = json_decode($this->params);
return true;
}
public function toArray()
{
$particle = $this->module === 'mod_gantry5_particle';
// Convert params to array.
$params = json_decode(json_encode($this->params), true);
$array = [
'id' => $this->id,
'position' => $this->position,
'ordering' => (int) $this->ordering,
'type' => $particle ? 'particle' :
'joomla',
'title' => $this->title,
'chrome' => [
'display_title' => (bool) $this->showtitle,
'class' =>
!empty($params['moduleclass_sfx']) ?
$params['moduleclass_sfx'] : ''
],
'options' => null,
'assignments' => $this->assignments()
];
$options = array_filter(
[
'type' => !$particle ? $this->module :
null,
'note' => $this->note ?: null,
'published' => (bool) $this->published,
'content' => $this->content ?: null,
'params' => &$params,
'language' => $this->language !==
'*' ? $this->language : null,
],
[$this, 'is_not_null']
);
if ($particle) {
$array['joomla'] = $options;
$options = !empty($params['particle']) ?
json_decode($params['particle'], true) : [];
$options['type'] =
isset($options['particle']) ? $options['particle'] :
null;
$options['attributes'] =
isset($options['options']['particle']) ?
$options['options']['particle'] : [];
unset($options['particle'],
$options['options']);
$array['options'] = $options;
unset($params['particle']);
} else {
$array['options'] = $options;
}
return array_filter($array, [$this, 'is_not_null']);
}
public function create(array $array)
{
$type = $array['type'];
if ($type === 'particle') {
$particle = isset($array['options']) ?
$array['options'] : [];
$array['options'] = isset($array['joomla'])
? $array['joomla'] : [];
$array['options']['type'] =
'mod_gantry5_particle';
$array['options']['params']['particle'] =
$particle;
} elseif ($type !== 'joomla') {
return null;
}
$options = $array['options'];
$properties = [
'title' => $array['title'],
'note' => isset($options['note']) ?
$options['note'] : '',
'content' => isset($options['content'])
? $options['content'] : '',
'position' => $array['position'],
'ordering' => (int) $array['ordering'],
'published' => (int)
!empty($options['published']),
'module' => $options['type'],
'showtitle' => (int)
!empty($array['chrome']['display_title']),
'params' => isset($options['params']) ?
json_decode(json_encode($options['params'])) : [],
'language' =>
isset($options['language']) ? $options['language'] :
'*',
'_assignments' =>
isset($array['assignments']) ? $array['assignments'] :
[],
];
$object = new static();
$object->bind($properties);
return $object;
}
public function render($file)
{
return Gantry::instance()['theme']->render($file,
['particle' => $this]);
}
public function compile($string)
{
return Gantry::instance()['theme']->compile($string,
['particle' => $this]);
}
// Internal functions
/**
* @param $val
* @return bool
* @internal
*/
public function is_not_null($val)
{
return !is_null($val);
}
static protected function collection($items)
{
return new ModuleCollection($items);
}
}
PK���[�Y����"Joomla/Module/ModuleCollection.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla\Module;
use Gantry\Joomla\Object\Collection;
class ModuleCollection extends Collection
{
public function toArray()
{
return $this->__call('toArray', []);
}
public function export()
{
$assignments = $this->assignments();
$paths =
$this->getAssignmentPath($this->values($assignments));
$items = $this->toArray();
$positions = [];
// Convert assignments to our format.
foreach ($items as $item) {
$position = $item['position'];
$name = $item['options']['type'] .
'-' . $item['id'];
if ($position === '') {
continue;
}
if (empty($item['assignments'])) {
$item['assignments'] = [];
} elseif (in_array(0, $item['assignments'])) {
$item['assignments'] = ['page' =>
true];
} else {
$list = [];
foreach ($item['assignments'] as $assignment) {
$key = abs($assignment);
if (isset($paths[$key])) {
$list[$paths[$key]] = $assignment > 0 ? 1 : -1;
}
}
$item['assignments'] = ['page' =>
[$list]];
}
unset($item['position'], $item['id'],
$item['ordering']);
$positions[$position][$name] = $item;
}
return $positions;
}
public function assignments()
{
$this->loadAssignments();
return $this->__call('assignments', []);
}
public function loadAssignments()
{
$ids = $this->defined('assignments', false);
$ids = array_filter($ids);
if (!$ids) {
return;
}
$idlist = implode(',', array_keys($ids));
$db = \JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('moduleid,
menuid')->from('#__modules_menu')->where("moduleid
IN ($idlist)");
$db->setQuery($query);
$assignments = $db->loadRowList();
$list = [];
foreach ($assignments as $value) {
$list[$value[0]][] = (int) $value[1];
}
foreach ($this as $module) {
$module->assignments(isset($list[$module->id]) ?
$list[$module->id] : []);
}
}
protected function getAssignmentPath(array $ids)
{
if (!$ids) {
return [];
}
$idlist = implode(',', array_map('intval',
$ids));
$db = \JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('id,
path')->from('#__menu')->where("id IN
($idlist)");
$db->setQuery($query);
$paths = $db->loadRowList();
$list = [];
foreach ($paths as $value) {
$list[$value[0]] = $value[1];
}
return $list;
}
protected function values($values)
{
$list = [];
foreach ($values as $array) {
$list = array_merge($list, (array) $array);
}
return array_unique($list);
}
}
PK���[�.�H
H
Joomla/Module/ModuleFinder.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla\Module;
use Gantry\Joomla\Object\Finder;
class ModuleFinder extends Finder
{
protected $table = '#__modules';
protected $readonly = true;
protected $state = [];
protected $published = [0, 1];
protected $limit = 0;
/**
* Makes all created objects as readonly.
*
* @return $this
*/
public function readonly($readonly = true)
{
$this->readonly = (bool)$readonly;
return $this;
}
public function find($object = true)
{
$ids = parent::find();
if (!$object) {
return $ids;
}
return Module::getInstances($ids, $this->readonly);
}
public function id($ids, $include = true)
{
return $this->addToGroup('a.id', $ids, $include);
}
public function language($language = true)
{
if (!$language) {
return $this;
}
if ($language === true || is_numeric($language)) {
$language = \JFactory::getLanguage()->getTag();
}
return $this->where('a.language', 'IN',
[$language, '*']);
}
public function published($published = 1)
{
if (!is_array($published)) {
$published = (array) intval($published);
}
$this->published = $published;
return $this;
}
public function particle()
{
return $this->where('a.module', '=',
'mod_gantry5_particle');
}
public function authorised($authorised = true)
{
if (!$authorised) {
return $this;
}
$groups = \JFactory::getUser()->getAuthorisedViewLevels();
return $this->where('a.access', 'IN',
$groups);
}
protected function addToGroup($key, $ids, $include = true)
{
$op = $include ? 'IN' : 'NOT IN';
if (isset($this->state[$key][$op])) {
$this->state[$key][$op] =
array_merge($this->state[$key][$op], $ids);
} else {
$this->state[$key][$op] = $ids;
}
return $this;
}
protected function prepare()
{
$this->where('client_id', '=',
0)->where('published', 'IN',
$this->published)->order('position')->order('ordering');
foreach ($this->state as $key => $list) {
foreach ($list as $op => $group) {
$this->where($key, $op, array_unique($group));
}
}
}
}
PK���[嶱�2�2
Joomla/Object/AbstractObject.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla\Object;
/**
* Abstract base class for database objects.
*
*
*/
abstract class AbstractObject extends \JObject
{
/**
* If you don't have global instance ids, override this in
extending class.
* @var array
*/
static protected $instances = [];
/**
* Override table class in your own class.
* @var string
*/
static protected $table;
/**
* JTable class prefix, override if needed.
* @var string
*/
static protected $tablePrefix = 'JTable';
/**
* Override table in your own class.
* @var string
*/
static protected $order;
/**
* @var int
*/
public $id;
/**
* Is object stored into database?
* @var boolean
*/
protected $_exists = false;
/**
* Readonly object.
* @var bool
*/
protected $_readonly = false;
/**
* @var bool
*/
protected $_initialized = false;
/**
* Class constructor, overridden in descendant classes.
*
* @param int $identifier Identifier.
*/
public function __construct($identifier = null)
{
parent::__construct();
if ($identifier) {
$this->load($identifier);
}
}
/**
* Override this function if you need to initialize object right after
creating it.
*
* Can be used for example if the database fields need to be converted
to array or JRegistry.
*
* @return bool True if initialization was done, false if object was
already initialized.
*/
public function initialize()
{
$initialized = $this->_initialized;
$this->_initialized = true;
return !$initialized;
}
/**
* Make instance as read only object.
*/
public function readonly()
{
$this->_readonly = true;
}
/**
* Returns the global instance to the object.
*
* Note that using array of fields will always make a query to the
database, but it's very useful feature if you want to search
* one item by using arbitrary set of matching fields. If there are
more than one matching object, first one gets returned.
*
* @param int|array $keys An optional primary key value to
load the object by, or an array of fields to match.
* @param boolean $reload Force object reload from the
database.
*
* @return Object
*/
static public function getInstance($keys = null, $reload = false)
{
// If we are creating or loading a new item or we load instance by
alternative keys,
// we need to create a new object.
if (!$keys || is_array($keys) || !isset(static::$instances[(int)
$keys])) {
$c = get_called_class();
$instance = new $c($keys);
/** @var Object $instance */
if (!$instance->exists()) return $instance;
// Instance exists: make sure that we return the global
instance.
$keys = $instance->id;
}
// Return global instance from the identifier, possibly reloading
it first.
$instance = static::$instances[(int) $keys];
if ($reload) $instance->load($keys);
return $instance;
}
/**
* Removes all or selected instances from the object cache.
*
* @param null|int|array $ids
*/
static public function freeInstances($ids = null)
{
if ($ids === null) {
$ids = array_keys(static::$instances);
}
$ids = (array) $ids;
foreach ($ids as $id) {
unset(static::$instances[$id]);
}
}
/**
* Returns true if the object exists in the database.
*
* @param boolean $exists Internal parameter to change state.
*
* @return boolean True if object exists in database.
*/
public function exists($exists = null)
{
$return = $this->_exists;
if ($exists !== null) $this->_exists = (bool) $exists;
return $return;
}
/**
* Tests if dynamically defined property has been defined.
*
* @param string $property
* @param bool $defined
* @return bool
*/
public function defined($property, $defined = true)
{
$property = '_' . $property;
return $defined ? isset($this->{$property}) :
!isset($this->{$property});
}
/**
* Returns an associative array of object properties.
*
* @param boolean $public If true, returns only the public
properties.
*
* @return array
*/
public function getProperties($public = true)
{
if ($public) {
$getProperties = function($obj) { return get_object_vars($obj);
};
return $getProperties($this);
}
return get_object_vars($this);
}
/**
* Method to bind an associative array to the instance.
*
* This method optionally takes an array of properties to ignore or
allow when binding.
*
* @param array $src An associative array or object to bind to
the JTable instance.
* @param array $fields An optional array list of properties to
ignore / include only while binding.
* @param boolean $include True to include only listed fields,
false to ignore listed fields.
*
* @return boolean True on success.
*/
public function bind(array $src = null, array $fields = null, $include
= false)
{
if (empty($src)) return false;
if (!empty($fields)) {
$src = $include ? array_intersect_key($src,
array_flip($fields)) : array_diff_key($src, array_flip($fields));
}
$this->setProperties ( $src );
return true;
}
/**
* Method to load object from the database.
*
* @param mixed $keys An optional primary key value to load the
object by, or an array of fields to match. If not
* set the instance key value is used.
*
* @return boolean True on success, false if the object doesn't
exist.
*/
public function load($keys = null)
{
if ($keys !== null && !is_array($keys)) {
$keys = array('id'=>(int) $keys);
}
// Create the table object.
$table = static::getTable ();
// Make sure we set the given keys to the object even if it is not
loaded.
$table->reset();
if ($keys !== null) $table->bind($keys);
// Load the object based on the keys.
$this->_exists = $table->load($keys, false);
// Work around Joomla 3.1.1 bug on load() returning true if keys
didn't exist.
if ($table->id == 0) $this->_exists = false;
// Assuming all is well at this point lets bind the data.
$this->setProperties($table->getProperties());
if ($this->id) {
if (!isset(static::$instances[$this->id])) {
static::$instances[$this->id] = $this;
}
}
$this->initialize();
return $this->_exists;
}
/**
* Method to save the object to the database.
*
* Before saving the object, this method checks if object can be safely
saved.
* It will also trigger onContentBeforeSave and onContentAfterSave
events.
*
* @return boolean True on success.
*/
public function save()
{
// Check the object.
if ($this->_readonly || !$this->check()) {
return false;
}
$isNew = !$this->_exists;
// Initialize table object.
$table = static::getTable ();
$table->bind($this->getProperties());
// Check the table object.
if (!$table->check()) {
$this->setError($table->getError());
return false;
}
// Include the content plugins for the on save events.
$dispatcher = \JEventDispatcher::getInstance();
\JPluginHelper::importPlugin('content');
// Trigger the onContentBeforeSave event.
$result = $dispatcher->trigger('onContentBeforeSave',
array("com_gantry5.".get_called_class(), $table, $isNew));
if (in_array(false, $result, true)) {
$this->setError($table->getError());
return false;
}
// Store the data.
if (!$table->store()) {
$this->setError($table->getError());
return false;
}
// If item was created, load the object.
if ($isNew) {
$this->load($table->id);
if (!isset(static::$instances[$this->id])) {
static::$instances[$this->id] = $this;
}
}
// Trigger the onContentAfterSave event.
$dispatcher->trigger('onContentAfterSave',
array("com_gantry5.".get_called_class(), $table, $isNew));
return true;
}
/**
* Method to delete the object from the database.
*
* @return boolean True on success.
*/
public function delete()
{
if ($this->_readonly) {
return false;
}
if (!$this->_exists) {
return true;
}
// Initialize table object.
$table = static::getTable();
$table->bind($this->getProperties());
// Include the content plugins for the on save events.
$dispatcher = \JEventDispatcher::getInstance();
\JPluginHelper::importPlugin('content');
// Trigger the onContentBeforeDelete event.
$result =
$dispatcher->trigger('onContentBeforeDelete',
array("com_gantry5.".get_called_class(), $table));
if (in_array(false, $result, true)) {
$this->setError($table->getError());
return false;
}
if (!$table->delete()) {
$this->setError($table->getError());
return false;
}
$this->_exists = false;
// Trigger the onContentAfterDelete event.
$dispatcher->trigger('onContentAfterDelete',
array("com_gantry5.".get_called_class(), $table));
return true;
}
/**
* Method to perform sanity checks on the instance properties to ensure
* they are safe to store in the database.
*
* Child classes should override this method to make sure the data they
are storing in
* the database is safe and as expected before storage.
*
* @return boolean True if the instance is sane and able to be stored
in the database.
*/
public function check()
{
return true;
}
static public function getAvailableInstances()
{
return static::collection(static::$instances);
}
static public function getInstances(array $ids, $readonly = true)
{
if (!$ids) {
return array();
}
$results = array();
$list = array();
foreach ($ids as $id) {
if (!isset(static::$instances[$id])) {
$list[] = $id;
}
}
if ($list) {
$query = static::getQuery();
$query->where('id IN (' . implode(',',
$list) . ')');
static::loadInstances($query);
}
foreach ($ids as $id) {
if (isset(static::$instances[$id])) {
if ($readonly) {
$results[$id] = clone static::$instances[$id];
} else {
$results[$id] = static::$instances[$id];
}
}
}
return static::collection($results);
}
// Internal functions
static protected function collection($items)
{
return new Collection($items);
}
/**
* Method to get the table object.
*
* @return \JTable The table object.
*/
static protected function getTable()
{
return \JTable::getInstance(static::$table, static::$tablePrefix);
}
/**
* @return \JDatabaseQuery
*/
static protected function getQuery()
{
$table = static::getTable();
$db = \JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('a.*')->from($table->getTableName().'
AS a')->order(static::$order);
return $query;
}
/**
* @param \JDatabaseQuery|string $query
*/
static protected function loadInstances($query = null)
{
if (!$query) {
$query = static::getQuery();
}
$db = \JFactory::getDbo();
$db->setQuery($query);
/** @var Object[] $items */
$items = (array) $db->loadObjectList('id',
get_called_class());
foreach ($items as $item) {
if (!isset(static::$instances[$item->id])) {
$item->exists(true);
$item->initialize();
}
}
static::$instances += $items;
}
}
PK���[�g����Joomla/Object/Collection.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla\Object;
use \Gantry\Component\Collection\Collection as BaseCollection;
class Collection extends BaseCollection
{
public function __construct(array $items)
{
$this->items = $items;
}
public function get($property)
{
$list = [];
if ($property === 'id') {
return array_keys($this->items);
}
foreach ($this as $object) {
$list[$object->id] = $object->{$property};
}
return $list;
}
public function __call($name, $arguments)
{
$list = [];
foreach ($this as $object) {
$list[$object->id] = method_exists($object, $name) ?
call_user_func_array([$object, $name], $arguments) : null;
}
return $list;
}
}
PK���[T��BBJoomla/Object/Finder.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla\Object;
/**
* Class Finder
* @package Gantry\Joomla\Object
*/
abstract class Finder
{
/**
* Table associated with the model.
*
* @var string
*/
protected $table;
/**
* @var string
*/
protected $primaryKey = 'id';
/**
* @var \JDatabaseQuery
*/
protected $query;
/**
* @var \JDatabase
*/
protected $db;
protected $start = 0;
protected $limit = 20;
protected $skip = false;
/**
* Finder constructor.
*
* @param array $options
*/
public function __construct(array $options = [])
{
if (!$this->table) {
throw new \DomainException('Table name missing from '
. get_class($this));
}
$this->db = \JFactory::getDbo();
$this->query = $this->db->getQuery(true);
$this->query->from($this->table . ' AS a');
if ($options) {
$this->parse($options);
}
}
public function parse(array $options)
{
foreach ($options as $func => $params) {
if (method_exists($this, $func)) {
call_user_func_array([$this, $func], (array) $params);
}
}
return $this;
}
/**
* Set limitstart for the query.
*
* @param int $limitstart
*
* @return $this
*/
public function start($limitstart = 0)
{
$this->start = $limitstart;
return $this;
}
/**
* Set limit to the query.
*
* @param int $limit
*
* @return $this
*/
public function limit($limit = null)
{
if (!is_null($limit))
{
$this->limit = $limit;
}
return $this;
}
/**
* Set order by field and direction.
*
* This function can be used more than once to chain order by.
*
* @param string $by
* @param int $direction
* @param string $alias
*
* @return $this
*/
public function order($by, $direction = 1, $alias = 'a')
{
if (is_numeric($direction)) {
$direction = $direction > 0 ? 'ASC' :
'DESC';
} else {
$direction = strtolower((string)$direction) == 'desc'
? 'DESC' : 'ASC';
}
$by = (string)$alias . '.' .
$this->db->quoteName($by);
$this->query->order("{$by} {$direction}");
return $this;
}
/**
* Filter by field.
*
* @param string $field Field name.
* @param string $operation Operation
(>|>=|<|<=|=|IN|NOT IN)
* @param string|array $value Value.
*
* @return $this
*/
public function where($field, $operation, $value)
{
$db = $this->db;
$operation = strtoupper($operation);
switch ($operation)
{
case '>':
case '>=':
case '<':
case '<=':
case '=':
// Quote all non integer values.
$value = (string)(int)$value === (string)$value ?
(int)$value : $db->quote($value);
$this->query->where("{$this->db->quoteName($field)}
{$operation} {$value}");
break;
case 'BETWEEN':
case 'NOT BETWEEN':
list($a, $b) = (array) $value;
// Quote all non integer values.
$a = (string)(int)$a === (string)$a ? (int)$a :
$db->quote($a);
$b = (string)(int)$b === (string)$b ? (int)$b :
$db->quote($b);
$this->query->where("{$this->db->quoteName($field)}
{$operation} {$a} AND {$b}");
break;
case 'IN':
case 'NOT IN':
$value = (array) $value;
if (empty($value)) {
// WHERE field IN (nothing).
$this->query->where('0');
} else {
// Quote all non integer values.
array_walk($value, function (&$value) use ($db) {
$value = (string)(int)$value === (string)$value ? (int)$value :
$db->quote($value); });
$list = implode(',', $value);
$this->query->where("{$this->db->quoteName($field)}
{$operation} ({$list})");
}
break;
}
return $this;
}
/**
* Get items.
*
* Derived classes should generally override this function to return
correct objects.
*
* @return array
*/
public function find()
{
if ($this->skip)
{
return array();
}
$baseQuery = clone $this->query;
$this->prepare();
$query = $this->query;
$this->query = $baseQuery;
$query->select('a.' . $this->primaryKey);
$this->db->setQuery($query, $this->start,
$this->limit);
$results = (array) $this->db->loadColumn();
return $results;
}
/**
* Count items.
*
* @return int
*/
public function count()
{
$baseQuery = clone $this->query;
$this->prepare();
$query = $this->query;
$this->query = $baseQuery;
$query->select('COUNT(*)');
$this->db->setQuery($query);
$count = (int) $this->db->loadResult();
return $count;
}
/**
* Override to include common where rules.
*
* @return void
*/
protected function prepare()
{
}
}
PK���[�`�
�
Joomla/StyleHelper.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla;
use Gantry\Component\Filesystem\Folder;
use Gantry\Framework\Gantry;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* Joomla style helper.
*/
class StyleHelper
{
public static function getStyle($id)
{
\JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_templates/tables');
$style = \JTable::getInstance('Style',
'TemplatesTable');
$style->load($id);
return $style;
}
public static function loadStyles($template)
{
$db = \JFactory::getDbo();
$query = $db
->getQuery(true)
->select('s.id, s.template, s.home, s.title AS
long_title, s.params')
->from('#__template_styles AS s')
->where('s.client_id = 0')
->where("s.template = {$db->quote($template)}")
->order('s.id');
$db->setQuery($query);
$list = (array) $db->loadObjectList('id');
foreach ($list as $id => &$style) {
$style->title = preg_replace('/' .
preg_quote(\JText::_($style->template), '/') .
'\s*-\s*/u', '', $style->long_title);
$style->home = $style->home && $style->home
!== '1' ? $style->home : (bool)$style->home;
}
return $list;
}
public static function getDefaultStyle()
{
return static::getStyle(['home' => 1,
'client_id' => 0]);
}
public static function copy($style, $old, $new)
{
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$oldPath = $locator->findResource('gantry-config://' .
$old, true, true);
$newPath = $locator->findResource('gantry-config://' .
$new, true, true);
if (file_exists($oldPath)) {
Folder::copy($oldPath, $newPath);
}
$extension = !empty($style->extension_id) ?
$style->extension_id : $style->template;
$installer = new TemplateInstaller($extension);
$installer->updateStyle($new, ['configuration' =>
$new]);
}
public static function update($id, $preset)
{
$style = static::getStyle($id);
$extension = !empty($style->extension_id) ?
$style->extension_id : $style->template;
$installer = new TemplateInstaller($extension);
$installer->updateStyle($id, ['configuration' =>
$id, 'preset' => $preset]);
}
public static function delete($id)
{
$gantry = Gantry::instance();
/** @var UniformResourceLocator $locator */
$locator = $gantry['locator'];
$path = $locator->findResource('gantry-config://' .
$id, true, true);
if (is_dir($path)) {
Folder::delete($path, true);
}
}
/**
* @return \TemplatesModelStyle
*/
public static function loadModel()
{
static $model;
if (!$model) {
$path = JPATH_ADMINISTRATOR .
'/components/com_templates/';
\JTable::addIncludePath("{$path}/tables");
require_once "{$path}/models/style.php";
// Load language strings.
$lang = \JFactory::getLanguage();
$lang->load('com_templates');
$model = new \TemplatesModelStyle;
}
return $model;
}
}
PK���[h��Joomla/TemplateInstaller.phpnu�[���<?php
/**
* @package Gantry5
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2017 RocketTheme, LLC
* @license GNU/GPLv2 and later
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace Gantry\Joomla;
use Gantry\Framework\ThemeInstaller;
/**
* Class TemplateInstaller
* @package Gantry\Joomla
* @deprecated 5.3.2
*/
class TemplateInstaller extends ThemeInstaller {}
PK���[���Admin/Controller/Html/About.phpnu�[���PK���[$�_EYYZAdmin/Controller/Html/Cache.phpnu�[���PK���[��x� 4Admin/Controller/Html/Configurations/Assignments.phpnu�[���PK���[�}mFmF/�Admin/Controller/Html/Configurations/Layout.phpnu�[���PK���['��L-L--OXAdmin/Controller/Html/Configurations/Page.phpnu�[���PK���[�Qޙ""1��Admin/Controller/Html/Configurations/Settings.phpnu�[���PK���[�[T�
/r�Admin/Controller/Html/Configurations/Styles.phpnu�[���PK���[���7VV(��Admin/Controller/Html/Configurations.phpnu�[���PK���[��_iEE
��Admin/Controller/Html/Export.phpnu�[���PK���[�?�C}
}
#�Admin/Controller/Html/Import.phpnu�[���PK���[�^�ww!�Admin/Controller/Html/Install.phpnu�[���PK���[
����F�F�Admin/Controller/Html/Menu.phpnu�[���PK���[�,�ȵ*�*#�MAdmin/Controller/Html/Positions.phpnu�[���PK���[�����
�xAdmin/Controller/Html/Themes.phpnu�[���PK���[��z66
|Admin/Controller/Json/Atoms.phpnu�[���PK���[7��]��#��Admin/Controller/Json/Changelog.phpnu�[���PK���[�)����)ȞAdmin/Controller/Json/Confirmdeletion.phpnu�[���PK���[�����!��Admin/Controller/Json/Devprod.phpnu�[���PK���[
PQ�>�>$ȧAdmin/Controller/Json/Filepicker.phpnu�[���PK���[��l�
�
$��Admin/Controller/Json/Fontpicker.phpnu�[���PK���[�u#S�F�F��Admin/Controller/Json/Icons.phpnu�[���PK���[�DEL
L
!�;Admin/Controller/Json/Layouts.phpnu�[���PK���[�e��))"T\Admin/Controller/Json/Particle.phpnu�[���PK���[�P_�%%!�uAdmin/Controller/Json/Unsaved.phpnu�[���PK���[譤��EyAdmin/EventListener.phpnu�[���PK���[uTQ'3�Admin/Page.phpnu�[���PK���[�Ht�����Admin/Particles.phpnu�[���PK���[�w�22��Admin/Router.phpnu�[���PK���[\��Ɵ
�
%�Admin/Styles.phpnu�[���PK���[�Y�zpp�Admin/Theme.phpnu�[���PK���[܁l��Admin/ThemeList.phpnu�[���PK���[�(r��"u�Component/Admin/HtmlController.phpnu�[���PK���[��p���"�Component/Admin/JsonController.phpnu�[���PK���[ܵ����-�Component/Assignments/AbstractAssignments.phpnu�[���PK���[�d�//**$Component/Assignments/AssignmentFilter.phpnu�[���PK���[3�U���.�7Component/Assignments/AssignmentsInterface.phpnu�[���PK���[�)!�99#�:Component/Collection/Collection.phpnu�[���PK���[�?�~~,�@Component/Collection/CollectionInterface.phpnu�[���PK���[�c��9$9$"eEComponent/Config/BlueprintForm.phpnu�[���PK���[ù���$�iComponent/Config/BlueprintSchema.phpnu�[���PK���[�-��!5�Component/Config/CompiledBase.phpnu�[���PK���[�ԂDD'�Component/Config/CompiledBlueprints.phpnu�[���PK���[��ͭ
#��Component/Config/CompiledConfig.phpnu�[���PK���[Ѱ�Pdd�Component/Config/Config.phpnu�[���PK���[ҽ`\!\!%��Component/Config/ConfigFileFinder.phpnu�[���PK���[��VVu�Component/Config/Validation.phpnu�[���PK���[��"(�FComponent/Config/ValidationException.phpnu�[���PK���[#NJ���()KComponent/Content/Block/ContentBlock.phpnu�[���PK���[{�?:xx1TbComponent/Content/Block/ContentBlockInterface.phpnu�[���PK���[��ue�2�2%-fComponent/Content/Block/HtmlBlock.phpnu�[���PK���[�v*B��./�Component/Content/Block/HtmlBlockInterface.phpnu�[���PK���[ �Q��i�i+U�Component/Content/Document/HtmlDocument.phpnu�[���PK���[,���'�Component/Controller/BaseController.phpnu�[���PK���[���00'�!Component/Controller/HtmlController.phpnu�[���PK���[0s���'�&Component/Controller/JsonController.phpnu�[���PK���[�VVaa3�*Component/Controller/RestfulControllerInterface.phpnu�[���PK���[��7���1Component/File/CompiledFile.phpnu�[���PK���[{BB#�AComponent/File/CompiledYamlFile.phpnu�[���PK���[�{�+�+oEComponent/Filesystem/Folder.phpnu�[���PK���[ڀ}e
OqComponent/Filesystem/Streams.phpnu�[���PK���[����WW
�|Component/Gantry/GantryTrait.phpnu�[���PK���[�;o�S�Component/Gettext/Gettext.phpnu�[���PK���[�xх������Component/Layout/Layout.phpnu�[���PK���[.|�G
!�Component/Layout/LayoutReader.phpnu�[���PK���[Q�E���$NComponent/Layout/Version/Format0.phpnu�[���PK���[��+�#�#$#%Component/Layout/Version/Format1.phpnu�[���PK���[��]��E�E$@IComponent/Layout/Version/Format2.phpnu�[���PK���[j픞--Z�Component/Menu/AbstractMenu.phpnu�[���PK���[��1D�&�&¼Component/Menu/Item.phpnu�[���PK���[�{{GLGL'��Component/Outline/OutlineCollection.phpnu�[���PK���[�T�ڍ�c0Component/Position/Module.phpnu�[���PK���[�l*�)#)#=AComponent/Position/Position.phpnu�[���PK���[���..
�dComponent/Position/Positions.phpnu�[���PK���[���O��3~Component/Remote/Response.phpnu�[���PK���[��N@
�Component/Request/Input.phpnu�[���PK���[(5���f�Component/Request/Request.phpnu�[���PK���[]�>J��#��Component/Response/HtmlResponse.phpnu�[���PK���[(�gg#��Component/Response/JsonResponse.phpnu�[���PK���[�~�77'a�Component/Response/RedirectResponse.phpnu�[���PK���[ʚ@%����Component/Response/Response.phpnu�[���PK���[V�99 �Component/Router/Router.phpnu�[���PK���[�M�6��$��Component/Router/RouterInterface.phpnu�[���PK���[X}�q&q&$��Component/Stylesheet/CssCompiler.phpnu�[���PK���[�03��-{Component/Stylesheet/CssCompilerInterface.phpnu�[���PK���[�d瑄,�,&�Component/Stylesheet/Scss/Compiler.phpnu�[���PK���[�}��%�FComponent/Stylesheet/ScssCompiler.phpnu�[���PK���[�i}}�`Component/System/Messages.phpnu�[���PK���[�Y�22!�cComponent/Theme/AbstractTheme.phpnu�[���PK���[�����
�Component/Theme/ThemeDetails.phpnu�[���PK���[1���%�%"M�Component/Theme/ThemeInstaller.phpnu�[���PK���[��IA��"��Component/Theme/ThemeInterface.phpnu�[���PK���[b����Z�Z��Component/Theme/ThemeTrait.phpnu�[���PK���[$�E��
�
#) Component/Translator/Translator.phpnu�[���PK���[�f��GG,)7 Component/Translator/TranslatorInterface.phpnu�[���PK���[�Ϸ�&�: Component/Twig/Node/TwigNodeAssets.phpnu�[���PK���[���y��(�C Component/Twig/Node/TwigNodeMarkdown.phpnu�[���PK���[7n^c��)�I Component/Twig/Node/TwigNodePageblock.phpnu�[���PK���[�ܽ���'�R Component/Twig/Node/TwigNodeScripts.phpnu�[���PK���[JtE5��&'U Component/Twig/Node/TwigNodeStyles.phpnu�[���PK���[�$�� &kW Component/Twig/Node/TwigNodeSwitch.phpnu�[���PK���[�K��%�_ Component/Twig/Node/TwigNodeThrow.phpnu�[���PK���[Bh���(�d Component/Twig/Node/TwigNodeTryCatch.phpnu�[���PK���[��5��
�
0�k Component/Twig/TokenParser/TokenParserAssets.phpnu�[���PK���[B�$��2�v Component/Twig/TokenParser/TokenParserMarkdown.phpnu�[���PK���[I��\ \ 3�| Component/Twig/TokenParser/TokenParserPageblock.phpnu�[���PK���[
FX���1�� Component/Twig/TokenParser/TokenParserScripts.phpnu�[���PK���[�++B��0� Component/Twig/TokenParser/TokenParserStyles.phpnu�[���PK���[���#��0� Component/Twig/TokenParser/TokenParserSwitch.phpnu�[���PK���[�ʱtt/_� Component/Twig/TokenParser/TokenParserThrow.phpnu�[���PK���[�TLL22� Component/Twig/TokenParser/TokenParserTryCatch.phpnu�[���PK���[�
�&� Component/Twig/TwigCacheFilesystem.phpnu�[���PK���[K�
k�Q�Q
S� Component/Twig/TwigExtension.phpnu�[���PK���[��6���Z
Component/Url/Url.phpnu�[���PK���[�H��AA!x
Component/Whoops/SystemFacade.phpnu�[���PK���[JH��CC
,
Framework/Assignments.phpnu�[���PK���[�����$�$�C
Framework/Atoms.phpnu�[���PK���["��{�$�$�h
Framework/Base/Gantry.phpnu�[���PK���[B�s�MM��
Framework/Base/Page.phpnu�[���PK���[qyX~��O�
Framework/Base/Platform.phpnu�[���PK���[3�S��r�
Framework/Base/Site.phpnu�[���PK���[�1L�GG]�
Framework/Base/Theme.phpnu�[���PK���[�.���
Framework/Configurations.phpnu�[���PK���[4y,cc�
Framework/Document.phpnu�[���PK���[�NE��
Framework/Exception.phpnu�[���PK���[��(�+�+�
Framework/Exporter.phpnu�[���PK���[��D���NFramework/Gantry.phpnu�[���PK���["�����
m
Framework/Markdown/Parsedown.phpnu�[���PK���[S�kn��%T
Framework/Markdown/ParsedownExtra.phpnu�[���PK���[TD���%�Framework/Markdown/ParsedownTrait.phpnu�[���PK���[��.@2@2�!Framework/Menu.phpnu�[���PK���[�~���!�!ATFramework/Outlines.phpnu�[���PK���[�%jȌ�_vFramework/Page.phpnu�[���PK���["��υB�B-�Framework/Platform.phpnu�[���PK���[�8����Framework/Positions.phpnu�[���PK���[�l�$��4�Framework/Request.phpnu�[���PK���[#Q�ii,d�Framework/Services/ConfigServiceProvider.phpnu�[���PK���[��d��+)�Framework/Services/ErrorServiceProvider.phpnu�[���PK���[�I>44-m�Framework/Services/StreamsServiceProvider.phpnu�[���PK���[�ɿ�mm��Framework/Site.phpnu�[���PK���[7*3�����Framework/Theme.phpnu�[���PK���["ݲc�E�EwFramework/ThemeInstaller.phpnu�[���PK���[��g\\MLFramework/Translator.phpnu�[���PK���[J�s33&�NJoomla/Assignments/AssignmentsMenu.phpnu�[���PK���[=�|���'zWJoomla/Assignments/AssignmentsStyle.phpnu�[���PK���[��b_Joomla/CacheHelper.phpnu�[���PK���[*�����eJoomla/Category/Category.phpnu�[���PK���[&��w;;"�lJoomla/Category/CategoryFinder.phpnu�[���PK���[��-��J}Joomla/Content/Content.phpnu�[���PK���[=3���
+�Joomla/Content/ContentFinder.phpnu�[���PK���[�v!��6�Joomla/Manifest.phpnu�[���PK���[�]k���M�Joomla/Module/Module.phpnu�[���PK���[�Y����"9�Joomla/Module/ModuleCollection.phpnu�[���PK���[�.�H
H
v�Joomla/Module/ModuleFinder.phpnu�[���PK���[嶱�2�2
�Joomla/Object/AbstractObject.phpnu�[���PK���[�g����V
Joomla/Object/Collection.phpnu�[���PK���[T��BB�
Joomla/Object/Finder.phpnu�[���PK���[�`�
�
$
Joomla/StyleHelper.phpnu�[���PK���[h��(,
Joomla/TemplateInstaller.phpnu�[���PK��<.