Commit 326af91906814cb519afeb0bc752c70e0be82b79

Authored by mzavalniuk
1 parent 16f1e516

add artbox-core to repo

Showing 183 changed files with 16055 additions and 0 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 183 files are displayed.

artweb/artbox-core/CHANGELOG.md 0 → 100755
  1 +# Change Log
  2 +All notable changes to this project will be documented in this file.
  3 +
  4 +## 1.0.0 - 2017-03-21
  5 +### Added
  6 +- This CHANGELOG file to hopefully serve as an evolving example of a standardized open source project CHANGELOG.
  7 +- Added initial Artbox Core extension.
0 8 \ No newline at end of file
... ...
artweb/artbox-core/LICENSE.md 0 → 100755
  1 +The Yii framework is free software. It is released under the terms of
  2 +the following BSD License.
  3 +
  4 +Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com)
  5 +All rights reserved.
  6 +
  7 +Redistribution and use in source and binary forms, with or without
  8 +modification, are permitted provided that the following conditions
  9 +are met:
  10 +
  11 + * Redistributions of source code must retain the above copyright
  12 + notice, this list of conditions and the following disclaimer.
  13 + * Redistributions in binary form must reproduce the above copyright
  14 + notice, this list of conditions and the following disclaimer in
  15 + the documentation and/or other materials provided with the
  16 + distribution.
  17 + * Neither the name of Yii Software LLC nor the names of its
  18 + contributors may be used to endorse or promote products derived
  19 + from this software without specific prior written permission.
  20 +
  21 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24 +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25 +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27 +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  29 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30 +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31 +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32 +POSSIBILITY OF SUCH DAMAGE.
... ...
artweb/artbox-core/README.md 0 → 100755
  1 +Artbox Core
  2 +===============================
  3 +
  4 +Artbox Core is a core extension of light-weight CMS developed by Artweb written with
  5 +[Yii 2 framework](http://www.yiiframework.com/).
  6 +
  7 +Core extension includes functionality for app Internationalization, basic SEO optimization,
  8 +feedback, image manipulation, user data and static pages control. Also provides events
  9 +notifications.
  10 +
  11 +This extension is enough to develop landings or small websites with static pages.
  12 +
  13 +To prepare your application you should run migrations:
  14 +
  15 + php yii migrate --migationPath=vendor/artweb/artbox-core/migrations
  16 +
  17 +DIRECTORY STRUCTURE
  18 +-------------------
  19 +
  20 +```
  21 +assets contains AssetBundles
  22 +behaviors contains Behaviors classes
  23 +components contains custom Classes, which don't belong to other groups
  24 +controllers contains controllers for core models
  25 +helpers contains helper classes to manipulate, for example static files
  26 + and HTML
  27 +messages contains translations for core strings
  28 +migrations contains migrations, which should be applied after extension
  29 + installation
  30 +models contains core models
  31 +views contains views files for core controllers
  32 +web contains assets and other files, which should be web available
  33 +widgets contains widgets
  34 +```
... ...
artweb/artbox-core/assets/ArtboxAmChartAsset.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\assets;
  4 +
  5 + use yii\web\AssetBundle;
  6 +
  7 + /**
  8 + * Class ArtboxAmChartAsset
  9 + *
  10 + * @package artbox\core\assets
  11 + */
  12 + class ArtboxAmChartAsset extends AssetBundle
  13 + {
  14 + public $sourcePath = '@bower/amcharts/dist/amcharts';
  15 + public $css = [];
  16 + public $js = [
  17 + 'amcharts.js',
  18 + 'serial.js',
  19 + 'pie.js',
  20 + ];
  21 + public $depends = [
  22 + 'yii\web\JqueryAsset',
  23 + 'yii\bootstrap\BootstrapAsset',
  24 + ];
  25 +
  26 + }
0 27 \ No newline at end of file
... ...
artweb/artbox-core/assets/ArtboxCoreAsset.php 0 → 100755
  1 +<?php
  2 + namespace artbox\core\assets;
  3 +
  4 + use yii\web\AssetBundle;
  5 +
  6 + /**
  7 + * Asset class for artbox-core
  8 + */
  9 + class ArtboxCoreAsset extends AssetBundle
  10 + {
  11 + /**
  12 + * @inheritdoc
  13 + */
  14 + public $sourcePath = '@artbox/core/web';
  15 +
  16 + /**
  17 + * @inheritdoc
  18 + */
  19 + public $css = [
  20 + 'css/styles.css',
  21 + ];
  22 +
  23 + /**
  24 + * @inheritdoc
  25 + */
  26 + public $js = [
  27 + 'js/script.js',
  28 + ];
  29 +
  30 + public $depends = [
  31 + 'yiister\gentelella\assets\Asset',
  32 + 'hiqdev\assets\icheck\iCheckAsset',
  33 + 'hiqdev\assets\pnotify\PNotifyAsset',
  34 + ];
  35 + }
... ...
artweb/artbox-core/assets/GalleryAsset.php 0 → 100644
  1 +<?php
  2 +
  3 + namespace artbox\core\assets;
  4 +
  5 + use yii\web\AssetBundle;
  6 +
  7 + /**
  8 + * Class GalleryAsset
  9 + *
  10 + * @package artbox\core\assets
  11 + */
  12 + class GalleryAsset extends AssetBundle
  13 + {
  14 + public $sourcePath = '@artbox/core/assets/src';
  15 +
  16 + public $js = [
  17 + 'js/galleryWidget.js',
  18 + ];
  19 +
  20 + public $depends = [
  21 + 'artbox\core\components\imagemanager\assets\ImageManagerInputAsset',
  22 + ];
  23 + }
0 24 \ No newline at end of file
... ...
artweb/artbox-core/assets/src/js/galleryWidget.js 0 → 100755
  1 +$(
  2 + function() {
  3 + $(document)
  4 + .on(
  5 + 'change', '.gw-image-input', function() {
  6 + var input = this;
  7 + $.ajax(
  8 + {
  9 + url: '/admin/imagemanager/manager/view',
  10 + type: "POST",
  11 + data: {
  12 + 'ImageManager_id': input.value
  13 + },
  14 + success: function(data) {
  15 + $(
  16 + '#' + $(input)
  17 + .data('img')
  18 + )
  19 + .attr('src', data.image);
  20 + $(
  21 + '#' + $(input)
  22 + .data('name')
  23 + )
  24 + .html(data.fileName);
  25 + }
  26 + }
  27 + );
  28 + }
  29 + );
  30 +
  31 + $(document)
  32 + .on(
  33 + 'click', '#add-image', function() {
  34 + var hash = Math.floor(Math.random() * 89999) + 10000;
  35 + var content = '<div class="col-md-2 gw-item"><input id="' + hash + '" class="gw-image-input" name ="images[' + hash + ']" ' + 'data-img="' + hash + '_img" data-name="' + hash + '_name" type ="hidden"> ' + '<div class="image_gall"><img id="' + hash + '_img" alt=""></div>' + '<p id="' + hash + '_name" class="text-info"></p>' + '<button type="button" class="open-modal-imagemanager btn btn-primary" data-aspect-ratio="" data-crop-view-mode="1" ' + 'data-input-id="' + hash + '"><i class="fa fa-folder-open"></i></button><button type="button" class="remove-img btn btn-danger">' + '<i class="fa fa-trash"></i></button></div>';
  36 + $('.gw-container')
  37 + .append(content);
  38 + // if (document.querySelectorAll(".gw-container > .gw-item").length % 3 === 0) {
  39 + // $('.gw-container').append('<div class="clearfix"></div>');
  40 + // }
  41 + }
  42 + );
  43 + $(document)
  44 + .on(
  45 + 'click', '.remove-img', function() {
  46 + $(this)
  47 + .parent()
  48 + .remove();
  49 + }
  50 + )
  51 + }
  52 +);
0 53 \ No newline at end of file
... ...
artweb/artbox-core/behaviors/BitMaskBehavior.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\behaviors;
  4 +
  5 + use yii\base\Behavior;
  6 + use yii\web\Request;
  7 +
  8 + /**
  9 + * Class BitMaskBehavior
  10 + *
  11 + * @package artbox\core\behaviors
  12 + */
  13 + class BitMaskBehavior extends Behavior
  14 + {
  15 + /**
  16 + * Field for the mask
  17 + *
  18 + * @var array
  19 + */
  20 + public $fields;
  21 +
  22 + /**
  23 + * Param for storing masks
  24 + *
  25 + * @var
  26 + */
  27 + public $masks;
  28 +
  29 + /**
  30 + * Db field for storing mask integer value
  31 + *
  32 + * @var string
  33 + */
  34 + public $maskField = 'mask';
  35 +
  36 + /**
  37 + * Generate the integer mask from request
  38 + *
  39 + * @param \yii\web\Request $request
  40 + */
  41 + public function loadMask(Request $request)
  42 + {
  43 + $owner = $this->owner;
  44 + $maskField = $this->maskField;
  45 + if (isset($request->post($this->getModelName())[ 'masks' ])) {
  46 + $masks = $request->post($this->getModelName())[ 'masks' ];
  47 + } else {
  48 + if ($request->isPost) {
  49 + $owner->$maskField = 0;
  50 + return;
  51 + } else {
  52 + return;
  53 + }
  54 + }
  55 +
  56 + $owner->$maskField = 0;
  57 + foreach ($masks as $mask => $value) {
  58 + if ($value == '1') {
  59 + $owner->$maskField += 2 ** (int) $this->fields[ $mask ];
  60 + }
  61 + }
  62 + }
  63 +
  64 + /**
  65 + * Get the value of the owners mask field
  66 + *
  67 + * @return mixed
  68 + */
  69 + public function getMaskInt()
  70 + {
  71 + $maskField = $this->maskField;
  72 + return $this->owner->$maskField;
  73 + }
  74 +
  75 + /**
  76 + * Return the name of the owner's model
  77 + * without namespaces
  78 + *
  79 + * @return string
  80 + */
  81 + public function getModelName()
  82 + {
  83 + $owner = $this->owner;
  84 + $arr = explode('\\', get_class($owner));
  85 + return array_pop($arr);
  86 + }
  87 +
  88 + /**
  89 + * Checks the value
  90 + *
  91 + * @param string $field
  92 + *
  93 + * @return bool
  94 + */
  95 + public function is(string $field)
  96 + {
  97 + if (array_key_exists($field, $this->fields)) {
  98 + $result = $this->getMaskInt() & 2 ** $this->fields[ $field ];
  99 + if ($result === 0) {
  100 + return false;
  101 + } else {
  102 + return true;
  103 + }
  104 + } else {
  105 + return false;
  106 + }
  107 + }
  108 + }
0 109 \ No newline at end of file
... ...
artweb/artbox-core/behaviors/GalleryBehavior.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\behaviors;
  4 +
  5 + use artbox\core\models\Image;
  6 + use yii\base\Behavior;
  7 + use yii\db\ActiveRecord;
  8 + use yii\helpers\Json;
  9 +
  10 + /**
  11 + * Class GalleryBehavior
  12 + *
  13 + * @package artbox\core\behaviors\
  14 + * @property ActiveRecord $owner
  15 + */
  16 + class GalleryBehavior extends Behavior
  17 + {
  18 + /**
  19 + * @var string Name of the field in owner's table where gallery will be saved
  20 + */
  21 + public $gallery_field = 'gallery';
  22 +
  23 + /**
  24 + * @return array
  25 + */
  26 + public function getImages(): array
  27 + {
  28 + $gallery_field = $this->gallery_field;
  29 +
  30 + if (empty(Json::decode($this->owner->$gallery_field))) {
  31 + return [];
  32 + }
  33 +
  34 + return Image::find()
  35 + ->filterWhere([ 'id' => Json::decode($this->owner->$gallery_field)])
  36 + ->all();
  37 + }
  38 +
  39 + /**
  40 + * @param array $post
  41 + *
  42 + * @return bool
  43 + */
  44 + public function saveImages(array $post): bool
  45 + {
  46 + $gallery_field = $this->gallery_field;
  47 +
  48 + $to_save = [];
  49 + foreach ($post[ 'images' ] as $image) {
  50 + /**
  51 + * Can make additional validation here
  52 + */
  53 + if (!empty($image)) {
  54 + $to_save[] = $image;
  55 + }
  56 + }
  57 +
  58 + $this->owner->$gallery_field = Json::encode($to_save);
  59 +
  60 + return $this->owner->save();
  61 + }
  62 + }
0 63 \ No newline at end of file
... ...
artweb/artbox-core/behaviors/LinkBehavior.php 0 → 100755
  1 +<?php
  2 + namespace artbox\core\behaviors;
  3 +
  4 + use yii\base\Behavior;
  5 + use yii\base\Event;
  6 + use yii\base\InvalidConfigException;
  7 + use yii\base\Object;
  8 + use yii\db\ActiveRecord;
  9 + use yii\web\NotFoundHttpException;
  10 +
  11 + /**
  12 + * Class LinkBehavior
  13 + * Behavior to create linked object after inserting parent object.
  14 + */
  15 + class LinkBehavior extends Behavior
  16 + {
  17 + /**
  18 + * Key in parent object to link. Default to primaryKey()[0]
  19 + *
  20 + * @var string $parentKey
  21 + */
  22 + public $parentKey;
  23 +
  24 + /**
  25 + * Fully-namespaced class to be linked. Required.
  26 + *
  27 + * @var string $linkClass
  28 + */
  29 + public $linkClass;
  30 +
  31 + /**
  32 + * Key in link object. Default to primaryKey()[0]
  33 + *
  34 + * @var string $linkKey
  35 + */
  36 + public $linkKey;
  37 +
  38 + /**
  39 + * Named behaviors to be detached from link object before insertion.
  40 + *
  41 + * @var array
  42 + */
  43 + public $detachBehaviors = [];
  44 +
  45 + /**
  46 + * @var ActiveRecord $linkClassInstance
  47 + */
  48 + protected $linkClassInstance;
  49 +
  50 + /**
  51 + * @inheritdoc
  52 + */
  53 + public function events()
  54 + {
  55 + return [
  56 + ActiveRecord::EVENT_AFTER_INSERT => 'linkObject',
  57 + ];
  58 + }
  59 +
  60 + /**
  61 + * @inheritdoc
  62 + */
  63 + public function attach($owner)
  64 + {
  65 + parent::attach($owner);
  66 + $this->checkValidity();
  67 + }
  68 +
  69 + /**
  70 + * Save link object.
  71 + *
  72 + * @param Event $event Handler for insertion success
  73 + *
  74 + * @return \yii\db\ActiveRecord
  75 + * @throws \yii\base\InvalidConfigException
  76 + */
  77 + public function linkObject($event = null)
  78 + {
  79 + $owner = $this->owner;
  80 + /**
  81 + * @var ActiveRecord $linkClassInstance
  82 + */
  83 + $linkClassInstance = $this->linkClassInstance;
  84 + $value = null;
  85 + if ($owner->canGetProperty($this->parentKey, true, false)) {
  86 + $key = $this->parentKey;
  87 + $value = $owner->$key;
  88 + } else {
  89 + throw new InvalidConfigException(\Yii::t('core', 'Can\'t get $parentKey property'));
  90 + }
  91 + if (empty( $value )) {
  92 + throw new InvalidConfigException(\Yii::t('core', "Can't get parent key {$key}"));
  93 + }
  94 + $linkClassInstance->setAttribute($this->linkKey, $value);
  95 + foreach ($this->detachBehaviors as $name) {
  96 + if (is_string($name)) {
  97 + $linkClassInstance->detachBehavior($name);
  98 + }
  99 + }
  100 + $linkClassInstance->save();
  101 + return $linkClassInstance;
  102 + }
  103 +
  104 + /**
  105 + * Check if $linkClassInstance ready to be inserted, otherwise throw exception
  106 + *
  107 + * @throws \yii\base\InvalidConfigException
  108 + */
  109 + protected function checkValidity()
  110 + {
  111 + $owner = $this->owner;
  112 + if (empty( $this->linkClass )) {
  113 + throw new InvalidConfigException(\Yii::t('core', 'Link class must be set'));
  114 + } else {
  115 + $this->linkClassInstance = \Yii::createObject($this->linkClass);
  116 + if (!$this->linkClassInstance instanceof ActiveRecord) {
  117 + throw new InvalidConfigException(
  118 + \Yii::t('core', 'Link class must be instance of yii\db\ActiveRecord')
  119 + );
  120 + }
  121 + }
  122 + /** @noinspection PhpParamsInspection */
  123 + $this->ensureAttribute('parentKey', $owner);
  124 + /** @noinspection PhpParamsInspection */
  125 + $this->ensureAttribute('linkKey', $this->linkClassInstance);
  126 + if (empty( $this->parentKey ) || empty( $this->linkKey )) {
  127 + throw new InvalidConfigException(
  128 + \Yii::t(
  129 + 'core',
  130 + '$parentKey and $linkKey must be set or use ActiveRecord to get its primaryKey()[0] attributes.'
  131 + )
  132 + );
  133 + }
  134 + if (!$owner->canGetProperty($this->parentKey, true, false)) {
  135 + throw new InvalidConfigException(\Yii::t('core', 'Can\'t get $parentKey property'));
  136 + }
  137 + }
  138 +
  139 + /**
  140 + * Bind keys to default properties if keys empty.
  141 + *
  142 + * @param string $property Property to bind
  143 + * @param Object $object Property owner
  144 + */
  145 + protected function ensureAttribute(string $property, Object $object)
  146 + {
  147 + if (empty( $this->$property )) {
  148 + if ($object instanceof ActiveRecord) {
  149 + $pks = $object->primaryKey();
  150 + if (!empty( $pks )) {
  151 + $this->$property = $pks[ 0 ];
  152 + }
  153 + }
  154 + }
  155 + }
  156 +
  157 + /**
  158 + * Generate link object an d save it directly.
  159 + *
  160 + * @return ActiveRecord
  161 + */
  162 + public function ensureExistance()
  163 + {
  164 + $link = $this->getLinkObject();
  165 + if (!$link) {
  166 + $link = $this->linkObject();
  167 + }
  168 + return $link;
  169 + }
  170 +
  171 + /**
  172 + * Get link object
  173 + *
  174 + * @param bool $throw Whether to throw exception if link object not found
  175 + *
  176 + * @return null|\yii\db\ActiveRecord
  177 + * @throws \yii\web\NotFoundHttpException
  178 + */
  179 + public function getLinkObject(bool $throw = false)
  180 + {
  181 + /**
  182 + * @var ActiveRecord $linkClassInstance
  183 + */
  184 + $linkClassInstance = $this->linkClassInstance;
  185 + $owner = $this->owner;
  186 + $parentKey = $this->parentKey;
  187 + /**
  188 + * @var ActiveRecord $result
  189 + */
  190 + $result = $linkClassInstance::find()
  191 + ->where([ $this->linkKey => $this->owner->$parentKey ])
  192 + ->one();
  193 + if ($throw && !$result) {
  194 + throw new NotFoundHttpException(\Yii::t('core', "Linked object for {$owner::className()} not found"));
  195 + }
  196 + return $result;
  197 + }
  198 + }
0 199 \ No newline at end of file
... ...
artweb/artbox-core/behaviors/ManyToManyBehavior.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\behaviors;
  4 +
  5 + use yii\base\Behavior;
  6 + use yii\db\ActiveRecord;
  7 +
  8 + /**
  9 + * Class ManyToManyBehavior
  10 + *
  11 + * @package artbox\catalog\behaviors
  12 + */
  13 + class ManyToManyBehavior extends Behavior
  14 + {
  15 + /**
  16 + * @param string $name
  17 + * @param ActiveRecord[] $models
  18 + * @param array $extraColumns
  19 + */
  20 + public function linkMany(string $name, array $models, array $extraColumns = [])
  21 + {
  22 + /**
  23 + * @var ActiveRecord $owner
  24 + */
  25 + $owner = $this->owner;
  26 +
  27 + $owner->unlinkAll($name, true);
  28 +
  29 + foreach ($models as $model) {
  30 + $owner->link($name, $model, $extraColumns);
  31 + }
  32 + }
  33 + }
0 34 \ No newline at end of file
... ...
artweb/artbox-core/behaviors/SlugBehavior.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\behaviors;
  4 +
  5 + use artbox\core\helpers\SlugHelper;
  6 + use artbox\core\models\Alias;
  7 + use yii;
  8 + use yii\base\Behavior;
  9 + use yii\base\ErrorException;
  10 + use yii\db\ActiveRecord;
  11 + use yii\helpers\Json;
  12 +
  13 + /**
  14 + * Class SlugBehavior
  15 + * Behavior to generate and maintain connection with aliases.
  16 + *
  17 + * @property ActiveRecord $owner
  18 + */
  19 + class SlugBehavior extends Behavior
  20 + {
  21 +
  22 + /**
  23 + * Attribute from which slug should be generated
  24 + *
  25 + * @var string
  26 + */
  27 + public $inAttribute = 'title';
  28 +
  29 + /**
  30 + * Attribute which holds link to Alias
  31 + *
  32 + * @var int
  33 + */
  34 + public $outAttribute = 'alias_id';
  35 +
  36 + /**
  37 + * Action which should be called after parsing Url
  38 + *
  39 + * @var string
  40 + */
  41 + public $action;
  42 +
  43 + /**
  44 + * Params which should be passed to controller action
  45 + *
  46 + * @var array
  47 + */
  48 + public $params;
  49 +
  50 + /**
  51 + * Whether to use transit or just replace non-alphabetic symbols.
  52 + *
  53 + * @var bool
  54 + */
  55 + public $translit = true;
  56 +
  57 + /**
  58 + * Fields available in for SEO.
  59 + *
  60 + * @var array
  61 + */
  62 + public $fields = [];
  63 +
  64 + /**
  65 + * Get Alias $value for $owner.
  66 + * If needed db request would be used only once.
  67 + *
  68 + * @var string $aliasValue
  69 + */
  70 + protected $aliasValue = null;
  71 +
  72 + /**
  73 + * Current Alias model for $owner.
  74 + *
  75 + * @var Alias|null $currentAlias
  76 + */
  77 + private $currentAlias;
  78 +
  79 + /**
  80 + * Whether db query to get Alias already executed, means that request won't be made until force flag is set.
  81 + *
  82 + * @var bool $executed
  83 + */
  84 + private $executed = false;
  85 +
  86 + /**
  87 + * @inheritdoc
  88 + */
  89 + public function events()
  90 + {
  91 + return [
  92 + ActiveRecord::EVENT_AFTER_INSERT => 'getSlug',
  93 + ActiveRecord::EVENT_AFTER_UPDATE => 'getSlug',
  94 + ActiveRecord::EVENT_BEFORE_DELETE => 'deleteSlug',
  95 + ];
  96 + }
  97 +
  98 + /**
  99 + * @inheritdoc
  100 + */
  101 + public function attach($owner)
  102 + {
  103 + parent::attach($owner);
  104 + if (!$owner instanceof ActiveRecord) {
  105 + throw new yii\base\InvalidConfigException(
  106 + \Yii::t('core', 'SlugBeahvior can only be attached to the instance of ActiveRecord')
  107 + );
  108 + }
  109 + }
  110 +
  111 + /**
  112 + * Generate slug
  113 + *
  114 + * @param yii\base\Event $event
  115 + *
  116 + * @return void
  117 + */
  118 + public function getSlug($event)
  119 + {
  120 + /**
  121 + * @var string $attribute_value
  122 + */
  123 + $attribute_value = $this->owner->getAttribute($this->inAttribute);
  124 + if (!empty($attribute_value)) {
  125 + /**
  126 + * @var string $alias_value
  127 + */
  128 + $alias_value = $this->aliasValue;
  129 + $this->currentAlias = $this->findCurrentAlias();
  130 + if (empty($alias_value)) {
  131 + $result = $this->generateSlug($attribute_value);
  132 + } else {
  133 + $result = $this->generateSlug($alias_value);
  134 + }
  135 + $this->saveSlug($result);
  136 + }
  137 + }
  138 +
  139 + /**
  140 + * Delete slug
  141 + *
  142 + * @param yii\base\Event $event
  143 + *
  144 + * @return void
  145 + */
  146 + public function deleteSlug($event)
  147 + {
  148 + if (!empty($current = $this->findCurrentAlias())) {
  149 + $current->delete();
  150 + }
  151 + }
  152 +
  153 + /**
  154 + * Get current Alias. Db query will be made first time or if $force flag is set.
  155 + *
  156 + * @param bool $force
  157 + *
  158 + * @return \artbox\core\models\Alias|null
  159 + */
  160 + public function findCurrentAlias($force = false)
  161 + {
  162 + if ($force || !$this->executed) {
  163 + /**
  164 + * @var int $alias_id
  165 + */
  166 + $alias_id = $this->owner->getAttribute($this->outAttribute);
  167 + $currentAlias = null;
  168 + if (!empty($alias_id)) {
  169 + /**
  170 + * @var Alias|null $currentAlias
  171 + */
  172 + $currentAlias = Alias::find()
  173 + ->where(
  174 + [
  175 + 'id' => $alias_id,
  176 + ]
  177 + )
  178 + ->one();
  179 + }
  180 + $this->executed = true;
  181 + return $currentAlias;
  182 + } else {
  183 + return $this->currentAlias;
  184 + }
  185 + }
  186 +
  187 + /**
  188 + * Generate unique slug.
  189 + *
  190 + * @param string $slug
  191 + *
  192 + * @return string
  193 + */
  194 + private function generateSlug($slug)
  195 + {
  196 + $slug = $this->slugify($slug);
  197 + $languageId = null;
  198 + if ($this->owner->hasAttribute('language_id')) {
  199 + $languageId = $this->owner->getAttribute('language_id');
  200 + }
  201 + return SlugHelper::unify($slug, $this->currentAlias, $languageId);
  202 + }
  203 +
  204 + /**
  205 + * Generate slug from string according to $translit flag.
  206 + *
  207 + * @param string $slug
  208 + *
  209 + * @return string
  210 + */
  211 + private function slugify($slug)
  212 + {
  213 + if ($this->translit) {
  214 + return SlugHelper::slugify($slug);
  215 + } else {
  216 + return $this->slug($slug, '-', true);
  217 + }
  218 + }
  219 +
  220 + /**
  221 + * Replace non-alphabetic symbols with $replcement symbol.
  222 + *
  223 + * @param string $string
  224 + * @param string $replacement
  225 + * @param bool $lowercase
  226 + *
  227 + * @return string
  228 + */
  229 + private function slug($string, $replacement = '-', $lowercase = true)
  230 + {
  231 + $string = preg_replace('/[^\p{L}\p{Nd}]+/u', $replacement, $string);
  232 + $string = trim($string, $replacement);
  233 + return $lowercase ? strtolower($string) : $string;
  234 + }
  235 +
  236 + /**
  237 + * Check if $slug differs from current Alias value
  238 + *
  239 + * @param $slug
  240 + *
  241 + * @return bool
  242 + */
  243 + private function hasChanged($slug)
  244 + {
  245 + if (!empty($this->currentAlias) && $this->currentAlias->value === $slug) {
  246 + return false;
  247 + } else {
  248 + return true;
  249 + }
  250 + }
  251 +
  252 + /**
  253 + * If $slug differs from Db Alias value, updates current if exists or create new Alias row.
  254 + *
  255 + * @param $slug
  256 + *
  257 + * @throws \yii\base\ErrorException
  258 + */
  259 + protected function saveSlug($slug)
  260 + {
  261 + if (!$this->hasChanged($slug)) {
  262 + return;
  263 + } else {
  264 + $route = $this->buildRoute();
  265 + $owner = $this->owner;
  266 + if (empty($alias = $this->findCurrentAlias())) {
  267 + /**
  268 + * @var Alias $alias
  269 + */
  270 + $alias = \Yii::createObject(
  271 + Alias::className(),
  272 + [
  273 + [
  274 + 'value' => $slug,
  275 + 'route' => $route,
  276 + 'entity' => $owner::className(),
  277 + 'title' => $owner->getAttribute($this->inAttribute),
  278 + 'h1' => $owner->getAttribute($this->inAttribute),
  279 + 'fields' => Json::encode($this->fields),
  280 + 'language_id' => $owner->getAttribute('language_id'),
  281 + ],
  282 + ]
  283 + );
  284 +
  285 + } else {
  286 + $alias->value = $slug;
  287 + $alias->route = $route;
  288 + $alias->entity = $owner::className();
  289 + $alias->language_id = $owner->getAttribute('language_id');
  290 + }
  291 + if ($alias->save()) {
  292 + $owner->{$this->outAttribute} = $alias->id;
  293 + $this->detach();
  294 + $owner->save(false, [ $this->outAttribute ]);
  295 + } else {
  296 + $alias = Alias::find()
  297 + ->where(
  298 + [
  299 + 'route' => $alias->route,
  300 + 'language_id' => $alias->language_id,
  301 + ]
  302 + )
  303 + ->one();
  304 + if ($alias) {
  305 + $owner->{$this->outAttribute} = $alias->id;
  306 + $this->detach();
  307 + $owner->save(false, [ $this->outAttribute ]);
  308 + } else {
  309 + throw new ErrorException(
  310 + \Yii::t(
  311 + 'core',
  312 + 'Alias cannot be saved: ' . Json::encode($alias) . '. Errors: ' . Json::encode(
  313 + $alias->getErrors()
  314 + )
  315 + )
  316 + );
  317 + }
  318 + }
  319 + }
  320 + }
  321 +
  322 + /**
  323 + * Get $aliasValue. Try to get from cached value and tries to get from Db if empty.
  324 + *
  325 + * @return string
  326 + */
  327 + public function getAliasValue()
  328 + {
  329 + if (empty($this->aliasValue) && !$this->executed) {
  330 + $currentAlias = $this->findCurrentAlias();
  331 + if (!empty($currentAlias)) {
  332 + $this->aliasValue = $currentAlias->value;
  333 + return $currentAlias->value;
  334 + }
  335 + }
  336 + return $this->aliasValue;
  337 + }
  338 +
  339 + /**
  340 + * Set $aliasValue
  341 + *
  342 + * @param $value
  343 + */
  344 + public function setAliasValue($value)
  345 + {
  346 + $this->aliasValue = $value;
  347 + }
  348 +
  349 + /**
  350 + * Build Json route from $action and $params fields.
  351 + *
  352 + * @return null|string
  353 + */
  354 + protected function buildRoute()
  355 + {
  356 + $owner = $this->owner;
  357 + $route = [];
  358 + $action = $this->action;
  359 + if (empty($action)) {
  360 + return null;
  361 + } else {
  362 + $route[ 0 ] = $action;
  363 + }
  364 + $params = $this->params;
  365 + if (!empty($params) && is_array($params)) {
  366 + foreach ($params as $param => $attribute) {
  367 + $attributeValue = $owner->getAttribute($attribute);
  368 + if (!empty($attributeValue)) {
  369 + $route[ $param ] = $attributeValue;
  370 + }
  371 + }
  372 + }
  373 + return Json::encode($route);
  374 + }
  375 + }
  376 +
0 377 \ No newline at end of file
... ...
artweb/artbox-core/components/AliasCache.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components;
  4 +
  5 + use artbox\core\models\Alias;
  6 + use artbox\core\models\Language;
  7 + use yii\base\InvalidParamException;
  8 + use yii\base\Object;
  9 + use yii\helpers\Json;
  10 +
  11 + class AliasCache extends Object
  12 + {
  13 + protected $aliases = [];
  14 +
  15 + /**
  16 + * Get cached Alias or execute callback in order to save new Alias to cache
  17 + *
  18 + * @param array $params
  19 + * @param \artbox\core\models\Language $language
  20 + * @param callable $callback
  21 + *
  22 + * @return \artbox\core\models\Alias|null
  23 + */
  24 + public function getOrSet(array $params, Language $language, callable $callback)
  25 + {
  26 + try {
  27 + $paramString = Json::encode($params);
  28 + if (array_key_exists($paramString, $this->aliases) && array_key_exists(
  29 + $language->id,
  30 + $this->aliases[ $paramString ]
  31 + )
  32 + ) {
  33 + return $this->aliases[ $paramString ][ $language->id ];
  34 + } else {
  35 + /**
  36 + * @var \artbox\core\models\Alias $result
  37 + */
  38 + $result = $callback();
  39 + $this->aliases[ $paramString ][ $language->id ] = $result;
  40 + return $result;
  41 + }
  42 + } catch (InvalidParamException $exception) {
  43 + }
  44 + return null;
  45 + }
  46 +
  47 + public function cache(Alias $alias)
  48 + {
  49 + $this->aliases[ Json::encode($alias->route) ][ $alias->language_id ] = $alias;
  50 + }
  51 + }
0 52 \ No newline at end of file
... ...
artweb/artbox-core/components/LanguageRequest.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components;
  4 +
  5 + use artbox\core\models\Language;
  6 + use yii\base\InvalidConfigException;
  7 + use yii\log\Logger;
  8 + use yii\web\Request;
  9 +
  10 + class LanguageRequest extends Request
  11 + {
  12 + /**
  13 + * Language model $url field for current request.
  14 + *
  15 + * @var string
  16 + */
  17 + private $languageUrl;
  18 +
  19 + /**
  20 + * Get $languageUrl from current Request Url.
  21 + *
  22 + * @return string
  23 + */
  24 + public function getLanguageUrl()
  25 + {
  26 + if ($this->languageUrl === null) {
  27 + $this->languageUrl = $this->getUrl();
  28 +
  29 + $url_list = explode('/', $this->languageUrl);
  30 +
  31 + $language_url = isset($url_list[ 1 ]) ? $url_list[ 1 ] : null;
  32 + if ($paramsPos = strpos($language_url, '?')) {
  33 + $language_url = substr($language_url, 0, $paramsPos);
  34 + }
  35 +
  36 + $is_language = Language::setCurrent($language_url);
  37 + if (!$is_language && !$this->isAjax) {
  38 + if (strpos($language_url, '.') === false && count(Language::getActive()) !== 1) {
  39 + \Yii::$app->response->redirect('/' . Language::getCurrent()->url . $this->url, 302, false);
  40 + } else {
  41 + \Yii::getLogger()
  42 + ->log(
  43 + "Url $language_url has extension '.' symbol in name. No language redirect applied.",
  44 + Logger::LEVEL_INFO,
  45 + 'artbox'
  46 + );
  47 + }
  48 + }
  49 +
  50 + if ($language_url !== null && $language_url === Language::getCurrent()->url && strpos(
  51 + $this->languageUrl,
  52 + Language::getCurrent()->url
  53 + ) === 1
  54 + ) {
  55 + $this->languageUrl = substr($this->languageUrl, strlen(Language::getCurrent()->url) + 1);
  56 + if (count(Language::getActive()) === 1 && !$this->isAjax) {
  57 + \Yii::$app->response->redirect('/', 302, false);
  58 + }
  59 + }
  60 + }
  61 + return $this->languageUrl;
  62 + }
  63 +
  64 + /**
  65 + * @inheritdoc
  66 + */
  67 + protected function resolvePathInfo()
  68 + {
  69 + $pathInfo = $this->getLanguageUrl();
  70 +
  71 + if (( $pos = strpos($pathInfo, '?') ) !== false) {
  72 + $pathInfo = substr($pathInfo, 0, $pos);
  73 + }
  74 +
  75 + $pathInfo = urldecode($pathInfo);
  76 +
  77 + if (!preg_match(
  78 + '%^(?:
  79 + [\x09\x0A\x0D\x20-\x7E]
  80 + | [\xC2-\xDF][\x80-\xBF]
  81 + | \xE0[\xA0-\xBF][\x80-\xBF]
  82 + | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}
  83 + | \xED[\x80-\x9F][\x80-\xBF]
  84 + | \xF0[\x90-\xBF][\x80-\xBF]{2}
  85 + | [\xF1-\xF3][\x80-\xBF]{3}
  86 + | \xF4[\x80-\x8F][\x80-\xBF]{2}
  87 + )*$%xs',
  88 + $pathInfo
  89 + )
  90 + ) {
  91 + $pathInfo = utf8_encode($pathInfo);
  92 + }
  93 +
  94 + $scriptUrl = $this->getScriptUrl();
  95 + $baseUrl = $this->getBaseUrl();
  96 +
  97 + if (strpos($pathInfo, $scriptUrl) === 0) {
  98 + $pathInfo = substr($pathInfo, strlen($scriptUrl));
  99 + } elseif ($baseUrl === '' || strpos($pathInfo, $baseUrl) === 0) {
  100 + $pathInfo = substr($pathInfo, strlen($baseUrl));
  101 + } elseif (isset($_SERVER[ 'PHP_SELF' ]) && strpos($_SERVER[ 'PHP_SELF' ], $scriptUrl) === 0) {
  102 + $pathInfo = substr($_SERVER[ 'PHP_SELF' ], strlen($scriptUrl));
  103 + } else {
  104 + throw new InvalidConfigException('Unable to determine the path info of the current request.');
  105 + }
  106 +
  107 + if ($pathInfo === '/') {
  108 + $pathInfo = substr($pathInfo, 1);
  109 + }
  110 +
  111 + return (string) $pathInfo;
  112 + }
  113 + }
0 114 \ No newline at end of file
... ...
artweb/artbox-core/components/SeoComponent.php 0 → 100644
  1 +<?php
  2 +
  3 + namespace artbox\core\components;
  4 +
  5 + use artbox\core\exceptions\AliasOverwriteException;
  6 + use artbox\core\models\interfaces\AliasInterface;
  7 + use yii\base\Object;
  8 + use yii\db\ActiveRecord;
  9 + use yii\helpers\Json;
  10 +
  11 + /**
  12 + * Class SeoComponent
  13 + *
  14 +*@package artbox\core\components
  15 + * @property AliasInterface $alias
  16 + * @property string $title
  17 + * @property string $desc
  18 + * @property string $h1
  19 + * @property string $text
  20 + * @property string $robots
  21 + * @property integer $aliasId
  22 + * @property boolean $loaded
  23 + */
  24 + class SeoComponent extends Object
  25 + {
  26 + /**
  27 + * Read only roperty to show wether Alias was loaded or not
  28 + *
  29 + * @var bool
  30 + */
  31 + protected $loaded = false;
  32 +
  33 + /**
  34 + * Data that will be replaced in seo fields
  35 + *
  36 + * @var array
  37 + */
  38 + protected $fields = [];
  39 +
  40 + /**
  41 + * Seo title
  42 + *
  43 + * @var string
  44 + */
  45 + protected $title;
  46 +
  47 + /**
  48 + * meta description
  49 + *
  50 + * @var string
  51 + */
  52 + protected $desc;
  53 +
  54 + /**
  55 + * h1 tag on pages
  56 + *
  57 + * @var string
  58 + */
  59 + protected $h1;
  60 +
  61 + /**
  62 + * Seo text
  63 + *
  64 + * @var string
  65 + */
  66 + protected $text;
  67 +
  68 + /**
  69 + * The alias model that contains seo data
  70 + * sets in Seo url manager
  71 + *
  72 + * @var AliasInterface
  73 + */
  74 + protected $alias;
  75 +
  76 + /**
  77 + * ActiveRecord instance that contains actual data for replacing
  78 + *
  79 + * @var ActiveRecord
  80 + */
  81 + protected $model;
  82 +
  83 + /**
  84 + * Getter for read only property
  85 + *
  86 + * @return bool
  87 + */
  88 + public function getLoaded(): bool
  89 + {
  90 + return $this->loaded;
  91 + }
  92 +
  93 + /**
  94 + * Setting alias model
  95 + *
  96 + * @param \artbox\core\models\interfaces\AliasInterface $alias
  97 + *
  98 + * @throws \artbox\core\exceptions\AliasOverwriteException
  99 + */
  100 + public function setAlias(AliasInterface $alias)
  101 + {
  102 + if ($this->loaded) {
  103 + throw new AliasOverwriteException();
  104 + }
  105 +
  106 + $this->alias = $alias;
  107 +
  108 + $this->title = $alias->getTitle();
  109 + $this->desc = $alias->getDesc();
  110 + $this->h1 = $alias->getH1();
  111 + $this->text = $alias->getText();
  112 +
  113 + $this->loaded = true;
  114 + }
  115 +
  116 + /**
  117 + * @return int
  118 + */
  119 + public function getAliasId()
  120 + {
  121 + return $this->alias->getId();
  122 + }
  123 +
  124 + /**
  125 + * @return string
  126 + */
  127 + public function getTitle()
  128 + {
  129 + return $this->title;
  130 + }
  131 +
  132 + /**
  133 + * @return string
  134 + */
  135 + public function getDesc()
  136 + {
  137 + return $this->desc;
  138 + }
  139 +
  140 + /**
  141 + * @return string
  142 + */
  143 + public function getH1()
  144 + {
  145 + return $this->h1;
  146 + }
  147 +
  148 + /**
  149 + * @return string
  150 + */
  151 + public function getText()
  152 + {
  153 + return $this->text;
  154 + }
  155 +
  156 + /**
  157 + * @return string
  158 + */
  159 + public function getRobots()
  160 + {
  161 + if (!empty($this->alias) && !empty($this->alias->getRobots())) {
  162 + return $this->alias->getRobots();
  163 + }
  164 +
  165 + return 'all';
  166 + }
  167 +
  168 + /**
  169 + * Setting up ActiveRecord model and starting to generate data
  170 + *
  171 + * @param \yii\db\ActiveRecord $model
  172 + */
  173 + public function setModel(ActiveRecord $model)
  174 + {
  175 + $this->model = $model;
  176 +
  177 + $this->generateData();
  178 + }
  179 +
  180 + /**
  181 + * Trying to get field values with all dependecies
  182 + * if it fails fill it with empty string
  183 + *
  184 + * @return void
  185 + */
  186 + protected function populateFields()
  187 + {
  188 + $fields = array_keys(Json::decode($this->alias->getFields()) ? : []);
  189 + foreach ($fields as $field) {
  190 + $params = explode('.', $field);
  191 +
  192 + $chain = $this->model;
  193 +
  194 + foreach ($params as $param) {
  195 + if (!empty($chain->$param)) {
  196 + $chain = $chain->$param;
  197 + } else {
  198 + $chain = '';
  199 + break;
  200 + }
  201 + }
  202 + $this->fields[ '[[' . $field . ']]' ] = $chain;
  203 + }
  204 + }
  205 +
  206 + /**
  207 + * Populating self data with modified information from Alias model
  208 + *
  209 + * @return void
  210 + */
  211 + protected function generateData()
  212 + {
  213 + $this->populateFields();
  214 +
  215 + $title = $this->alias->getTitle();
  216 + $desc = $this->alias->getDesc();
  217 + $h1 = $this->alias->getH1();
  218 + $text = $this->alias->getSeoText();
  219 +
  220 + foreach ($this->fields as $search => $replace) {
  221 + $title = str_replace($search, $replace, $title);
  222 + $desc = str_replace($search, $replace, $desc);
  223 + $h1 = str_replace($search, $replace, $h1);
  224 + $text = str_replace($search, $replace, $text);
  225 + }
  226 +
  227 + $this->title = $title;
  228 + $this->desc = $desc;
  229 + $this->h1 = $h1;
  230 + $this->text = $text;
  231 + }
  232 + }
  233 +
0 234 \ No newline at end of file
... ...
artweb/artbox-core/components/SeoUrlManager.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components;
  4 +
  5 + use artbox\catalog\helpers\FilterHelper;
  6 + use artbox\core\models\Alias;
  7 + use artbox\core\models\Language;
  8 + use yii\helpers\Json;
  9 + use yii\web\UrlManager;
  10 + use Yii;
  11 +
  12 + /**
  13 + * Class SeoUrlManager
  14 + *
  15 + * @package artbox\core\components
  16 + */
  17 + class SeoUrlManager extends UrlManager
  18 + {
  19 + /**
  20 + * Whether to try to redirect from non-seo to seo
  21 + *
  22 + * @var bool
  23 + */
  24 + public $forceRedirect = false;
  25 +
  26 + /**
  27 + * Routes which will be used in alias db query
  28 + *
  29 + * @var array $skipRoute
  30 + */
  31 + public $skipRoute = [];
  32 +
  33 + /**
  34 + * @inheritdoc
  35 + */
  36 + public function parseRequest($request)
  37 + {
  38 + /**
  39 + * @var \artbox\core\components\LanguageRequest $request
  40 + * @var SeoComponent $seo
  41 + */
  42 +
  43 + $seo = Yii::$app->get('seo');
  44 +
  45 + // This function called before url parsed by LanguageRequest, so $language is null
  46 + $request->getLanguageUrl();
  47 + $language = Language::getCurrent();
  48 + if ($request->pathInfo === '') {
  49 + // Do redirect if no active alias for homepage
  50 + $alias = Alias::findRoute([ 'site/index' ], $language);
  51 + if ($alias) {
  52 + $seo->setAlias($alias);
  53 +
  54 + $route = Json::decode($alias->route);
  55 +
  56 + $result[] = array_shift($route);
  57 + $result[] = $route;
  58 +
  59 +
  60 + return $result;
  61 + }
  62 + } else {
  63 + $alias = Alias::findUrl($request->pathInfo, $language);
  64 + }
  65 + if ($this->forceRedirect && empty($alias)) {
  66 + $get = $request->get();
  67 + foreach ($get as $index => $item) {
  68 + if ($value = intval($item)) {
  69 + $get[ $index ] = $value;
  70 + }
  71 + }
  72 + $alias = Alias::findRoute(array_merge([ $request->pathInfo ], $get), $language);
  73 + if ($alias) {
  74 + \Yii::$app->response->redirect(Json::decode($alias->route));
  75 + }
  76 + }
  77 +
  78 + if (!empty($alias)) {
  79 + /**
  80 + */
  81 + $seo->setAlias($alias);
  82 +
  83 + $route = Json::decode($alias->route);
  84 +
  85 + $result[] = array_shift($route);
  86 + $result[] = $route;
  87 +
  88 + return $result;
  89 + }
  90 +
  91 + return parent::parseRequest($request);
  92 + }
  93 +
  94 + /**
  95 + * #1 Decide set or not language in the beginning of url (is there one active or more)
  96 + * #2 Add hash or not (is there $params['#'] or not)
  97 + * #3 Create url by ready alias or not
  98 + * #4 Does language setted from param ( $language_id )
  99 + *
  100 +*@inheritdoc
  101 + */
  102 + public function createUrl($params)
  103 + {
  104 + /**
  105 + * Decide how much active languages (1)
  106 + */
  107 + $count = count(Language::getActive());
  108 +
  109 + if ($params[ 0 ] === 'site/index') {
  110 + if ($count > 1) {
  111 + return '/';
  112 + } else {
  113 + return '/' . Language::getCurrent()->url;
  114 + }
  115 + }
  116 +
  117 + /**
  118 + * (1,2,3)
  119 + */
  120 + if (!empty($params[ 'alias' ]) && $params[ 'alias' ] instanceof Alias) {
  121 + /**
  122 + * @var Alias $alias
  123 + */
  124 + $alias = $params[ 'alias' ];
  125 + $language = Language::getCurrent();
  126 + $hash = isset($params[ '#' ]) ? '#' . $params[ '#' ] : '';
  127 + return ( $count > 1 ) ? ( '/' . $language->url . '/' . $alias->value ) : ( '/' . $alias->value ) . $hash;
  128 + }
  129 +
  130 + /**
  131 + * (4)
  132 + */
  133 + if (!empty($params[ 'language_id' ])) {
  134 + $language = Language::findOne($params[ 'language_id' ]);
  135 + unset($params[ 'language_id' ]);
  136 + }
  137 + if (empty($language)) {
  138 + $language = Language::getCurrent();
  139 + }
  140 + /**
  141 + * @var \artbox\core\components\AliasCache $cacheModel
  142 + */
  143 + $cacheModel = \Yii::$app->get('aliasCache', false);
  144 + $rules = [];
  145 + foreach ($this->rules as $rule) {
  146 + if (!in_array($rule->route, $this->skipRoute)) {
  147 + $rules[] = $rule->route;
  148 + }
  149 + }
  150 + $diff = null;
  151 + if (!in_array($params[ 0 ], $rules)) {
  152 + if (count($params) > 2 && !empty($params[ 'id' ])) {
  153 + $aliasParams = [
  154 + $params[ 0 ],
  155 + 'id' => $params[ 'id' ],
  156 + ];
  157 + } else {
  158 + $aliasParams = $params;
  159 + }
  160 + if ($cacheModel) {
  161 + $alias = $cacheModel->getOrSet(
  162 + $aliasParams,
  163 + $language,
  164 + function () use ($aliasParams, $language) {
  165 + return Alias::findRoute($aliasParams, $language);
  166 + }
  167 + );
  168 + } else {
  169 + $alias = Alias::findRoute($aliasParams, $language);
  170 + }
  171 + if (!empty($alias)) {
  172 + $diff = array_diff($params, $aliasParams);
  173 + }
  174 + } else {
  175 + $alias = null;
  176 + }
  177 + if (!empty($alias)) {
  178 + $value = $alias->value;
  179 + return ( $count > 1 ) ? ( '/' . $language->url . '/' . $value ) : ( '/' . $value ) . ( $diff ? ( '?' . http_build_query(
  180 + $diff
  181 + ) ) : '' );
  182 + } else {
  183 + $url = parent::createUrl($params);
  184 + /**
  185 + * @var FilterHelper $filter
  186 + */
  187 + if (class_exists('artbox\catalog\helpers\FilterHelper')) {
  188 + $filter = \Yii::$app->get('filter');
  189 + $result = ( $count > 1 ) ? ( '/' . $language->url . $filter->filterObj->replaceFilterUrl(
  190 + $url
  191 + ) ) : $filter->filterObj->replaceFilterUrl($url);
  192 + } else {
  193 + $result = ( $count > 1 ) ? ( '/' . $language->url . $url ) : $url;
  194 + }
  195 + return $result;
  196 + }
  197 + }
  198 + }
0 199 \ No newline at end of file
... ...
artweb/artbox-core/components/Sitemap.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components;
  4 +
  5 + use artbox\core\models\SitemapDynamic;
  6 + use artbox\core\models\SitemapStatic;
  7 + use yii\base\Object;
  8 + use yii\db\ActiveRecord;
  9 + use yii\helpers\Html;
  10 + use yii\web\UrlManager;
  11 +
  12 + class Sitemap extends Object
  13 + {
  14 + public $entities = [];
  15 + public $path = '@frontend/web/sitemap.xml';
  16 + public $url = 'sitemap.xml';
  17 +
  18 + /**
  19 + * Get absolute url to sitemap.xml
  20 + *
  21 + * @return string
  22 + */
  23 + public function getUrl(): string
  24 + {
  25 + /**
  26 + * @var UrlManager $urlManager
  27 + */
  28 + $urlManager = \Yii::$app->get('urlManagerFrontend');
  29 + return $urlManager->createAbsoluteUrl('/' . $this->url);
  30 + }
  31 +
  32 + /**
  33 + * Check whether sitemap.xml exist
  34 + *
  35 + * @return bool
  36 + */
  37 + public function checkFileExist(): bool
  38 + {
  39 + return file_exists(\Yii::getAlias($this->path));
  40 + }
  41 + /**
  42 + * Generate sitemap XML in $path
  43 + *
  44 + * @return bool
  45 + */
  46 + public function generateXML(): bool
  47 + {
  48 + return $this->saveXML($this->generateOneShot());
  49 + }
  50 +
  51 + /**
  52 + * Save generated xml to $path file
  53 + *
  54 + * @param string $xml
  55 + *
  56 + * @return bool
  57 + */
  58 + protected function saveXML(string $xml): bool
  59 + {
  60 + $realpath = \Yii::getAlias($this->path);
  61 + if (file_put_contents($realpath, $xml)) {
  62 + return true;
  63 + } else {
  64 + return false;
  65 + }
  66 + }
  67 +
  68 + /**
  69 + * Generate xml from configs
  70 + *
  71 + * @return string
  72 + */
  73 + public function generateOneShot(): string
  74 + {
  75 + /**
  76 + * @var UrlManager $urlManager
  77 + */
  78 + $urlManager = \Yii::$app->get('urlManagerFrontend');
  79 + $content = '<?xml version="1.0" encoding="UTF-8"?>';
  80 + $content .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
  81 + /**
  82 + * @var SitemapStatic[] $static
  83 + */
  84 + // ***** Begin generating static pages
  85 + $static = SitemapStatic::find()
  86 + ->all();
  87 + foreach ($static as $item) {
  88 + $content .= Html::tag(
  89 + 'url',
  90 + Html::tag('loc', $item->url) . Html::tag('lastmod', date('Y-m-d')) . Html::tag(
  91 + 'changefreq',
  92 + $item->frequency
  93 + ) . Html::tag('priority', $item->priority)
  94 + );
  95 + }
  96 + // ***** <<< End
  97 + /**
  98 + * @var SitemapDynamic $dynamic
  99 + */
  100 + $dynamic = SitemapDynamic::find()
  101 + ->indexBy('entity')
  102 + ->where([ 'status' => 1 ])
  103 + ->all();
  104 + $entities = $this->entities;
  105 + foreach ($entities as $entity) {
  106 + /**
  107 + * @var string $class
  108 + */
  109 + $class = $entity[ 'class' ];
  110 + /**
  111 + * @var ActiveRecord $classInstance
  112 + */
  113 + $classInstance = new $class();
  114 + if (is_subclass_of($classInstance, ActiveRecord::className())) {
  115 + if (!empty($dynamic[ $class ])) {
  116 + /**
  117 + * @var SitemapDynamic $model
  118 + */
  119 + $model = $dynamic[ $class ];
  120 + $query = $classInstance::find();
  121 + if (isset($entity[ 'conditions' ])) {
  122 + foreach ($entity[ 'conditions' ] as $condition) {
  123 + $query->where($condition);
  124 + }
  125 + }
  126 + $result = $query->all();
  127 + foreach ($result as $record) {
  128 + $content .= Html::tag(
  129 + 'url',
  130 + Html::tag(
  131 + 'loc',
  132 + $urlManager->createAbsoluteUrl(
  133 + [
  134 + $entity[ 'url' ],
  135 + 'id' => $record->getAttribute('id'),
  136 + ]
  137 + )
  138 + ) . Html::tag('lastmod', date('Y-m-d')) . Html::tag(
  139 + 'changefreq',
  140 + $model->frequency
  141 + ) . Html::tag('priority', $model->priority)
  142 + );
  143 + }
  144 + }
  145 + }
  146 + }
  147 + $content .= '</urlset>';
  148 + return $content;
  149 + }
  150 + }
0 151 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/.gitignore 0 → 100755
  1 +/nbproject
0 2 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/Module.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components\imagemanager;
  4 +
  5 + use Yii;
  6 + use yii\base\UnknownClassException;
  7 + use yii\base\InvalidConfigException;
  8 + use yii\web\AssetManager;
  9 + use artbox\core\components\imagemanager\assets\ImageManagerModuleAsset;
  10 +
  11 + /**
  12 + * imagemanager module definition class
  13 + */
  14 + class Module extends \yii\base\Module
  15 + {
  16 +
  17 + public $defaultRoute = 'manager';
  18 + //stylesheet for modal iframe
  19 + public $cssFiles = [];
  20 + //allowed Extensions for upload
  21 + public $allowedFileExtensions = [
  22 + 'jpg',
  23 + 'jpeg',
  24 + 'gif',
  25 + 'png',
  26 + ];
  27 + //set assetPublishedUrl
  28 + public $assetPublishedUrl;
  29 +
  30 + /**
  31 + * @var bool|callable Variable that defines if the upload action will be available
  32 + * This variable defaults to true, to enable uploading by default
  33 + * It is also possible to give a callable function, in which case the function will be executed
  34 + */
  35 + public $canUploadImage = true;
  36 +
  37 + /**
  38 + * @var bool|callable Variable that defines if the delete action will be available
  39 + * This variable default to true, to enable removal if image
  40 + * It is also possible to give a callable function, in which case the function will be executed
  41 + */
  42 + public $canRemoveImage = true;
  43 +
  44 + /**
  45 + * @var bool|callable Variable that defines if blameable behavior is used.
  46 + * This can be a boolean, or a callable function that returns a boolean
  47 + */
  48 + public $setBlameableBehavior = false;
  49 +
  50 + /**
  51 + * @inheritdoc
  52 + */
  53 + public function init()
  54 + {
  55 + parent::init();
  56 + //set language
  57 + if (!isset(Yii::$app->i18n->translations[ 'imagemanager' ])) {
  58 + Yii::$app->i18n->translations[ 'imagemanager' ] = [
  59 + 'class' => 'yii\i18n\PhpMessageSource',
  60 + 'sourceLanguage' => 'en',
  61 + 'basePath' => '@artbox/core/components/imagemanager/messages',
  62 + ];
  63 + }
  64 + //check extensions
  65 + $this->_checkExtensionsExists();
  66 + //check mediaPath isset
  67 + if (Yii::$app->imagemanager->mediaPath === null) {
  68 + throw new InvalidConfigException("Component param 'mediaPath' need to be set to a location");
  69 + }
  70 + //set asset path
  71 + $this->assetPublishedUrl = ( new AssetManager )->getPublishedUrl(
  72 + "@artbox/core/components/imagemanager/assets/source"
  73 + );
  74 +
  75 + // Check if the canRemoveImage variable is callable
  76 + if (is_callable($this->canRemoveImage)) {
  77 + $this->canRemoveImage = call_user_func($this->canRemoveImage);
  78 + }
  79 +
  80 + // Check if the canUploadImage variable is callable
  81 + if (is_callable($this->canUploadImage)) {
  82 + $this->canUploadImage = call_user_func($this->canUploadImage);
  83 + }
  84 +
  85 + // Check if blameable behavior is callable
  86 + if (is_callable($this->setBlameableBehavior)) {
  87 + $this->setBlameableBehavior = call_user_func($this->setBlameableBehavior);
  88 + }
  89 +
  90 + // Check if the variable configuration is correct in order for the module to function
  91 + $this->_checkVariableConfiguration();
  92 + }
  93 +
  94 + /**
  95 + * @inheritdoc
  96 + */
  97 + public function beforeAction($action)
  98 + {
  99 + if (parent::beforeAction($action)) {
  100 + //set view
  101 + $view = $action->controller->getView();
  102 +
  103 + //set asset
  104 + ImageManagerModuleAsset::register($view);
  105 +
  106 + //get parameters
  107 + $viewMode = Yii::$app->request->get("view-mode", "page");
  108 +
  109 + /* @var $action \yii\base\Action */
  110 + if ($viewMode == "iframe") {
  111 + //set stylesheet for modal
  112 + if (is_array($this->cssFiles) && count($this->cssFiles) > 0) {
  113 + //if exists loop through files and add them to iframe mode
  114 + foreach ($this->cssFiles AS $cssFile) {
  115 + //registrate file
  116 + $view->registerCssFile($cssFile, [ 'depends' => 'yii\bootstrap\BootstrapAsset' ]);
  117 + }
  118 + }
  119 + }
  120 + return true;
  121 + }
  122 + return false;
  123 + }
  124 +
  125 + /**
  126 + * Check if extensions exists
  127 + *
  128 + * @throws UnknownClassException Throw error if extension is not found
  129 + */
  130 + private function _checkExtensionsExists()
  131 + {
  132 + //kartik file uploaded is installed
  133 + if (!class_exists('kartik\file\FileInput')) {
  134 + throw new UnknownClassException(
  135 + "Can't find: kartik\\file\FileInput. Install \"kartik-v/yii2-widget-fileinput\": \"@dev\""
  136 + );
  137 + }
  138 + //check Yii imagine is installed
  139 + if (!class_exists('yii\imagine\Image')) {
  140 + throw new UnknownClassException(
  141 + "Can't find: yii\imagine\Image. Install \"yiisoft/yii2-imagine\": \"~2.0.0\""
  142 + );
  143 + }
  144 + }
  145 +
  146 + /**
  147 + * Check if the module variables have the content that is expected
  148 + *
  149 + * @throws InvalidConfigException
  150 + */
  151 + private function _checkVariableConfiguration()
  152 + {
  153 + // Check if the canUploadImage is boolean
  154 + if (!is_bool($this->canUploadImage)) {
  155 + throw new InvalidConfigException(
  156 + '$canUploadImage variable only supports a boolean value, if you have a custom function you must return a boolean'
  157 + );
  158 + }
  159 + // Check if the canRemoveImage is boolean
  160 + if (!is_bool($this->canRemoveImage)) {
  161 + throw new InvalidConfigException(
  162 + '$removeImageAllowed variable only supports a boolean value, if you have a custom function you must return a boolean'
  163 + );
  164 + }
  165 + // Check if the setBlamableBehavior is boolean
  166 + if (!is_bool($this->setBlameableBehavior)) {
  167 + throw new InvalidConfigException(
  168 + '$setBlameableBehavior only supports a boolean value, if you have a customer function make sure that you return a boolean'
  169 + );
  170 + }
  171 +
  172 + // Check if the blameable behavior is set to true
  173 + if ($this->setBlameableBehavior) {
  174 + // Get the migration record
  175 + $mRecordMigrationRun = Yii::$app->db->createCommand(
  176 + 'SELECT * FROM `migration` WHERE `version` = \'m170223_113221_addBlameableBehavior\''
  177 + )
  178 + ->queryOne();
  179 + if ($mRecordMigrationRun === false) {
  180 + throw new InvalidConfigException(
  181 + 'Image Manager: You have not run the latest migration, see the documentation how to do this.'
  182 + );
  183 + }
  184 + }
  185 + }
  186 +
  187 + }
... ...
artweb/artbox-core/components/imagemanager/assets/ImageManagerInputAsset.php 0 → 100755
  1 +<?php
  2 + namespace artbox\core\components\imagemanager\assets;
  3 +
  4 + use yii\web\AssetBundle;
  5 +
  6 + /**
  7 + * ImageManagerInputAsset.
  8 + */
  9 + class ImageManagerInputAsset extends AssetBundle
  10 + {
  11 + public $sourcePath = '@artbox/core/components/imagemanager/assets/source';
  12 + public $css = [
  13 + 'css/imagemanager.input.css',
  14 + ];
  15 + public $js = [
  16 + 'js/script.imagemanager.input.js',
  17 + ];
  18 + public $depends = [
  19 + 'yii\web\JqueryAsset',
  20 + 'yii\bootstrap\BootstrapPluginAsset',
  21 + ];
  22 + }
0 23 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/assets/ImageManagerModuleAsset.php 0 → 100755
  1 +<?php
  2 + namespace artbox\core\components\imagemanager\assets;
  3 +
  4 + use yii\web\AssetBundle;
  5 +
  6 + /**
  7 + * ImageManagerModuleAsset.
  8 + */
  9 + class ImageManagerModuleAsset extends AssetBundle
  10 + {
  11 + public $sourcePath = '@artbox/core/components/imagemanager/assets/source';
  12 + public $css = [
  13 + 'css/cropper.min.css',
  14 + 'css/imagemanager.module.css',
  15 + ];
  16 + public $js = [
  17 + 'js/cropper.min.js',
  18 + 'js/script.imagemanager.module.js',
  19 + ];
  20 + public $depends = [
  21 + 'yii\web\JqueryAsset',
  22 + 'yii\bootstrap\BootstrapPluginAsset',
  23 + ];
  24 + }
0 25 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/assets/source/css/cropper.min.css 0 → 100755
  1 +/*!
  2 + * Cropper v2.3.2
  3 + * https://github.com/fengyuanchen/cropper
  4 + *
  5 + * Copyright (c) 2014-2016 Fengyuan Chen and contributors
  6 + * Released under the MIT license
  7 + *
  8 + * Date: 2016-06-08T12:14:46.286Z
  9 + */.cropper-container{font-size:0;line-height:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;direction:ltr!important;-ms-touch-action:none;touch-action:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.cropper-container img{display:block;width:100%;min-width:0!important;max-width:none!important;height:100%;min-height:0!important;max-height:none!important;image-orientation:0deg!important}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{position:absolute;top:0;right:0;bottom:0;left:0}.cropper-wrap-box{overflow:hidden}.cropper-drag-box{opacity:0;background-color:#fff;filter:alpha(opacity=0)}.cropper-dashed,.cropper-modal{opacity:.5;filter:alpha(opacity=50)}.cropper-modal{background-color:#000}.cropper-view-box{display:block;overflow:hidden;width:100%;height:100%;outline:#39f solid 1px;outline-color:rgba(51,153,255,.75)}.cropper-dashed{position:absolute;display:block;border:0 dashed #eee}.cropper-dashed.dashed-h{top:33.33333%;left:0;width:100%;height:33.33333%;border-top-width:1px;border-bottom-width:1px}.cropper-dashed.dashed-v{top:0;left:33.33333%;width:33.33333%;height:100%;border-right-width:1px;border-left-width:1px}.cropper-center{position:absolute;top:50%;left:50%;display:block;width:0;height:0;opacity:.75;filter:alpha(opacity=75)}.cropper-center:after,.cropper-center:before{position:absolute;display:block;content:' ';background-color:#eee}.cropper-center:before{top:0;left:-3px;width:7px;height:1px}.cropper-center:after{top:-3px;left:0;width:1px;height:7px}.cropper-face,.cropper-line,.cropper-point{position:absolute;display:block;width:100%;height:100%;opacity:.1;filter:alpha(opacity=10)}.cropper-face{top:0;left:0;background-color:#fff}.cropper-line,.cropper-point{background-color:#39f}.cropper-line.line-e{top:0;right:-3px;width:5px;cursor:e-resize}.cropper-line.line-n{top:-3px;left:0;height:5px;cursor:n-resize}.cropper-line.line-w{top:0;left:-3px;width:5px;cursor:w-resize}.cropper-line.line-s{bottom:-3px;left:0;height:5px;cursor:s-resize}.cropper-point{width:5px;height:5px;opacity:.75;filter:alpha(opacity=75)}.cropper-point.point-e{top:50%;right:-3px;margin-top:-3px;cursor:e-resize}.cropper-point.point-n{top:-3px;left:50%;margin-left:-3px;cursor:n-resize}.cropper-point.point-w{top:50%;left:-3px;margin-top:-3px;cursor:w-resize}.cropper-point.point-s{bottom:-3px;left:50%;margin-left:-3px;cursor:s-resize}.cropper-point.point-ne{top:-3px;right:-3px;cursor:ne-resize}.cropper-point.point-nw{top:-3px;left:-3px;cursor:nw-resize}.cropper-point.point-sw{bottom:-3px;left:-3px;cursor:sw-resize}.cropper-point.point-se{right:-3px;bottom:-3px;width:20px;height:20px;cursor:se-resize;opacity:1;filter:alpha(opacity=100)}.cropper-point.point-se:before{position:absolute;right:-50%;bottom:-50%;display:block;width:200%;height:200%;content:' ';opacity:0;background-color:#39f;filter:alpha(opacity=0)}@media (min-width:768px){.cropper-point.point-se{width:15px;height:15px}}@media (min-width:992px){.cropper-point.point-se{width:10px;height:10px}}@media (min-width:1200px){.cropper-point.point-se{width:5px;height:5px;opacity:.75;filter:alpha(opacity=75)}}.cropper-invisible{opacity:0;filter:alpha(opacity=0)}.cropper-bg{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC)}.cropper-hide{position:absolute;display:block;width:0;height:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed}
0 10 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/assets/source/css/imagemanager.input.css 0 → 100755
  1 +#modal-imagemanager {
  2 + z-index: 999999;
  3 +}
  4 +
  5 +#modal-imagemanager .modal-header h4 {
  6 + margin: 0;
  7 +}
  8 +
  9 +#modal-imagemanager iframe {
  10 + border: none;
  11 + width: 100%;
  12 + min-height: 500px;
  13 +}
  14 +
  15 +.image-manager-input {
  16 +}
  17 +
  18 +.image-manager-input .image-wrapper {
  19 + margin-top: 10px;
  20 + border: 1px solid #ddd;
  21 + border-radius: 4px;
  22 + display: inline-block;
  23 + padding: 4px;
  24 + background: #fff;
  25 +}
  26 +
  27 +.image-manager-input .image-wrapper .img-preview {
  28 + background: #dadada;
  29 + max-width: 200px;
  30 + max-height: 200px;
  31 + height: auto;
  32 + line-height: 1.42857;
  33 +}
0 34 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/assets/source/css/imagemanager.module.css 0 → 100755
  1 +/*CSS for module*/
  2 +#module-imagemanager {
  3 + padding-left: 0;
  4 + padding-right: 0;
  5 +}
  6 +
  7 +#module-imagemanager > .row {
  8 + margin: 0;
  9 +}
  10 +
  11 +#module-imagemanager.tinymce,
  12 +#module-imagemanager.ckeditor {
  13 + padding: 15px;
  14 +}
  15 +
  16 +/*overview*/
  17 +#module-imagemanager > .row .col-overview {
  18 + padding-left: 0;
  19 + padding-right: 0;
  20 + border-right: 1px solid #ddd;
  21 + height: 100%;
  22 + overflow: auto;
  23 +}
  24 +
  25 +#module-imagemanager > .row .col-overview .item-overview {
  26 + max-height: 500px;
  27 + overflow: auto;
  28 +}
  29 +
  30 +#module-imagemanager > .row .col-overview .item-overview .item {
  31 + position: relative;
  32 + overflow: hidden;
  33 + width: 128px;
  34 + height: 128px;
  35 + cursor: pointer;
  36 +}
  37 +
  38 +#module-imagemanager > .row .col-overview .item-overview .item.selected {
  39 + background: #00ac24;
  40 +}
  41 +
  42 +#module-imagemanager > .row .col-overview .item-overview .item .thumbnail {
  43 + margin-bottom: 0;
  44 +}
  45 +
  46 +#module-imagemanager > .row .col-overview .item-overview .item .thumbnail img {
  47 + max-height: 118px;
  48 + background: #dadada;
  49 +}
  50 +
  51 +#module-imagemanager > .row .col-overview .item-overview .item .thumbnail .filename {
  52 + background-color: rgba(255, 255, 255, 0.9);
  53 + position: absolute;
  54 + bottom: 4px;
  55 + left: 4px;
  56 + right: 4px;
  57 + max-height: 100%;
  58 + overflow: hidden;
  59 + white-space: nowrap;
  60 + text-overflow: ellipsis;
  61 + padding: 0 10px;
  62 +}
  63 +
  64 +/*edit column*/
  65 +#module-imagemanager > .row .col-image-editor {
  66 + padding-left: 0;
  67 + display: none;
  68 +}
  69 +
  70 +/*cropper*/
  71 +#module-imagemanager > .row .col-image-editor .image-cropper .image-wrapper {
  72 + max-height: 460px;
  73 +}
  74 +
  75 +#module-imagemanager > .row .col-image-editor .image-cropper .image-wrapper img#image-cropper {
  76 + max-width: 100%;
  77 +}
  78 +
  79 +/*options*/
  80 +#module-imagemanager > .row .col-options {
  81 + padding-right: 0;
  82 +}
  83 +
  84 +/*File upload*/
  85 +#module-imagemanager > .row .col-options .file-input .form-control {
  86 + display: none;
  87 +}
  88 +
  89 +#module-imagemanager > .row .col-options .form-group .file-input .input-group,
  90 +#module-imagemanager > .row .col-options .form-group .file-input .input-group .input-group-btn {
  91 + float: left;
  92 +}
  93 +
  94 +#module-imagemanager > .row .col-options .form-group .btn-add-flyleaf {
  95 + float: left;
  96 +}
  97 +
  98 +/*details*/
  99 +#module-imagemanager > .row .col-options .image-info {
  100 + margin-top: 10px;
  101 +}
  102 +
  103 +#module-imagemanager > .row .col-options .image-info .thumbnail {
  104 + margin-bottom: 10px;
  105 +}
  106 +
  107 +#module-imagemanager > .row .col-options .image-info .thumbnail img {
  108 + max-width: 100%;
  109 + background: #dadada;
  110 +}
  111 +
  112 +#module-imagemanager > .row .col-options .image-info .edit-buttons {
  113 + margin-bottom: 10px;
  114 +}
  115 +
  116 +#module-imagemanager > .row .col-options .image-info .details {
  117 +}
  118 +
  119 +#module-imagemanager > .row .col-options .image-info .details .fileName {
  120 + font-weight: bold;
  121 + overflow: hidden;
  122 + white-space: nowrap;
  123 + text-overflow: ellipsis;
  124 +}
  125 +
  126 +#module-imagemanager > .row .col-options .image-info .pick-image-item {
  127 + margin-top: 10px;
  128 +}
  129 +
  130 +#module-imagemanager a.delete-image-item {
  131 + margin-top: 5px;
  132 +}
0 133 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/assets/source/img/img_no-image.png 0 → 100755

8.26 KB

artweb/artbox-core/components/imagemanager/assets/source/js/cropper.min.js 0 → 100755
  1 +/*!
  2 + * Cropper v2.3.2
  3 + * https://github.com/fengyuanchen/cropper
  4 + *
  5 + * Copyright (c) 2014-2016 Fengyuan Chen and contributors
  6 + * Released under the MIT license
  7 + *
  8 + * Date: 2016-06-08T12:14:46.286Z
  9 + */
  10 +!function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t("object"==typeof exports?require("jquery"):jQuery)}(function(t){"use strict";function i(t){return"number"==typeof t&&!isNaN(t)}function e(t){return"undefined"==typeof t}function s(t,e){var s=[];return i(e)&&s.push(e),s.slice.apply(t,s)}function a(t,i){var e=s(arguments,2);return function(){return t.apply(i,e.concat(s(arguments)))}}function o(t){var i=t.match(/^(https?:)\/\/([^\:\/\?#]+):?(\d*)/i);return i&&(i[1]!==C.protocol||i[2]!==C.hostname||i[3]!==C.port)}function h(t){var i="timestamp="+(new Date).getTime();return t+(-1===t.indexOf("?")?"?":"&")+i}function n(t){return t?' crossOrigin="'+t+'"':""}function r(t,i){var e;return t.naturalWidth&&!mt?i(t.naturalWidth,t.naturalHeight):(e=document.createElement("img"),e.onload=function(){i(this.width,this.height)},void(e.src=t.src))}function p(t){var e=[],s=t.rotate,a=t.scaleX,o=t.scaleY;return i(a)&&i(o)&&e.push("scale("+a+","+o+")"),i(s)&&e.push("rotate("+s+"deg)"),e.length?e.join(" "):"none"}function c(t,i){var e,s,a=Ct(t.degree)%180,o=(a>90?180-a:a)*Math.PI/180,h=bt(o),n=Bt(o),r=t.width,p=t.height,c=t.aspectRatio;return i?(e=r/(n+h/c),s=e/c):(e=r*n+p*h,s=r*h+p*n),{width:e,height:s}}function l(e,s){var a,o,h,n=t("<canvas>")[0],r=n.getContext("2d"),p=0,l=0,d=s.naturalWidth,g=s.naturalHeight,u=s.rotate,f=s.scaleX,m=s.scaleY,v=i(f)&&i(m)&&(1!==f||1!==m),w=i(u)&&0!==u,x=w||v,C=d*Ct(f||1),b=g*Ct(m||1);return v&&(a=C/2,o=b/2),w&&(h=c({width:C,height:b,degree:u}),C=h.width,b=h.height,a=C/2,o=b/2),n.width=C,n.height=b,x&&(p=-d/2,l=-g/2,r.save(),r.translate(a,o)),v&&r.scale(f,m),w&&r.rotate(u*Math.PI/180),r.drawImage(e,$t(p),$t(l),$t(d),$t(g)),x&&r.restore(),n}function d(i){var e=i.length,s=0,a=0;return e&&(t.each(i,function(t,i){s+=i.pageX,a+=i.pageY}),s/=e,a/=e),{pageX:s,pageY:a}}function g(t,i,e){var s,a="";for(s=i,e+=i;e>s;s++)a+=Lt(t.getUint8(s));return a}function u(t){var i,e,s,a,o,h,n,r,p,c,l=new D(t),d=l.byteLength;if(255===l.getUint8(0)&&216===l.getUint8(1))for(p=2;d>p;){if(255===l.getUint8(p)&&225===l.getUint8(p+1)){n=p;break}p++}if(n&&(e=n+4,s=n+10,"Exif"===g(l,e,4)&&(h=l.getUint16(s),o=18761===h,(o||19789===h)&&42===l.getUint16(s+2,o)&&(a=l.getUint32(s+4,o),a>=8&&(r=s+a)))),r)for(d=l.getUint16(r,o),c=0;d>c;c++)if(p=r+12*c+2,274===l.getUint16(p,o)){p+=8,i=l.getUint16(p,o),mt&&l.setUint16(p,1,o);break}return i}function f(t){var i,e=t.replace(G,""),s=atob(e),a=s.length,o=new B(a),h=new y(o);for(i=0;a>i;i++)h[i]=s.charCodeAt(i);return o}function m(t){var i,e=new y(t),s=e.length,a="";for(i=0;s>i;i++)a+=Lt(e[i]);return"data:image/jpeg;base64,"+$(a)}function v(i,e){this.$element=t(i),this.options=t.extend({},v.DEFAULTS,t.isPlainObject(e)&&e),this.isLoaded=!1,this.isBuilt=!1,this.isCompleted=!1,this.isRotated=!1,this.isCropped=!1,this.isDisabled=!1,this.isReplaced=!1,this.isLimited=!1,this.wheeling=!1,this.isImg=!1,this.originalUrl="",this.canvas=null,this.cropBox=null,this.init()}var w=t(window),x=t(document),C=window.location,b=window.navigator,B=window.ArrayBuffer,y=window.Uint8Array,D=window.DataView,$=window.btoa,L="cropper",T="cropper-modal",X="cropper-hide",Y="cropper-hidden",k="cropper-invisible",M="cropper-move",W="cropper-crop",H="cropper-disabled",R="cropper-bg",z="mousedown touchstart pointerdown MSPointerDown",O="mousemove touchmove pointermove MSPointerMove",P="mouseup touchend touchcancel pointerup pointercancel MSPointerUp MSPointerCancel",E="wheel mousewheel DOMMouseScroll",U="dblclick",I="load."+L,F="error."+L,j="resize."+L,A="build."+L,S="built."+L,N="cropstart."+L,_="cropmove."+L,q="cropend."+L,K="crop."+L,Z="zoom."+L,Q=/e|w|s|n|se|sw|ne|nw|all|crop|move|zoom/,V=/^data\:/,G=/^data\:([^\;]+)\;base64,/,J=/^data\:image\/jpeg.*;base64,/,tt="preview",it="action",et="e",st="w",at="s",ot="n",ht="se",nt="sw",rt="ne",pt="nw",ct="all",lt="crop",dt="move",gt="zoom",ut="none",ft=t.isFunction(t("<canvas>")[0].getContext),mt=b&&/(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i.test(b.userAgent),vt=Number,wt=Math.min,xt=Math.max,Ct=Math.abs,bt=Math.sin,Bt=Math.cos,yt=Math.sqrt,Dt=Math.round,$t=Math.floor,Lt=String.fromCharCode;v.prototype={constructor:v,init:function(){var t,i=this.$element;if(i.is("img")){if(this.isImg=!0,this.originalUrl=t=i.attr("src"),!t)return;t=i.prop("src")}else i.is("canvas")&&ft&&(t=i[0].toDataURL());this.load(t)},trigger:function(i,e){var s=t.Event(i,e);return this.$element.trigger(s),s},load:function(i){var e,s,a=this.options,n=this.$element;if(i&&(n.one(A,a.build),!this.trigger(A).isDefaultPrevented())){if(this.url=i,this.image={},!a.checkOrientation||!B)return this.clone();if(e=t.proxy(this.read,this),V.test(i))return J.test(i)?e(f(i)):this.clone();s=new XMLHttpRequest,s.onerror=s.onabort=t.proxy(function(){this.clone()},this),s.onload=function(){e(this.response)},a.checkCrossOrigin&&o(i)&&n.prop("crossOrigin")&&(i=h(i)),s.open("get",i),s.responseType="arraybuffer",s.send()}},read:function(t){var i,e,s,a=this.options,o=u(t),h=this.image;if(o>1)switch(this.url=m(t),o){case 2:e=-1;break;case 3:i=-180;break;case 4:s=-1;break;case 5:i=90,s=-1;break;case 6:i=90;break;case 7:i=90,e=-1;break;case 8:i=-90}a.rotatable&&(h.rotate=i),a.scalable&&(h.scaleX=e,h.scaleY=s),this.clone()},clone:function(){var i,e,s=this.options,a=this.$element,r=this.url,p="";s.checkCrossOrigin&&o(r)&&(p=a.prop("crossOrigin"),p?i=r:(p="anonymous",i=h(r))),this.crossOrigin=p,this.crossOriginUrl=i,this.$clone=e=t("<img"+n(p)+' src="'+(i||r)+'">'),this.isImg?a[0].complete?this.start():a.one(I,t.proxy(this.start,this)):e.one(I,t.proxy(this.start,this)).one(F,t.proxy(this.stop,this)).addClass(X).insertAfter(a)},start:function(){var i=this.$element,e=this.$clone;this.isImg||(e.off(F,this.stop),i=e),r(i[0],t.proxy(function(i,e){t.extend(this.image,{naturalWidth:i,naturalHeight:e,aspectRatio:i/e}),this.isLoaded=!0,this.build()},this))},stop:function(){this.$clone.remove(),this.$clone=null},build:function(){var i,e,s,a=this.options,o=this.$element,h=this.$clone;this.isLoaded&&(this.isBuilt&&this.unbuild(),this.$container=o.parent(),this.$cropper=i=t(v.TEMPLATE),this.$canvas=i.find(".cropper-canvas").append(h),this.$dragBox=i.find(".cropper-drag-box"),this.$cropBox=e=i.find(".cropper-crop-box"),this.$viewBox=i.find(".cropper-view-box"),this.$face=s=e.find(".cropper-face"),o.addClass(Y).after(i),this.isImg||h.removeClass(X),this.initPreview(),this.bind(),a.aspectRatio=xt(0,a.aspectRatio)||NaN,a.viewMode=xt(0,wt(3,Dt(a.viewMode)))||0,a.autoCrop?(this.isCropped=!0,a.modal&&this.$dragBox.addClass(T)):e.addClass(Y),a.guides||e.find(".cropper-dashed").addClass(Y),a.center||e.find(".cropper-center").addClass(Y),a.cropBoxMovable&&s.addClass(M).data(it,ct),a.highlight||s.addClass(k),a.background&&i.addClass(R),a.cropBoxResizable||e.find(".cropper-line, .cropper-point").addClass(Y),this.setDragMode(a.dragMode),this.render(),this.isBuilt=!0,this.setData(a.data),o.one(S,a.built),setTimeout(t.proxy(function(){this.trigger(S),this.trigger(K,this.getData()),this.isCompleted=!0},this),0))},unbuild:function(){this.isBuilt&&(this.isBuilt=!1,this.isCompleted=!1,this.initialImage=null,this.initialCanvas=null,this.initialCropBox=null,this.container=null,this.canvas=null,this.cropBox=null,this.unbind(),this.resetPreview(),this.$preview=null,this.$viewBox=null,this.$cropBox=null,this.$dragBox=null,this.$canvas=null,this.$container=null,this.$cropper.remove(),this.$cropper=null)},render:function(){this.initContainer(),this.initCanvas(),this.initCropBox(),this.renderCanvas(),this.isCropped&&this.renderCropBox()},initContainer:function(){var t=this.options,i=this.$element,e=this.$container,s=this.$cropper;s.addClass(Y),i.removeClass(Y),s.css(this.container={width:xt(e.width(),vt(t.minContainerWidth)||200),height:xt(e.height(),vt(t.minContainerHeight)||100)}),i.addClass(Y),s.removeClass(Y)},initCanvas:function(){var i,e=this.options.viewMode,s=this.container,a=s.width,o=s.height,h=this.image,n=h.naturalWidth,r=h.naturalHeight,p=90===Ct(h.rotate),c=p?r:n,l=p?n:r,d=c/l,g=a,u=o;o*d>a?3===e?g=o*d:u=a/d:3===e?u=a/d:g=o*d,i={naturalWidth:c,naturalHeight:l,aspectRatio:d,width:g,height:u},i.oldLeft=i.left=(a-g)/2,i.oldTop=i.top=(o-u)/2,this.canvas=i,this.isLimited=1===e||2===e,this.limitCanvas(!0,!0),this.initialImage=t.extend({},h),this.initialCanvas=t.extend({},i)},limitCanvas:function(t,i){var e,s,a,o,h=this.options,n=h.viewMode,r=this.container,p=r.width,c=r.height,l=this.canvas,d=l.aspectRatio,g=this.cropBox,u=this.isCropped&&g;t&&(e=vt(h.minCanvasWidth)||0,s=vt(h.minCanvasHeight)||0,n&&(n>1?(e=xt(e,p),s=xt(s,c),3===n&&(s*d>e?e=s*d:s=e/d)):e?e=xt(e,u?g.width:0):s?s=xt(s,u?g.height:0):u&&(e=g.width,s=g.height,s*d>e?e=s*d:s=e/d)),e&&s?s*d>e?s=e/d:e=s*d:e?s=e/d:s&&(e=s*d),l.minWidth=e,l.minHeight=s,l.maxWidth=1/0,l.maxHeight=1/0),i&&(n?(a=p-l.width,o=c-l.height,l.minLeft=wt(0,a),l.minTop=wt(0,o),l.maxLeft=xt(0,a),l.maxTop=xt(0,o),u&&this.isLimited&&(l.minLeft=wt(g.left,g.left+g.width-l.width),l.minTop=wt(g.top,g.top+g.height-l.height),l.maxLeft=g.left,l.maxTop=g.top,2===n&&(l.width>=p&&(l.minLeft=wt(0,a),l.maxLeft=xt(0,a)),l.height>=c&&(l.minTop=wt(0,o),l.maxTop=xt(0,o))))):(l.minLeft=-l.width,l.minTop=-l.height,l.maxLeft=p,l.maxTop=c))},renderCanvas:function(t){var i,e,s=this.canvas,a=this.image,o=a.rotate,h=a.naturalWidth,n=a.naturalHeight;this.isRotated&&(this.isRotated=!1,e=c({width:a.width,height:a.height,degree:o}),i=e.width/e.height,i!==s.aspectRatio&&(s.left-=(e.width-s.width)/2,s.top-=(e.height-s.height)/2,s.width=e.width,s.height=e.height,s.aspectRatio=i,s.naturalWidth=h,s.naturalHeight=n,o%180&&(e=c({width:h,height:n,degree:o}),s.naturalWidth=e.width,s.naturalHeight=e.height),this.limitCanvas(!0,!1))),(s.width>s.maxWidth||s.width<s.minWidth)&&(s.left=s.oldLeft),(s.height>s.maxHeight||s.height<s.minHeight)&&(s.top=s.oldTop),s.width=wt(xt(s.width,s.minWidth),s.maxWidth),s.height=wt(xt(s.height,s.minHeight),s.maxHeight),this.limitCanvas(!1,!0),s.oldLeft=s.left=wt(xt(s.left,s.minLeft),s.maxLeft),s.oldTop=s.top=wt(xt(s.top,s.minTop),s.maxTop),this.$canvas.css({width:s.width,height:s.height,left:s.left,top:s.top}),this.renderImage(),this.isCropped&&this.isLimited&&this.limitCropBox(!0,!0),t&&this.output()},renderImage:function(i){var e,s=this.canvas,a=this.image;a.rotate&&(e=c({width:s.width,height:s.height,degree:a.rotate,aspectRatio:a.aspectRatio},!0)),t.extend(a,e?{width:e.width,height:e.height,left:(s.width-e.width)/2,top:(s.height-e.height)/2}:{width:s.width,height:s.height,left:0,top:0}),this.$clone.css({width:a.width,height:a.height,marginLeft:a.left,marginTop:a.top,transform:p(a)}),i&&this.output()},initCropBox:function(){var i=this.options,e=this.canvas,s=i.aspectRatio,a=vt(i.autoCropArea)||.8,o={width:e.width,height:e.height};s&&(e.height*s>e.width?o.height=o.width/s:o.width=o.height*s),this.cropBox=o,this.limitCropBox(!0,!0),o.width=wt(xt(o.width,o.minWidth),o.maxWidth),o.height=wt(xt(o.height,o.minHeight),o.maxHeight),o.width=xt(o.minWidth,o.width*a),o.height=xt(o.minHeight,o.height*a),o.oldLeft=o.left=e.left+(e.width-o.width)/2,o.oldTop=o.top=e.top+(e.height-o.height)/2,this.initialCropBox=t.extend({},o)},limitCropBox:function(t,i){var e,s,a,o,h=this.options,n=h.aspectRatio,r=this.container,p=r.width,c=r.height,l=this.canvas,d=this.cropBox,g=this.isLimited;t&&(e=vt(h.minCropBoxWidth)||0,s=vt(h.minCropBoxHeight)||0,e=wt(e,p),s=wt(s,c),a=wt(p,g?l.width:p),o=wt(c,g?l.height:c),n&&(e&&s?s*n>e?s=e/n:e=s*n:e?s=e/n:s&&(e=s*n),o*n>a?o=a/n:a=o*n),d.minWidth=wt(e,a),d.minHeight=wt(s,o),d.maxWidth=a,d.maxHeight=o),i&&(g?(d.minLeft=xt(0,l.left),d.minTop=xt(0,l.top),d.maxLeft=wt(p,l.left+l.width)-d.width,d.maxTop=wt(c,l.top+l.height)-d.height):(d.minLeft=0,d.minTop=0,d.maxLeft=p-d.width,d.maxTop=c-d.height))},renderCropBox:function(){var t=this.options,i=this.container,e=i.width,s=i.height,a=this.cropBox;(a.width>a.maxWidth||a.width<a.minWidth)&&(a.left=a.oldLeft),(a.height>a.maxHeight||a.height<a.minHeight)&&(a.top=a.oldTop),a.width=wt(xt(a.width,a.minWidth),a.maxWidth),a.height=wt(xt(a.height,a.minHeight),a.maxHeight),this.limitCropBox(!1,!0),a.oldLeft=a.left=wt(xt(a.left,a.minLeft),a.maxLeft),a.oldTop=a.top=wt(xt(a.top,a.minTop),a.maxTop),t.movable&&t.cropBoxMovable&&this.$face.data(it,a.width===e&&a.height===s?dt:ct),this.$cropBox.css({width:a.width,height:a.height,left:a.left,top:a.top}),this.isCropped&&this.isLimited&&this.limitCanvas(!0,!0),this.isDisabled||this.output()},output:function(){this.preview(),this.isCompleted&&this.trigger(K,this.getData())},initPreview:function(){var i,e=n(this.crossOrigin),s=e?this.crossOriginUrl:this.url;this.$preview=t(this.options.preview),this.$clone2=i=t("<img"+e+' src="'+s+'">'),this.$viewBox.html(i),this.$preview.each(function(){var i=t(this);i.data(tt,{width:i.width(),height:i.height(),html:i.html()}),i.html("<img"+e+' src="'+s+'" style="display:block;width:100%;height:auto;min-width:0!important;min-height:0!important;max-width:none!important;max-height:none!important;image-orientation:0deg!important;">')})},resetPreview:function(){this.$preview.each(function(){var i=t(this),e=i.data(tt);i.css({width:e.width,height:e.height}).html(e.html).removeData(tt)})},preview:function(){var i=this.image,e=this.canvas,s=this.cropBox,a=s.width,o=s.height,h=i.width,n=i.height,r=s.left-e.left-i.left,c=s.top-e.top-i.top;this.isCropped&&!this.isDisabled&&(this.$clone2.css({width:h,height:n,marginLeft:-r,marginTop:-c,transform:p(i)}),this.$preview.each(function(){var e=t(this),s=e.data(tt),l=s.width,d=s.height,g=l,u=d,f=1;a&&(f=l/a,u=o*f),o&&u>d&&(f=d/o,g=a*f,u=d),e.css({width:g,height:u}).find("img").css({width:h*f,height:n*f,marginLeft:-r*f,marginTop:-c*f,transform:p(i)})}))},bind:function(){var i=this.options,e=this.$element,s=this.$cropper;t.isFunction(i.cropstart)&&e.on(N,i.cropstart),t.isFunction(i.cropmove)&&e.on(_,i.cropmove),t.isFunction(i.cropend)&&e.on(q,i.cropend),t.isFunction(i.crop)&&e.on(K,i.crop),t.isFunction(i.zoom)&&e.on(Z,i.zoom),s.on(z,t.proxy(this.cropStart,this)),i.zoomable&&i.zoomOnWheel&&s.on(E,t.proxy(this.wheel,this)),i.toggleDragModeOnDblclick&&s.on(U,t.proxy(this.dblclick,this)),x.on(O,this._cropMove=a(this.cropMove,this)).on(P,this._cropEnd=a(this.cropEnd,this)),i.responsive&&w.on(j,this._resize=a(this.resize,this))},unbind:function(){var i=this.options,e=this.$element,s=this.$cropper;t.isFunction(i.cropstart)&&e.off(N,i.cropstart),t.isFunction(i.cropmove)&&e.off(_,i.cropmove),t.isFunction(i.cropend)&&e.off(q,i.cropend),t.isFunction(i.crop)&&e.off(K,i.crop),t.isFunction(i.zoom)&&e.off(Z,i.zoom),s.off(z,this.cropStart),i.zoomable&&i.zoomOnWheel&&s.off(E,this.wheel),i.toggleDragModeOnDblclick&&s.off(U,this.dblclick),x.off(O,this._cropMove).off(P,this._cropEnd),i.responsive&&w.off(j,this._resize)},resize:function(){var i,e,s,a=this.options.restore,o=this.$container,h=this.container;!this.isDisabled&&h&&(s=o.width()/h.width,1===s&&o.height()===h.height||(a&&(i=this.getCanvasData(),e=this.getCropBoxData()),this.render(),a&&(this.setCanvasData(t.each(i,function(t,e){i[t]=e*s})),this.setCropBoxData(t.each(e,function(t,i){e[t]=i*s})))))},dblclick:function(){this.isDisabled||(this.$dragBox.hasClass(W)?this.setDragMode(dt):this.setDragMode(lt))},wheel:function(i){var e=i.originalEvent||i,s=vt(this.options.wheelZoomRatio)||.1,a=1;this.isDisabled||(i.preventDefault(),this.wheeling||(this.wheeling=!0,setTimeout(t.proxy(function(){this.wheeling=!1},this),50),e.deltaY?a=e.deltaY>0?1:-1:e.wheelDelta?a=-e.wheelDelta/120:e.detail&&(a=e.detail>0?1:-1),this.zoom(-a*s,i)))},cropStart:function(i){var e,s,a=this.options,o=i.originalEvent,h=o&&o.touches,n=i;if(!this.isDisabled){if(h){if(e=h.length,e>1){if(!a.zoomable||!a.zoomOnTouch||2!==e)return;n=h[1],this.startX2=n.pageX,this.startY2=n.pageY,s=gt}n=h[0]}if(s=s||t(n.target).data(it),Q.test(s)){if(this.trigger(N,{originalEvent:o,action:s}).isDefaultPrevented())return;i.preventDefault(),this.action=s,this.cropping=!1,this.startX=n.pageX||o&&o.pageX,this.startY=n.pageY||o&&o.pageY,s===lt&&(this.cropping=!0,this.$dragBox.addClass(T))}}},cropMove:function(t){var i,e=this.options,s=t.originalEvent,a=s&&s.touches,o=t,h=this.action;if(!this.isDisabled){if(a){if(i=a.length,i>1){if(!e.zoomable||!e.zoomOnTouch||2!==i)return;o=a[1],this.endX2=o.pageX,this.endY2=o.pageY}o=a[0]}if(h){if(this.trigger(_,{originalEvent:s,action:h}).isDefaultPrevented())return;t.preventDefault(),this.endX=o.pageX||s&&s.pageX,this.endY=o.pageY||s&&s.pageY,this.change(o.shiftKey,h===gt?t:null)}}},cropEnd:function(t){var i=t.originalEvent,e=this.action;this.isDisabled||e&&(t.preventDefault(),this.cropping&&(this.cropping=!1,this.$dragBox.toggleClass(T,this.isCropped&&this.options.modal)),this.action="",this.trigger(q,{originalEvent:i,action:e}))},change:function(t,i){var e,s,a=this.options,o=a.aspectRatio,h=this.action,n=this.container,r=this.canvas,p=this.cropBox,c=p.width,l=p.height,d=p.left,g=p.top,u=d+c,f=g+l,m=0,v=0,w=n.width,x=n.height,C=!0;switch(!o&&t&&(o=c&&l?c/l:1),this.isLimited&&(m=p.minLeft,v=p.minTop,w=m+wt(n.width,r.left+r.width),x=v+wt(n.height,r.top+r.height)),s={x:this.endX-this.startX,y:this.endY-this.startY},o&&(s.X=s.y*o,s.Y=s.x/o),h){case ct:d+=s.x,g+=s.y;break;case et:if(s.x>=0&&(u>=w||o&&(v>=g||f>=x))){C=!1;break}c+=s.x,o&&(l=c/o,g-=s.Y/2),0>c&&(h=st,c=0);break;case ot:if(s.y<=0&&(v>=g||o&&(m>=d||u>=w))){C=!1;break}l-=s.y,g+=s.y,o&&(c=l*o,d+=s.X/2),0>l&&(h=at,l=0);break;case st:if(s.x<=0&&(m>=d||o&&(v>=g||f>=x))){C=!1;break}c-=s.x,d+=s.x,o&&(l=c/o,g+=s.Y/2),0>c&&(h=et,c=0);break;case at:if(s.y>=0&&(f>=x||o&&(m>=d||u>=w))){C=!1;break}l+=s.y,o&&(c=l*o,d-=s.X/2),0>l&&(h=ot,l=0);break;case rt:if(o){if(s.y<=0&&(v>=g||u>=w)){C=!1;break}l-=s.y,g+=s.y,c=l*o}else s.x>=0?w>u?c+=s.x:s.y<=0&&v>=g&&(C=!1):c+=s.x,s.y<=0?g>v&&(l-=s.y,g+=s.y):(l-=s.y,g+=s.y);0>c&&0>l?(h=nt,l=0,c=0):0>c?(h=pt,c=0):0>l&&(h=ht,l=0);break;case pt:if(o){if(s.y<=0&&(v>=g||m>=d)){C=!1;break}l-=s.y,g+=s.y,c=l*o,d+=s.X}else s.x<=0?d>m?(c-=s.x,d+=s.x):s.y<=0&&v>=g&&(C=!1):(c-=s.x,d+=s.x),s.y<=0?g>v&&(l-=s.y,g+=s.y):(l-=s.y,g+=s.y);0>c&&0>l?(h=ht,l=0,c=0):0>c?(h=rt,c=0):0>l&&(h=nt,l=0);break;case nt:if(o){if(s.x<=0&&(m>=d||f>=x)){C=!1;break}c-=s.x,d+=s.x,l=c/o}else s.x<=0?d>m?(c-=s.x,d+=s.x):s.y>=0&&f>=x&&(C=!1):(c-=s.x,d+=s.x),s.y>=0?x>f&&(l+=s.y):l+=s.y;0>c&&0>l?(h=rt,l=0,c=0):0>c?(h=ht,c=0):0>l&&(h=pt,l=0);break;case ht:if(o){if(s.x>=0&&(u>=w||f>=x)){C=!1;break}c+=s.x,l=c/o}else s.x>=0?w>u?c+=s.x:s.y>=0&&f>=x&&(C=!1):c+=s.x,s.y>=0?x>f&&(l+=s.y):l+=s.y;0>c&&0>l?(h=pt,l=0,c=0):0>c?(h=nt,c=0):0>l&&(h=rt,l=0);break;case dt:this.move(s.x,s.y),C=!1;break;case gt:this.zoom(function(t,i,e,s){var a=yt(t*t+i*i),o=yt(e*e+s*s);return(o-a)/a}(Ct(this.startX-this.startX2),Ct(this.startY-this.startY2),Ct(this.endX-this.endX2),Ct(this.endY-this.endY2)),i),this.startX2=this.endX2,this.startY2=this.endY2,C=!1;break;case lt:if(!s.x||!s.y){C=!1;break}e=this.$cropper.offset(),d=this.startX-e.left,g=this.startY-e.top,c=p.minWidth,l=p.minHeight,s.x>0?h=s.y>0?ht:rt:s.x<0&&(d-=c,h=s.y>0?nt:pt),s.y<0&&(g-=l),this.isCropped||(this.$cropBox.removeClass(Y),this.isCropped=!0,this.isLimited&&this.limitCropBox(!0,!0))}C&&(p.width=c,p.height=l,p.left=d,p.top=g,this.action=h,this.renderCropBox()),this.startX=this.endX,this.startY=this.endY},crop:function(){this.isBuilt&&!this.isDisabled&&(this.isCropped||(this.isCropped=!0,this.limitCropBox(!0,!0),this.options.modal&&this.$dragBox.addClass(T),this.$cropBox.removeClass(Y)),this.setCropBoxData(this.initialCropBox))},reset:function(){this.isBuilt&&!this.isDisabled&&(this.image=t.extend({},this.initialImage),this.canvas=t.extend({},this.initialCanvas),this.cropBox=t.extend({},this.initialCropBox),this.renderCanvas(),this.isCropped&&this.renderCropBox())},clear:function(){this.isCropped&&!this.isDisabled&&(t.extend(this.cropBox,{left:0,top:0,width:0,height:0}),this.isCropped=!1,this.renderCropBox(),this.limitCanvas(!0,!0),this.renderCanvas(),this.$dragBox.removeClass(T),this.$cropBox.addClass(Y))},replace:function(t,i){!this.isDisabled&&t&&(this.isImg&&this.$element.attr("src",t),i?(this.url=t,this.$clone.attr("src",t),this.isBuilt&&this.$preview.find("img").add(this.$clone2).attr("src",t)):(this.isImg&&(this.isReplaced=!0),this.options.data=null,this.load(t)))},enable:function(){this.isBuilt&&(this.isDisabled=!1,this.$cropper.removeClass(H))},disable:function(){this.isBuilt&&(this.isDisabled=!0,this.$cropper.addClass(H))},destroy:function(){var t=this.$element;this.isLoaded?(this.isImg&&this.isReplaced&&t.attr("src",this.originalUrl),this.unbuild(),t.removeClass(Y)):this.isImg?t.off(I,this.start):this.$clone&&this.$clone.remove(),t.removeData(L)},move:function(t,i){var s=this.canvas;this.moveTo(e(t)?t:s.left+vt(t),e(i)?i:s.top+vt(i))},moveTo:function(t,s){var a=this.canvas,o=!1;e(s)&&(s=t),t=vt(t),s=vt(s),this.isBuilt&&!this.isDisabled&&this.options.movable&&(i(t)&&(a.left=t,o=!0),i(s)&&(a.top=s,o=!0),o&&this.renderCanvas(!0))},zoom:function(t,i){var e=this.canvas;t=vt(t),t=0>t?1/(1-t):1+t,this.zoomTo(e.width*t/e.naturalWidth,i)},zoomTo:function(t,i){var e,s,a,o,h,n=this.options,r=this.canvas,p=r.width,c=r.height,l=r.naturalWidth,g=r.naturalHeight;if(t=vt(t),t>=0&&this.isBuilt&&!this.isDisabled&&n.zoomable){if(s=l*t,a=g*t,i&&(e=i.originalEvent),this.trigger(Z,{originalEvent:e,oldRatio:p/l,ratio:s/l}).isDefaultPrevented())return;e?(o=this.$cropper.offset(),h=e.touches?d(e.touches):{pageX:i.pageX||e.pageX||0,pageY:i.pageY||e.pageY||0},r.left-=(s-p)*((h.pageX-o.left-r.left)/p),r.top-=(a-c)*((h.pageY-o.top-r.top)/c)):(r.left-=(s-p)/2,r.top-=(a-c)/2),r.width=s,r.height=a,this.renderCanvas(!0)}},rotate:function(t){this.rotateTo((this.image.rotate||0)+vt(t))},rotateTo:function(t){t=vt(t),i(t)&&this.isBuilt&&!this.isDisabled&&this.options.rotatable&&(this.image.rotate=t%360,this.isRotated=!0,this.renderCanvas(!0))},scale:function(t,s){var a=this.image,o=!1;e(s)&&(s=t),t=vt(t),s=vt(s),this.isBuilt&&!this.isDisabled&&this.options.scalable&&(i(t)&&(a.scaleX=t,o=!0),i(s)&&(a.scaleY=s,o=!0),o&&this.renderImage(!0))},scaleX:function(t){var e=this.image.scaleY;this.scale(t,i(e)?e:1)},scaleY:function(t){var e=this.image.scaleX;this.scale(i(e)?e:1,t)},getData:function(i){var e,s,a=this.options,o=this.image,h=this.canvas,n=this.cropBox;return this.isBuilt&&this.isCropped?(s={x:n.left-h.left,y:n.top-h.top,width:n.width,height:n.height},e=o.width/o.naturalWidth,t.each(s,function(t,a){a/=e,s[t]=i?Dt(a):a})):s={x:0,y:0,width:0,height:0},a.rotatable&&(s.rotate=o.rotate||0),a.scalable&&(s.scaleX=o.scaleX||1,s.scaleY=o.scaleY||1),s},setData:function(e){var s,a,o,h=this.options,n=this.image,r=this.canvas,p={};t.isFunction(e)&&(e=e.call(this.element)),this.isBuilt&&!this.isDisabled&&t.isPlainObject(e)&&(h.rotatable&&i(e.rotate)&&e.rotate!==n.rotate&&(n.rotate=e.rotate,this.isRotated=s=!0),h.scalable&&(i(e.scaleX)&&e.scaleX!==n.scaleX&&(n.scaleX=e.scaleX,a=!0),i(e.scaleY)&&e.scaleY!==n.scaleY&&(n.scaleY=e.scaleY,a=!0)),s?this.renderCanvas():a&&this.renderImage(),o=n.width/n.naturalWidth,i(e.x)&&(p.left=e.x*o+r.left),i(e.y)&&(p.top=e.y*o+r.top),i(e.width)&&(p.width=e.width*o),i(e.height)&&(p.height=e.height*o),this.setCropBoxData(p))},getContainerData:function(){return this.isBuilt?this.container:{}},getImageData:function(){return this.isLoaded?this.image:{}},getCanvasData:function(){var i=this.canvas,e={};return this.isBuilt&&t.each(["left","top","width","height","naturalWidth","naturalHeight"],function(t,s){e[s]=i[s]}),e},setCanvasData:function(e){var s=this.canvas,a=s.aspectRatio;t.isFunction(e)&&(e=e.call(this.$element)),this.isBuilt&&!this.isDisabled&&t.isPlainObject(e)&&(i(e.left)&&(s.left=e.left),i(e.top)&&(s.top=e.top),i(e.width)?(s.width=e.width,s.height=e.width/a):i(e.height)&&(s.height=e.height,s.width=e.height*a),this.renderCanvas(!0))},getCropBoxData:function(){var t,i=this.cropBox;return this.isBuilt&&this.isCropped&&(t={left:i.left,top:i.top,width:i.width,height:i.height}),t||{}},setCropBoxData:function(e){var s,a,o=this.cropBox,h=this.options.aspectRatio;t.isFunction(e)&&(e=e.call(this.$element)),this.isBuilt&&this.isCropped&&!this.isDisabled&&t.isPlainObject(e)&&(i(e.left)&&(o.left=e.left),i(e.top)&&(o.top=e.top),i(e.width)&&(s=!0,o.width=e.width),i(e.height)&&(a=!0,o.height=e.height),h&&(s?o.height=o.width/h:a&&(o.width=o.height*h)),this.renderCropBox())},getCroppedCanvas:function(i){var e,s,a,o,h,n,r,p,c,d,g;return this.isBuilt&&ft?this.isCropped?(t.isPlainObject(i)||(i={}),g=this.getData(),e=g.width,s=g.height,p=e/s,t.isPlainObject(i)&&(h=i.width,n=i.height,h?(n=h/p,r=h/e):n&&(h=n*p,r=n/s)),a=$t(h||e),o=$t(n||s),c=t("<canvas>")[0],c.width=a,c.height=o,d=c.getContext("2d"),i.fillColor&&(d.fillStyle=i.fillColor,d.fillRect(0,0,a,o)),d.drawImage.apply(d,function(){var t,i,a,o,h,n,p=l(this.$clone[0],this.image),c=p.width,d=p.height,u=this.canvas,f=[p],m=g.x+u.naturalWidth*(Ct(g.scaleX||1)-1)/2,v=g.y+u.naturalHeight*(Ct(g.scaleY||1)-1)/2;return-e>=m||m>c?m=t=a=h=0:0>=m?(a=-m,m=0,t=h=wt(c,e+m)):c>=m&&(a=0,t=h=wt(e,c-m)),0>=t||-s>=v||v>d?v=i=o=n=0:0>=v?(o=-v,v=0,i=n=wt(d,s+v)):d>=v&&(o=0,i=n=wt(s,d-v)),f.push($t(m),$t(v),$t(t),$t(i)),r&&(a*=r,o*=r,h*=r,n*=r),h>0&&n>0&&f.push($t(a),$t(o),$t(h),$t(n)),f}.call(this)),c):l(this.$clone[0],this.image):void 0},setAspectRatio:function(t){var i=this.options;this.isDisabled||e(t)||(i.aspectRatio=xt(0,t)||NaN,this.isBuilt&&(this.initCropBox(),this.isCropped&&this.renderCropBox()))},setDragMode:function(t){var i,e,s=this.options;this.isLoaded&&!this.isDisabled&&(i=t===lt,e=s.movable&&t===dt,t=i||e?t:ut,this.$dragBox.data(it,t).toggleClass(W,i).toggleClass(M,e),s.cropBoxMovable||this.$face.data(it,t).toggleClass(W,i).toggleClass(M,e))}},v.DEFAULTS={viewMode:0,dragMode:"crop",aspectRatio:NaN,data:null,preview:"",responsive:!0,restore:!0,checkCrossOrigin:!0,checkOrientation:!0,modal:!0,guides:!0,center:!0,highlight:!0,background:!0,autoCrop:!0,autoCropArea:.8,movable:!0,rotatable:!0,scalable:!0,zoomable:!0,zoomOnTouch:!0,zoomOnWheel:!0,wheelZoomRatio:.1,cropBoxMovable:!0,cropBoxResizable:!0,toggleDragModeOnDblclick:!0,minCanvasWidth:0,minCanvasHeight:0,minCropBoxWidth:0,minCropBoxHeight:0,minContainerWidth:200,minContainerHeight:100,build:null,built:null,cropstart:null,cropmove:null,cropend:null,crop:null,zoom:null},v.setDefaults=function(i){t.extend(v.DEFAULTS,i)},v.TEMPLATE='<div class="cropper-container"><div class="cropper-wrap-box"><div class="cropper-canvas"></div></div><div class="cropper-drag-box"></div><div class="cropper-crop-box"><span class="cropper-view-box"></span><span class="cropper-dashed dashed-h"></span><span class="cropper-dashed dashed-v"></span><span class="cropper-center"></span><span class="cropper-face"></span><span class="cropper-line line-e" data-action="e"></span><span class="cropper-line line-n" data-action="n"></span><span class="cropper-line line-w" data-action="w"></span><span class="cropper-line line-s" data-action="s"></span><span class="cropper-point point-e" data-action="e"></span><span class="cropper-point point-n" data-action="n"></span><span class="cropper-point point-w" data-action="w"></span><span class="cropper-point point-s" data-action="s"></span><span class="cropper-point point-ne" data-action="ne"></span><span class="cropper-point point-nw" data-action="nw"></span><span class="cropper-point point-sw" data-action="sw"></span><span class="cropper-point point-se" data-action="se"></span></div></div>',v.other=t.fn.cropper,t.fn.cropper=function(i){var a,o=s(arguments,1);return this.each(function(){var e,s,h=t(this),n=h.data(L);if(!n){if(/destroy/.test(i))return;e=t.extend({},h.data(),t.isPlainObject(i)&&i),h.data(L,n=new v(this,e))}"string"==typeof i&&t.isFunction(s=n[i])&&(a=s.apply(n,o))}),e(a)?this:a},t.fn.cropper.Constructor=v,t.fn.cropper.setDefaults=v.setDefaults,t.fn.cropper.noConflict=function(){return t.fn.cropper=v.other,this}});
0 11 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/assets/source/js/script.imagemanager.input.js 0 → 100755
  1 +var imageManagerInput = {
  2 + baseUrl: null, //language
  3 + message: null, //init imageManagerInput
  4 + init: function() {
  5 + //create modal
  6 + imageManagerInput.initModal();
  7 + }, //creat image Manager modal
  8 + initModal: function() {
  9 + //check if modal not jet exists
  10 + if ($("#modal-imagemanager").length === 0) {
  11 + //set html modal in var
  12 + var sModalHtml = '<div tabindex="-1" role="dialog" class="fade modal" id="modal-imagemanager">';
  13 + sModalHtml += '<div class="modal-dialog modal-lg">';
  14 + sModalHtml += '<div class="modal-content">';
  15 + sModalHtml += '<div class="modal-header">';
  16 + sModalHtml += '<button aria-hidden="true" data-dismiss="modal" class="close" type="button">&times;</button>';
  17 + sModalHtml += '<h4>Image manager</h4>';
  18 + sModalHtml += '</div>';
  19 + sModalHtml += '<div class="modal-body">';
  20 + sModalHtml += '<iframe src="#"></iframe>';
  21 + sModalHtml += '</div>';
  22 + sModalHtml += '</div>';
  23 + sModalHtml += '</div>';
  24 + sModalHtml += '</div>';
  25 + //prepend data to body
  26 + $('body')
  27 + .prepend(sModalHtml);
  28 + }
  29 + }, //open media manager modal
  30 + openModal: function(inputId, aspectRatio, cropViewMode) {
  31 + //get selected item
  32 + var iImageId = $("#" + inputId)
  33 + .val();
  34 + var srcImageIdQueryString = "";
  35 + if (iImageId !== "") {
  36 + srcImageIdQueryString = "&image-id=" + iImageId;
  37 + }
  38 + //create iframe url
  39 + var queryStringStartCharacter = ((imageManagerInput.baseUrl).indexOf('?') == -1) ? '?' : '&';
  40 + var imageManagerUrl = imageManagerInput.baseUrl + queryStringStartCharacter + "view-mode=iframe&input-id=" + inputId + "&aspect-ratio=" + aspectRatio + "&crop-view-mode=" + cropViewMode + srcImageIdQueryString;
  41 + //set iframe path
  42 + $("#modal-imagemanager iframe")
  43 + .attr("src", imageManagerUrl);
  44 + //set translation title for modal header
  45 + $("#modal-imagemanager .modal-dialog .modal-header h4")
  46 + .text(imageManagerInput.message.imageManager);
  47 + //open modal
  48 + $("#modal-imagemanager")
  49 + .modal("show");
  50 + }, //close media manager modal
  51 + closeModal: function() {
  52 + $("#modal-imagemanager")
  53 + .modal("hide");
  54 + }, //delete picked image
  55 + deletePickedImage: function(inputId) {
  56 + //remove value of the input field
  57 + var sFieldId = inputId;
  58 + var sFieldNameId = sFieldId + "_name";
  59 + var sImagePreviewId = sFieldId + "_image";
  60 + var bShowConfirm = JSON.parse(
  61 + $(".delete-selected-image[data-input-id='" + inputId + "']")
  62 + .data("show-delete-confirm")
  63 + );
  64 + //show warning if bShowConfirm == true
  65 + if (bShowConfirm) {
  66 + if (confirm(imageManagerInput.message.detachWarningMessage) == false) {
  67 + return false;
  68 + }
  69 + }
  70 + //set input data
  71 + $('#' + sFieldId)
  72 + .val("");
  73 + $('#' + sFieldNameId)
  74 + .val("");
  75 + //trigger change
  76 + $('#' + sFieldId)
  77 + .trigger("change");
  78 + //hide image
  79 + $('#' + sImagePreviewId)
  80 + .attr("src", "")
  81 + .parent()
  82 + .addClass("hide");
  83 + //delete hide class
  84 + $(".delete-selected-image[data-input-id='" + inputId + "']")
  85 + .addClass("hide");
  86 + }
  87 +};
  88 +
  89 +$(document)
  90 + .ready(
  91 + function() {
  92 + //init Image manage
  93 + imageManagerInput.init();
  94 +
  95 + //open media manager modal
  96 + $(document)
  97 + .on(
  98 + "click", ".open-modal-imagemanager", function() {
  99 + var aspectRatio = $(this)
  100 + .data("aspect-ratio");
  101 + var cropViewMode = $(this)
  102 + .data("crop-view-mode");
  103 + var inputId = $(this)
  104 + .data("input-id");
  105 + //open selector id
  106 + imageManagerInput.openModal(inputId, aspectRatio, cropViewMode);
  107 + }
  108 + );
  109 +
  110 + //delete picked image
  111 + $(document)
  112 + .on(
  113 + "click", ".delete-selected-image", function() {
  114 + var inputId = $(this)
  115 + .data("input-id");
  116 + //open selector id
  117 + imageManagerInput.deletePickedImage(inputId);
  118 + }
  119 + );
  120 + }
  121 + );
0 122 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/assets/source/js/script.imagemanager.module.js 0 → 100755
  1 +var imageManagerModule = {
  2 + //params for input selector
  3 + fieldId: null,
  4 + cropRatio: null,
  5 + cropViewMode: 1,
  6 + defaultImageId: null,
  7 + selectType: null, //current selected image
  8 + selectedImage: null, //language
  9 + message: null, //init imageManager
  10 + init: function() {
  11 + //init cropper
  12 + $('#module-imagemanager > .row .col-image-editor .image-cropper .image-wrapper img#image-cropper')
  13 + .cropper(
  14 + {
  15 + viewMode: imageManagerModule.cropViewMode
  16 + }
  17 + );
  18 +
  19 + //preselect image if image-id isset
  20 + if (imageManagerModule.defaultImageId !== "") {
  21 + imageManagerModule.selectImage(imageManagerModule.defaultImageId);
  22 + }
  23 +
  24 + //set selected after pjax complete
  25 + $('#pjax-mediamanager')
  26 + .on(
  27 + 'pjax:complete', function() {
  28 + if (imageManagerModule.selectedImage !== null) {
  29 + imageManagerModule.selectImage(imageManagerModule.selectedImage.id);
  30 + }
  31 + }
  32 + );
  33 +
  34 + $(document)
  35 + .on(
  36 + 'click', '#save-image-info', function() {
  37 + var form = $('#save-image-info-form');
  38 + $.ajax(
  39 + {
  40 + url: imageManagerModule.baseUrl + "/save-image-info",
  41 + type: "POST",
  42 + data: form.serialize(),
  43 + success: function(data) {
  44 + new PNotify(
  45 + {
  46 + title: "Notification",
  47 + text: "Image info saved",
  48 + type: "info",
  49 + styling: "bootstrap3",
  50 + icon: "glyphicon glyphicon-exclamation-sign"
  51 + }
  52 + );
  53 + }
  54 + }
  55 + );
  56 + }
  57 + );
  58 + }, //filter result
  59 + filterImageResult: function(searchTerm) {
  60 + //set new url
  61 + var newUrl = window.queryStringParameter.set(window.location.href, "ImageManagerSearch[globalSearch]", searchTerm);
  62 + //set pjax
  63 + $.pjax(
  64 + {
  65 + url: newUrl,
  66 + container: "#pjax-mediamanager",
  67 + push: false,
  68 + replace: false,
  69 + timeout: 5000,
  70 + scrollTo: false
  71 + }
  72 + );
  73 + }, //select an image
  74 + selectImage: function(id) {
  75 + //set selected class
  76 + $("#module-imagemanager .item-overview .item")
  77 + .removeClass("selected");
  78 + $("#module-imagemanager .item-overview .item[data-key='" + id + "']")
  79 + .addClass("selected");
  80 + //get details
  81 + imageManagerModule.getDetails(id);
  82 + }, //pick the selected image
  83 + pickImage: function() {
  84 + //switch between select type
  85 + switch (imageManagerModule.selectType) {
  86 + //default widget selector
  87 + case "input":
  88 + //get id data
  89 + var sFieldId = imageManagerModule.fieldId;
  90 + var sFieldNameId = sFieldId + "_name";
  91 + var sFieldImageId = sFieldId + "_image";
  92 + //set input data
  93 + $('#' + sFieldId, window.parent.document)
  94 + .val(imageManagerModule.selectedImage.id);
  95 + $('#' + sFieldNameId, window.parent.document)
  96 + .val(imageManagerModule.selectedImage.fileName);
  97 + $('#' + sFieldImageId, window.parent.document)
  98 + .attr("src", imageManagerModule.selectedImage.image)
  99 + .parent()
  100 + .removeClass("hide");
  101 + //trigger change
  102 + parent.$('#' + sFieldId)
  103 + .trigger('change');
  104 + //show delete button
  105 + $(".delete-selected-image[data-input-id='" + sFieldId + "']", window.parent.document)
  106 + .removeClass("hide");
  107 + //close the modal
  108 + window.parent.imageManagerInput.closeModal();
  109 + break;
  110 + //CKEditor selector
  111 + case "ckeditor":
  112 + //TinyMCE Selector
  113 + case "tinymce":
  114 + //check if isset image
  115 + if (imageManagerModule.selectedImage !== null) {
  116 + //call action by ajax
  117 + $.ajax(
  118 + {
  119 + url: imageManagerModule.baseUrl + "/get-original-image",
  120 + type: "POST",
  121 + data: {
  122 + ImageManager_id: imageManagerModule.selectedImage.id,
  123 + _csrf: $('meta[name=csrf-token]')
  124 + .prop('content')
  125 + },
  126 + dataType: "json",
  127 + success: function(responseData, textStatus, jqXHR) {
  128 + //set attributes for each selector
  129 + if (imageManagerModule.selectType == "ckeditor") {
  130 + var sField = window.queryStringParameter.get(window.location.href, "CKEditorFuncNum");
  131 + window.top.opener.CKEDITOR.tools.callFunction(sField, responseData);
  132 + window.self.close();
  133 + } else if (imageManagerModule.selectType == "tinymce") {
  134 + var sField = window.queryStringParameter.get(window.location.href, "tag_name");
  135 + window.opener.document.getElementById(sField).value = responseData;
  136 + window.close();
  137 + window.opener.focus();
  138 + }
  139 + },
  140 + error: function(jqXHR, textStatus, errorThrown) {
  141 + alert("Error: can't get item");
  142 + }
  143 + }
  144 + );
  145 + } else {
  146 + alert("Error: image can't picked");
  147 + }
  148 + break;
  149 + }
  150 +
  151 + }, //delete the selected image
  152 + deleteSelectedImage: function() {
  153 + //confirm message
  154 + if (confirm(imageManagerModule.message.deleteMessage)) {
  155 + //close editor
  156 + imageManagerModule.editor.close();
  157 + //check if isset image
  158 + if (imageManagerModule.selectedImage !== null) {
  159 + //call action by ajax
  160 + $.ajax(
  161 + {
  162 + url: imageManagerModule.baseUrl + "/delete",
  163 + type: "POST",
  164 + data: {
  165 + ImageManager_id: imageManagerModule.selectedImage.id,
  166 + _csrf: $('meta[name=csrf-token]')
  167 + .prop('content')
  168 + },
  169 + dataType: "json",
  170 + success: function(responseData, textStatus, jqXHR) {
  171 + //check if delete is true
  172 + if (responseData.delete === true) {
  173 + //delete item element
  174 + $("#module-imagemanager .item-overview .item[data-key='" + imageManagerModule.selectedImage.id + "']")
  175 + .remove();
  176 + //add hide class to info block
  177 + $("#module-imagemanager .image-info")
  178 + .addClass("hide");
  179 + //set selectedImage to null
  180 + imageManagerModule.selectedImage = null;
  181 + //close edit
  182 + } else {
  183 + alert("Error: item is not deleted");
  184 + }
  185 + },
  186 + error: function(jqXHR, textStatus, errorThrown) {
  187 + alert("Error: can't delete item");
  188 + }
  189 + }
  190 + );
  191 + } else {
  192 + alert("Error: image can't delete, no image isset set");
  193 + }
  194 + }
  195 + }, //get image details
  196 + getDetails: function(id, pickAfterGetDetails) {
  197 + //set propertie if not set
  198 + pickAfterGetDetails = pickAfterGetDetails !== undefined ? pickAfterGetDetails : false;
  199 + //call action by ajax
  200 + $.ajax(
  201 + {
  202 + url: imageManagerModule.baseUrl + "/view",
  203 + type: "POST",
  204 + data: {
  205 + ImageManager_id: id,
  206 + _csrf: $('meta[name=csrf-token]')
  207 + .prop('content')
  208 + },
  209 + dataType: "json",
  210 + success: function(responseData, textStatus, jqXHR) {
  211 + //set imageManagerModule.selectedImage property
  212 + imageManagerModule.selectedImage = responseData;
  213 +
  214 + //if need to pick image?
  215 + if (pickAfterGetDetails) {
  216 + imageManagerModule.pickImage();
  217 + //else set data
  218 + } else {
  219 + //set text elements
  220 + $("#module-imagemanager .image-info .fileName")
  221 + .text(responseData.fileName)
  222 + .attr("title", responseData.fileName);
  223 + $("#module-imagemanager .image-info .created")
  224 + .text(responseData.created);
  225 + $("#module-imagemanager .image-info .fileSize")
  226 + .text(responseData.fileSize);
  227 + $("#module-imagemanager .image-info .dimensions .dimension-width")
  228 + .text(responseData.dimensionWidth);
  229 + $("#module-imagemanager .image-info .dimensions .dimension-height")
  230 + .text(responseData.dimensionHeight);
  231 + $("#module-imagemanager .image-info .thumbnail")
  232 + .html("<img src='" + responseData.image + "' alt='" + responseData.fileName + "'/>");
  233 + $("#module-imagemanager .image-info .seo-info")
  234 + .html(responseData.div);
  235 + //remove hide class
  236 + $("#module-imagemanager .image-info")
  237 + .removeClass("hide");
  238 + }
  239 + },
  240 + error: function(jqXHR, textStatus, errorThrown) {
  241 + alert("Error: can't get ''data''");
  242 + }
  243 + }
  244 + );
  245 + }, //upload file
  246 + uploadSuccess: function(uploadResponse) {
  247 + //close editor
  248 + imageManagerModule.editor.close();
  249 + //reload pjax container
  250 + $.pjax.reload(
  251 + '#pjax-mediamanager', {
  252 + push: false,
  253 + replace: false,
  254 + timeout: 5000,
  255 + scrollTo: false
  256 + }
  257 + );
  258 + }, //editor functions
  259 + editor: {
  260 + //open editor block
  261 + open: function() {
  262 + //show editer / hide overview
  263 + $("#module-imagemanager > .row .col-image-editor")
  264 + .show();
  265 + $("#module-imagemanager > .row .col-overview")
  266 + .hide();
  267 + }, //close editor block
  268 + close: function() {
  269 + //show overview / hide editer
  270 + $("#module-imagemanager > .row .col-overview")
  271 + .show();
  272 + $("#module-imagemanager > .row .col-image-editor")
  273 + .hide();
  274 + }, //open cropper
  275 + openCropper: function() {
  276 + //check if isset image
  277 + if (imageManagerModule.selectedImage !== null) {
  278 + //call action by ajax
  279 + $.ajax(
  280 + {
  281 + url: imageManagerModule.baseUrl + "/get-original-image",
  282 + type: "POST",
  283 + data: {
  284 + ImageManager_id: imageManagerModule.selectedImage.id,
  285 + _csrf: $('meta[name=csrf-token]')
  286 + .prop('content')
  287 + },
  288 + dataType: "json",
  289 + success: function(responseData, textStatus, jqXHR) {
  290 + //hide cropper
  291 + $("#module-imagemanager > .row .col-image-cropper")
  292 + .css("visibility", "hidden");
  293 + //set image in cropper
  294 + $('#module-imagemanager > .row .col-image-editor .image-cropper .image-wrapper img#image-cropper')
  295 + .one(
  296 + 'built.cropper', function() {
  297 + //show cropper
  298 + $("#module-imagemanager > .row .col-image-cropper")
  299 + .css("visibility", "visible");
  300 + }
  301 + )
  302 + .cropper('reset')
  303 + .cropper('setAspectRatio', parseFloat(imageManagerModule.cropRatio))
  304 + .cropper('replace', responseData);
  305 + //open editor
  306 + imageManagerModule.editor.open();
  307 + },
  308 + error: function(jqXHR, textStatus, errorThrown) {
  309 + alert("Error: can't get item");
  310 + }
  311 + }
  312 + );
  313 + } else {
  314 + alert("Error: image can't crop, no image isset set");
  315 + }
  316 + }, //apply crop
  317 + applyCrop: function(pickAfterCrop) {
  318 + //set propertie if not set
  319 + pickAfterCrop = pickAfterCrop !== undefined ? pickAfterCrop : false;
  320 + //check if isset image
  321 + if (imageManagerModule.selectedImage !== null) {
  322 + //set image in cropper
  323 + var oCropData = $('#module-imagemanager > .row .col-image-editor .image-cropper .image-wrapper img#image-cropper')
  324 + .cropper("getData");
  325 + //call action by ajax
  326 + $.ajax(
  327 + {
  328 + url: imageManagerModule.baseUrl + "/crop",
  329 + type: "POST",
  330 + data: {
  331 + ImageManager_id: imageManagerModule.selectedImage.id,
  332 + CropData: oCropData,
  333 + _csrf: $('meta[name=csrf-token]')
  334 + .prop('content')
  335 + },
  336 + dataType: "json",
  337 + success: function(responseData, textStatus, jqXHR) {
  338 + //set cropped image
  339 + if (responseData !== null) {
  340 + //if pickAfterCrop is true? select directly else
  341 + if (pickAfterCrop) {
  342 + imageManagerModule.getDetails(responseData, true);
  343 + //else select the image only
  344 + } else {
  345 + //set new image
  346 + imageManagerModule.selectImage(responseData);
  347 + //reload pjax container
  348 + $.pjax.reload(
  349 + '#pjax-mediamanager', {
  350 + push: false,
  351 + replace: false,
  352 + timeout: 5000,
  353 + scrollTo: false
  354 + }
  355 + );
  356 + }
  357 + }
  358 + //close editor
  359 + imageManagerModule.editor.close();
  360 + },
  361 + error: function(jqXHR, textStatus, errorThrown) {
  362 + alert("Error: item is not cropped");
  363 + }
  364 + }
  365 + );
  366 + } else {
  367 + alert("Error: image can't crop, no image isset set");
  368 + }
  369 + }
  370 + }
  371 +};
  372 +
  373 +$(document)
  374 + .ready(
  375 + function() {
  376 + //init Image manage
  377 + imageManagerModule.init();
  378 + //on click select item (open view)
  379 + $(document)
  380 + .on(
  381 + "click", "#module-imagemanager .item-overview .item", function() {
  382 + //get id
  383 + var ImageManager_id = $(this)
  384 + .data("key");
  385 + //select image
  386 + imageManagerModule.selectImage(ImageManager_id);
  387 + }
  388 + );
  389 + //on click pick image
  390 + $(document)
  391 + .on(
  392 + "click", "#module-imagemanager .image-info .pick-image-item", function() {
  393 + imageManagerModule.pickImage();
  394 + return false;
  395 + }
  396 + );
  397 + //on click delete call "delete"
  398 + $(document)
  399 + .on(
  400 + "click", "#module-imagemanager .image-info .delete-image-item", function() {
  401 + imageManagerModule.deleteSelectedImage();
  402 + return false;
  403 + }
  404 + );
  405 + //on click crop call "crop"
  406 + $(document)
  407 + .on(
  408 + "click", "#module-imagemanager .image-info .crop-image-item", function() {
  409 + imageManagerModule.editor.openCropper();
  410 + return false;
  411 + }
  412 + );
  413 + //on click apply crop
  414 + $(document)
  415 + .on(
  416 + "click", "#module-imagemanager .image-cropper .apply-crop", function() {
  417 + imageManagerModule.editor.applyCrop();
  418 + return false;
  419 + }
  420 + );
  421 + //on click apply crop
  422 + $(document)
  423 + .on(
  424 + "click", "#module-imagemanager .image-cropper .apply-crop-select", function() {
  425 + imageManagerModule.editor.applyCrop(true);
  426 + return false;
  427 + }
  428 + );
  429 + //on click cancel crop
  430 + $(document)
  431 + .on(
  432 + "click", "#module-imagemanager .image-cropper .cancel-crop", function() {
  433 + imageManagerModule.editor.close();
  434 + return false;
  435 + }
  436 + );
  437 + //on keyup change set filter
  438 + $(document)
  439 + .on(
  440 + "keyup change", "#input-mediamanager-search", function() {
  441 + imageManagerModule.filterImageResult(
  442 + $(this)
  443 + .val()
  444 + );
  445 + }
  446 + );
  447 +
  448 + }
  449 + );
  450 +
  451 +/*
  452 + * return new get param to url
  453 + */
  454 +window.queryStringParameter = {
  455 + get: function(uri, key) {
  456 + var reParam = new RegExp('(?:[\?&]|&amp;)' + key + '=([^&]+)', 'i');
  457 + var match = uri.match(reParam);
  458 + return (match && match.length > 1) ? match[ 1 ] : null;
  459 + },
  460 + set: function(uri, key, value) {
  461 + //replace brackets
  462 + var keyReplace = key.replace("[]", "")
  463 + .replace(/\[/g, "%5B")
  464 + .replace(/\]/g, "%5D");
  465 + //replace data
  466 + var re = new RegExp("([?&])" + keyReplace + "=.*?(&|$)", "i");
  467 + var separator = uri.indexOf('?') !== -1 ? "&" : "?";
  468 + if (uri.match(re)) {
  469 + return uri.replace(re, '$1' + keyReplace + "=" + value + '$2');
  470 + } else {
  471 + return uri + separator + keyReplace + "=" + value;
  472 + }
  473 + }
  474 +};
0 475 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/components/ImageManagerGetPath.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components\imagemanager\components;
  4 +
  5 + use yii\base\Component;
  6 + use artbox\core\components\imagemanager\models\ImageManager;
  7 +
  8 + class ImageManagerGetPath extends Component
  9 + {
  10 +
  11 + /**
  12 + * @var null|string $mediaPath Folder path in which the images are stored
  13 + */
  14 + public $mediaPath = null;
  15 +
  16 + /**
  17 + * @var string $cachePath cache path where store the resized images (relative from webroot (index.php))
  18 + */
  19 + public $cachePath = "assets/imagemanager";
  20 +
  21 + /**
  22 + * @var boolean $useFilename use original filename in generated cache file
  23 + */
  24 + public $useFilename = true;
  25 +
  26 + /**
  27 + * @var boolean $useFilename use original filename in generated cache file
  28 + */
  29 + public $absoluteUrl = false;
  30 +
  31 + /*
  32 + * Init set config
  33 + */
  34 +
  35 + public function init()
  36 + {
  37 + parent::init();
  38 + // initialize the compontent with the configuration loaded from config.php
  39 + \Yii::$app->set(
  40 + 'imageresize',
  41 + [
  42 + 'class' => 'artbox\core\components\imageresize\ImageResize',
  43 + 'cachePath' => $this->cachePath,
  44 + 'useFilename' => $this->useFilename,
  45 + 'absoluteUrl' => $this->absoluteUrl,
  46 + ]
  47 + );
  48 + }
  49 +
  50 + /**
  51 + * Get the path for the given ImageManager_id record
  52 + *
  53 + * @param int $ImageManager_id ImageManager record for which the path needs to be generated
  54 + * @param int $width Thumbnail image width
  55 + * @param int $height Thumbnail image height
  56 + * @param string $thumbnailMode Thumbnail mode
  57 + *
  58 + * @return null|string Full path is returned when image is found, null if no image could be found
  59 + */
  60 + public function getImagePath($ImageManager_id, $width = 400, $height = 400, $thumbnailMode = "outbound")
  61 + {
  62 + //default return
  63 + $return = null;
  64 + $mImageManager = ImageManager::findOne($ImageManager_id);
  65 +
  66 + //check if not empty
  67 + if ($mImageManager !== null) {
  68 + //set crop mode
  69 + $mode = $thumbnailMode == "outbound" ? "outbound" : "inset";
  70 +
  71 + $sMediaPath = null;
  72 + if ($this->mediaPath !== null) {
  73 + $sMediaPath = $this->mediaPath;
  74 + }
  75 +
  76 + $sFileExtension = pathinfo($mImageManager->fileName, PATHINFO_EXTENSION);
  77 + //get image file path
  78 + $sImageFilePath = $sMediaPath . '/' . $mImageManager->id . '_' . $mImageManager->fileHash . '.' . $sFileExtension;
  79 + //check file exists
  80 + if (file_exists($sImageFilePath)) {
  81 + $return = \Yii::$app->imageresize->getUrl(
  82 + $sImageFilePath,
  83 + $width,
  84 + $height,
  85 + $mode,
  86 + null,
  87 + $mImageManager->fileName
  88 + );
  89 + } else {
  90 + $return = null; //isset(\Yii::$app->controller->module->assetPublishedUrl) ? \Yii::$app->controller->module->assetPublishedUrl. "/img/img_no-image.png" : null;
  91 + }
  92 + }
  93 + return $return;
  94 + }
  95 +
  96 + }
... ...
artweb/artbox-core/components/imagemanager/components/ImageManagerInputWidget.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components\imagemanager\components;
  4 +
  5 + use Yii;
  6 + use yii\widgets\InputWidget;
  7 + use yii\helpers\Html;
  8 + use yii\helpers\Json;
  9 + use yii\helpers\Url;
  10 + use artbox\core\components\imagemanager\models\ImageManager;
  11 + use artbox\core\components\imagemanager\assets\ImageManagerInputAsset;
  12 +
  13 + class ImageManagerInputWidget extends InputWidget
  14 + {
  15 +
  16 + /**
  17 + * @var null|integer The aspect ratio the image needs to be cropped in (optional)
  18 + */
  19 + public $aspectRatio = null; //option info: https://github.com/fengyuanchen/cropper/#aspectratio
  20 +
  21 + /**
  22 + * @var int Define the viewMode of the cropper
  23 + */
  24 + public $cropViewMode = 1; //option info: https://github.com/fengyuanchen/cropper/#viewmode
  25 +
  26 + /**
  27 + * @var bool Show a preview of the image under the input
  28 + */
  29 + public $showPreview = true;
  30 +
  31 + /**
  32 + * @var bool Show a confirmation message when de-linking a image from the input
  33 + */
  34 + public $showDeletePickedImageConfirm = false;
  35 +
  36 + /**
  37 + * @inheritdoc
  38 + */
  39 + public function init()
  40 + {
  41 + parent::init();
  42 + //set language
  43 + if (!isset(Yii::$app->i18n->translations[ 'imagemanager' ])) {
  44 + Yii::$app->i18n->translations[ 'imagemanager' ] = [
  45 + 'class' => 'yii\i18n\PhpMessageSource',
  46 + 'sourceLanguage' => 'en',
  47 + 'basePath' => '@artbox/core/components/imagemanager/messages',
  48 + ];
  49 + }
  50 + }
  51 +
  52 + /**
  53 + * @inheritdoc
  54 + */
  55 + public function run()
  56 + {
  57 + //default
  58 + $ImageManager_id = null;
  59 + $mImageManager = null;
  60 + $sFieldId = null;
  61 + //start input group
  62 + $field = "<div class='image-manager-input'>";
  63 + $field .= "<div class='input-group'>";
  64 + //set input fields
  65 + if ($this->hasModel()) {
  66 + //get field id
  67 + $sFieldId = Html::getInputId($this->model, $this->attribute);
  68 + $sFieldNameId = $sFieldId . "_name";
  69 + //get attribute name
  70 + $sFieldAttributeName = Html::getAttributeName($this->attribute);
  71 + //get filename from selected file
  72 + $ImageManager_id = $this->model->{$sFieldAttributeName};
  73 + $ImageManager_fileName = null;
  74 + if($ImageManager_id) {
  75 + $mImageManager = ImageManager::findOne($ImageManager_id);
  76 + } else {
  77 + $mImageManager = null;
  78 + }
  79 + if ($mImageManager !== null) {
  80 + $ImageManager_fileName = $mImageManager->fileName;
  81 + }
  82 + //create field
  83 + $field .= Html::textInput(
  84 + $this->attribute,
  85 + $ImageManager_fileName,
  86 + [
  87 + 'class' => 'form-control',
  88 + 'id' => $sFieldNameId,
  89 + 'readonly' => true,
  90 + ]
  91 + );
  92 + $field .= Html::activeHiddenInput($this->model, $this->attribute, $this->options);
  93 + } else {
  94 + $field .= Html::textInput($this->name . "_name", null, [ 'readonly' => true ]);
  95 + $field .= Html::hiddenInput($this->name, $this->value, $this->options);
  96 + }
  97 + //end input group
  98 + $sHideClass = $ImageManager_id === null ? 'hide' : '';
  99 + $field .= "<a href='#' class='input-group-addon btn btn-primary delete-selected-image " . $sHideClass . "' data-input-id='" . $sFieldId . "' data-show-delete-confirm='" . ( $this->showDeletePickedImageConfirm ? "true" : "false" ) . "'><i class='glyphicon glyphicon-remove' aria-hidden='true'></i></a>";
  100 + $field .= "<a href='#' class='input-group-addon btn btn-primary open-modal-imagemanager' data-aspect-ratio='" . $this->aspectRatio . "' data-crop-view-mode='" . $this->cropViewMode . "' data-input-id='" . $sFieldId . "'>";
  101 + $field .= "<i class='glyphicon glyphicon-folder-open' aria-hidden='true'></i>";
  102 + $field .= "</a></div>";
  103 +
  104 + //show preview if is true
  105 + if ($this->showPreview == true) {
  106 + $sHideClass = ( $mImageManager == null ) ? "hide" : "";
  107 + $sImageSource = isset($mImageManager->id) ? \Yii::$app->imagemanager->getImagePath(
  108 + $mImageManager->id,
  109 + 500,
  110 + 500,
  111 + 'inset'
  112 + ) : "";
  113 +
  114 + $field .= '<div class="image-wrapper ' . $sHideClass . '">' . '<img id="' . $sFieldId . '_image" alt="Thumbnail" class="img-responsive img-preview" src="' . $sImageSource . '">' . '</div>';
  115 + }
  116 +
  117 + //close image-manager-input div
  118 + $field .= "</div>";
  119 +
  120 + echo $field;
  121 +
  122 + $this->registerClientScript();
  123 + }
  124 +
  125 + /**
  126 + * Registers js Input
  127 + */
  128 + public function registerClientScript()
  129 + {
  130 + $view = $this->getView();
  131 + ImageManagerInputAsset::register($view);
  132 +
  133 + //set baseUrl from image manager
  134 + $sBaseUrl = Url::to([ '/imagemanager/manager' ]);
  135 + //set base url
  136 + $view->registerJs("imageManagerInput.baseUrl = '" . $sBaseUrl . "';");
  137 + $view->registerJs(
  138 + "imageManagerInput.message = " . Json::encode(
  139 + [
  140 + 'imageManager' => Yii::t('imagemanager', 'Image manager'),
  141 + 'detachWarningMessage' => Yii::t('imagemanager', 'Are you sure you want to detach the image?'),
  142 + ]
  143 + ) . ";"
  144 + );
  145 + }
  146 +
  147 + }
... ...
artweb/artbox-core/components/imagemanager/controllers/DefaultController.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components\imagemanager\controllers;
  4 +
  5 + use yii\web\Controller;
  6 +
  7 + /**
  8 + * Default controller for the `imagemanager` module
  9 + */
  10 + class DefaultController extends Controller
  11 + {
  12 + /**
  13 + * Renders the index view for the module
  14 + *
  15 + * @return string
  16 + */
  17 + public function actionIndex()
  18 + {
  19 + return $this->render('index');
  20 + }
  21 + }
... ...
artweb/artbox-core/components/imagemanager/controllers/ManagerController.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components\imagemanager\controllers;
  4 +
  5 + use artbox\core\components\imagemanager\models\ImageManagerLang;
  6 + use artbox\core\models\Language;
  7 + use Yii;
  8 + use artbox\core\components\imagemanager\models\ImageManager;
  9 + use artbox\core\components\imagemanager\models\ImageManagerSearch;
  10 + use yii\web\Response;
  11 + use yii\web\Controller;
  12 + use yii\web\NotFoundHttpException;
  13 + use yii\filters\VerbFilter;
  14 + use yii\helpers\Url;
  15 + use yii\helpers\Json;
  16 + use yii\helpers\BaseFileHelper;
  17 + use yii\imagine\Image;
  18 + use Imagine\Image\Box;
  19 + use Imagine\Image\Point;
  20 + use artbox\core\components\imagemanager\Module;
  21 + use Imagine\Image\Palette\RGB;
  22 +
  23 + /**
  24 + * Manager controller for the `imagemanager` module
  25 + */
  26 + class ManagerController extends Controller
  27 + {
  28 +
  29 + /**
  30 + * @inheritdoc
  31 + */
  32 + public function behaviors()
  33 + {
  34 + return [
  35 + 'verbs' => [
  36 + 'class' => VerbFilter::className(),
  37 + 'actions' => [
  38 + 'delete' => [ 'POST' ],
  39 + ],
  40 + ],
  41 + ];
  42 + }
  43 +
  44 + /**
  45 + * @inheritdoc
  46 + */
  47 + public function beforeAction($action)
  48 + {
  49 + //disable CSRF Validation
  50 + $this->enableCsrfValidation = false;
  51 + return parent::beforeAction($action);
  52 + }
  53 +
  54 + /**
  55 + * Lists all ImageManager models.
  56 + *
  57 + * @return mixed
  58 + */
  59 + public function actionIndex()
  60 + {
  61 + //get iframe parameters
  62 + $viewMode = Yii::$app->request->get("view-mode", "page");
  63 + $selectType = Yii::$app->request->get("select-type", "input");
  64 + $inputFieldId = Yii::$app->request->get("input-id");
  65 + $cropAspectRatio = Yii::$app->request->get("aspect-ratio");
  66 + $cropViewMode = Yii::$app->request->get("crop-view-mode", 1);
  67 + $defaultImageId = Yii::$app->request->get("image-id");
  68 +
  69 + //set blank layout if viewMode = iframe
  70 + if ($viewMode == "iframe") {
  71 + //set layout
  72 + $this->layout = "blank";
  73 +
  74 + //set stylesheet for modal
  75 + $aCssFiles = \Yii::$app->controller->module->cssFiles;
  76 + if (is_array($aCssFiles) && count($aCssFiles) > 0) {
  77 + //if exists loop through files and add them to iframe mode
  78 + foreach ($aCssFiles AS $cssFile) {
  79 + //registrate file
  80 + $this->view->registerCssFile($cssFile, [ 'depends' => 'yii\bootstrap\BootstrapAsset' ]);
  81 + }
  82 + }
  83 + }
  84 +
  85 + //set baseUrl from image manager
  86 + $sBaseUrl = Url::to([ '/imagemanager/manager' ]);
  87 + //set base url
  88 + $this->view->registerJs("imageManagerModule.baseUrl = '" . $sBaseUrl . "';", 3);
  89 + $this->view->registerJs("imageManagerModule.defaultImageId = '" . $defaultImageId . "';", 3);
  90 + $this->view->registerJs("imageManagerModule.fieldId = '" . $inputFieldId . "';", 3);
  91 + $this->view->registerJs("imageManagerModule.cropRatio = '" . $cropAspectRatio . "';", 3);
  92 + $this->view->registerJs("imageManagerModule.cropViewMode = '" . $cropViewMode . "';", 3);
  93 + $this->view->registerJs("imageManagerModule.selectType = '" . $selectType . "';", 3);
  94 + $this->view->registerJs(
  95 + "imageManagerModule.message = " . Json::encode(
  96 + [
  97 + 'deleteMessage' => Yii::t('imagemanager', 'Are you sure you want to delete this image?'),
  98 + ]
  99 + ) . ";",
  100 + 3
  101 + );
  102 +
  103 + $searchModel = new ImageManagerSearch();
  104 + $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
  105 +
  106 + //render template
  107 + return $this->render(
  108 + 'index',
  109 + [
  110 + 'searchModel' => $searchModel,
  111 + 'dataProvider' => $dataProvider,
  112 + 'viewMode' => $viewMode,
  113 + 'selectType' => $selectType,
  114 + ]
  115 + );
  116 + }
  117 +
  118 + /**
  119 + * Creates a new ImageManager model.
  120 + * If creation is successful, the browser will be redirected to the 'view' page.
  121 + *
  122 + * @return mixed
  123 + */
  124 + public function actionUpload()
  125 + {
  126 + //set response header
  127 + Yii::$app->getResponse()->format = Response::FORMAT_JSON;
  128 +
  129 + // Check if the user is allowed to upload the image
  130 + if (Yii::$app->controller->module->canUploadImage == false) {
  131 + // Return the response array to prevent from the action being executed any further
  132 + return [];
  133 + }
  134 +
  135 + //disable Csrf
  136 + Yii::$app->controller->enableCsrfValidation = false;
  137 + //return default
  138 + $return = $_FILES;
  139 + //set media path
  140 + $sMediaPath = \Yii::$app->imagemanager->mediaPath;
  141 + //create the folder
  142 + BaseFileHelper::createDirectory($sMediaPath);
  143 +
  144 + //check file isset
  145 + if (isset($_FILES[ 'imagemanagerFiles' ][ 'tmp_name' ])) {
  146 + //loop through each uploaded file
  147 + foreach ($_FILES[ 'imagemanagerFiles' ][ 'tmp_name' ] AS $key => $sTempFile) {
  148 + //collect variables
  149 + $sFileName = $_FILES[ 'imagemanagerFiles' ][ 'name' ][ $key ];
  150 + $sFileExtension = pathinfo($sFileName, PATHINFO_EXTENSION);
  151 + $iErrorCode = $_FILES[ 'imagemanagerFiles' ][ 'error' ][ $key ];
  152 + //if uploaded file has no error code than continue;
  153 + if ($iErrorCode == 0) {
  154 + //create a file record
  155 + $model = new ImageManager();
  156 + $model->fileName = str_replace("_", "-", $sFileName);
  157 + $model->fileHash = Yii::$app->getSecurity()
  158 + ->generateRandomString(32);
  159 + //if file is saved add record
  160 + if ($model->save()) {
  161 + //move file to dir
  162 + $sSaveFileName = $model->id . "_" . $model->fileHash . "." . $sFileExtension;
  163 + //move_uploaded_file($sTempFile, $sMediaPath."/".$sFileName);
  164 + //save with Imagine class
  165 + Image::getImagine()
  166 + ->open($sTempFile)
  167 + ->save($sMediaPath . "/" . $sSaveFileName,[
  168 + 'quality' => 100,
  169 + ]);
  170 + }
  171 + }
  172 + }
  173 + }
  174 + //echo return json encoded
  175 + return $return;
  176 + }
  177 +
  178 + /**
  179 + * Crop image and create new ImageManager model.
  180 + *
  181 + * @return mixed
  182 + */
  183 + public function actionCrop()
  184 + {
  185 + //return
  186 + $return = null;
  187 + //disable Csrf
  188 + Yii::$app->controller->enableCsrfValidation = false;
  189 + //set response header
  190 + Yii::$app->getResponse()->format = Response::FORMAT_JSON;
  191 + //set media path
  192 + $sMediaPath = \Yii::$app->imagemanager->mediaPath;
  193 + //get post
  194 + $ImageManager_id = Yii::$app->request->post("ImageManager_id");
  195 + $aCropData = Yii::$app->request->post("CropData");
  196 + //get details
  197 + $modelOriginal = $this->findModel($ImageManager_id);
  198 + //check if path is not null
  199 + if ($modelOriginal->imagePathPrivate !== null && $aCropData !== null) {
  200 + //dimension
  201 + $iDimensionWidth = round($aCropData[ 'width' ]);
  202 + $iDimensionHeight = round($aCropData[ 'height' ]);
  203 + //collect variables
  204 + $sFileNameReplace = preg_replace("/_crop_\d+x\d+/", "", $modelOriginal->fileName);
  205 + $sFileName = pathinfo($sFileNameReplace, PATHINFO_FILENAME);
  206 + $sFileExtension = pathinfo($sFileNameReplace, PATHINFO_EXTENSION);
  207 + $sDisplayFileName = $sFileName . "_crop_" . $iDimensionWidth . "x" . $iDimensionHeight . "." . $sFileExtension;
  208 +
  209 + //create a file record
  210 + $model = new ImageManager();
  211 + $model->fileName = $sDisplayFileName;
  212 + $model->fileHash = Yii::$app->getSecurity()
  213 + ->generateRandomString(32);
  214 + //if file is saved add record
  215 + if ($model->save()) {
  216 + //create file to dir
  217 + $sSaveFileName = $model->id . "_" . $model->fileHash . "." . $sFileExtension;
  218 +
  219 + if ($aCropData[ 'x' ] < 0 || $aCropData[ 'y' ] < 0) {
  220 + //get position
  221 + $posX = $aCropData[ 'x' ];
  222 + $posY = $aCropData[ 'y' ];
  223 + //get image size
  224 + $sizeImage = getimagesize($modelOriginal->imagePathPrivate);
  225 + $sizeImageW = $sizeImage[ 0 ]; // natural width
  226 + $sizeImageH = $sizeImage[ 1 ]; // natural height
  227 + //get orignal image and crop it
  228 + $iCropWidth = $sizeImageW;
  229 + if ($sizeImageW > $aCropData[ 'width' ]) {
  230 + $iCropWidth = $aCropData[ 'width' ] - abs($posX);
  231 + }
  232 + $iCropHeight = $sizeImageH;
  233 + if ($sizeImageH > $aCropData[ 'height' ]) {
  234 + $iCropHeight = $aCropData[ 'height' ] - abs($posY);
  235 + }
  236 +
  237 + //crop image
  238 + $image = Image::getImagine()
  239 + ->open($modelOriginal->imagePathPrivate)
  240 + ->crop(new Point(0, 0), new Box($iCropWidth, $iCropHeight));
  241 +
  242 + //create image
  243 + $size = new Box($aCropData[ 'width' ], $aCropData[ 'height' ]);
  244 + // $color = new Color('#FFF', 100);
  245 + Image::getImagine()
  246 + ->create($size, ( new RGB() )->color('#FFF'))
  247 + ->paste(
  248 + $image,
  249 + new Point(( $posX < 0 ? abs($posX) : $posX ), ( $posY < 0 ? abs($posY) : $posY ))
  250 + )
  251 + ->crop(
  252 + new Point(( $posX < 0 ? 0 : $posX ), ( $posY < 0 ? 0 : $posY )),
  253 + new Box($aCropData[ 'width' ], $aCropData[ 'height' ])
  254 + )
  255 + ->save($sMediaPath . "/" . $sSaveFileName);
  256 + } else {
  257 + //save new image
  258 + Image::getImagine()
  259 + ->open($modelOriginal->imagePathPrivate)
  260 + ->crop(
  261 + new Point($aCropData[ 'x' ], $aCropData[ 'y' ]),
  262 + new Box($aCropData[ 'width' ], $aCropData[ 'height' ])
  263 + )
  264 + ->save($sMediaPath . "/" . $sSaveFileName);
  265 + }
  266 +
  267 + //set return id
  268 + $return = $model->id;
  269 + }
  270 + }
  271 + //echo return json encoded
  272 + return $return;
  273 + }
  274 +
  275 + /**
  276 + * Get view details
  277 + *
  278 + * @return mixed
  279 + */
  280 + public function actionView()
  281 + {
  282 + //disable Csrf
  283 + Yii::$app->controller->enableCsrfValidation = false;
  284 + //return default
  285 + $return = [];
  286 + //set response header
  287 + Yii::$app->getResponse()->format = Response::FORMAT_JSON;
  288 + //get post
  289 + $ImageManager_id = Yii::$app->request->post("ImageManager_id");
  290 + //get details
  291 + $model = $this->findModel($ImageManager_id);
  292 + //set return details
  293 + $return[ 'id' ] = $model->id;
  294 + $return[ 'fileName' ] = $model->fileName;
  295 + $return[ 'created' ] = Yii::$app->formatter->asDate($model->created);
  296 + $return[ 'fileSize' ] = $model->imageDetails[ 'size' ];
  297 + $return[ 'dimensionWidth' ] = $model->imageDetails[ 'width' ];
  298 + $return[ 'dimensionHeight' ] = $model->imageDetails[ 'height' ];
  299 + $return[ 'image' ] = \Yii::$app->imagemanager->getImagePath($model->id, 400, 400, "inset") . "?t=" . time();
  300 +
  301 + $languages = ImageManagerLang::find()
  302 + ->where([ 'image_id' => $model->id ])
  303 + ->indexBy('language_id')
  304 + ->all();
  305 +
  306 + $div = $this->renderPartial(
  307 + '_image_info',
  308 + [
  309 + 'languages' => $languages,
  310 + 'model' => $model,
  311 + ]
  312 + );
  313 +
  314 + $return[ 'div' ] = $div;
  315 +
  316 + //return json encoded
  317 + return $return;
  318 + }
  319 +
  320 + public function actionSaveImageInfo()
  321 + {
  322 + \Yii::$app->response->format = Response::FORMAT_JSON;
  323 +
  324 + if (\Yii::$app->request->isPost) {
  325 + $id = Yii::$app->request->post("image_id");
  326 +
  327 + $model = $this->findModel($id);
  328 +
  329 + $languages = ImageManagerLang::find()
  330 + ->where([ 'image_id' => $model->id ])
  331 + ->indexBy('language_id')
  332 + ->all();
  333 +
  334 + foreach (Language::getActive() as $lang_id => $language) {
  335 + if (empty($languages[ $lang_id ])) {
  336 + $lang = new ImageManagerLang();
  337 + } else {
  338 + $lang = $languages[ $lang_id ];
  339 + }
  340 + /**
  341 + * @var ImageManagerLang $lang
  342 + */
  343 +
  344 + $lang->alt = \Yii::$app->request->post('image_info')[ $lang_id ][ 'alt' ];
  345 + $lang->title = \Yii::$app->request->post('image_info')[ $lang_id ][ 'title' ];
  346 + $lang->description = \Yii::$app->request->post('image_info')[ $lang_id ][ 'description' ];
  347 + $lang->image_id = $model->id;
  348 + $lang->language_id = $lang_id;
  349 + $lang->save();
  350 + }
  351 + }
  352 +
  353 + return 'oki';
  354 + }
  355 +
  356 + /**
  357 + * Get full image
  358 + *
  359 + * @return mixed
  360 + */
  361 + public function actionGetOriginalImage()
  362 + {
  363 + //disable Csrf
  364 + Yii::$app->controller->enableCsrfValidation = false;
  365 + //set response header
  366 + Yii::$app->getResponse()->format = Response::FORMAT_JSON;
  367 + //get post
  368 + $ImageManager_id = Yii::$app->request->post("ImageManager_id");
  369 + //get details
  370 + $model = $this->findModel($ImageManager_id);
  371 + //set return
  372 + $return = \Yii::$app->imagemanager->getImagePath(
  373 + $model->id,
  374 + $model->imageDetails[ 'width' ],
  375 + $model->imageDetails[ 'height' ],
  376 + "inset"
  377 + );
  378 + //return json encoded
  379 + return $return;
  380 + }
  381 +
  382 + /**
  383 + * Deletes an existing ImageManager model.
  384 + * If deletion is successful, the browser will be redirected to the 'index' page.
  385 + *
  386 + * @return mixed
  387 + */
  388 + public function actionDelete()
  389 + {
  390 + //return
  391 + $return = [ 'delete' => false ];
  392 + //set response header
  393 + Yii::$app->getResponse()->format = Response::FORMAT_JSON;
  394 +
  395 + // Check if the user is allowed to delete the image
  396 + if (Yii::$app->controller->module->canRemoveImage == false) {
  397 + // Return the response array to prevent from the action being executed any further
  398 + return $return;
  399 + }
  400 +
  401 + //get post
  402 + $ImageManager_id = Yii::$app->request->post("ImageManager_id");
  403 + //get details
  404 + $model = $this->findModel($ImageManager_id);
  405 +
  406 + //set some data
  407 + $sFileExtension = pathinfo($model->fileName, PATHINFO_EXTENSION);
  408 + $sMediaPath = \Yii::$app->imagemanager->mediaPath;
  409 + $sFileName = $model->id . "_" . $model->fileHash . "." . $sFileExtension;
  410 + //delete record
  411 + if ($model->delete()) {
  412 + //check if file exists? if it is delete file
  413 + if (file_exists($sMediaPath . "/" . $sFileName)) {
  414 + unlink($sMediaPath . "/" . $sFileName);
  415 + }
  416 + $return[ 'delete' ] = true;
  417 + }
  418 + return $return;
  419 + }
  420 +
  421 + /**
  422 + * Finds the ImageManager model based on its primary key value.
  423 + * If the model is not found, a 404 HTTP exception will be thrown.
  424 + *
  425 + * @param integer $id
  426 + *
  427 + * @return ImageManager the loaded model
  428 + * @throws NotFoundHttpException if the model cannot be found
  429 + */
  430 + protected function findModel($id)
  431 + {
  432 + if (( $model = ImageManager::findOne($id) ) !== null) {
  433 + /* @var $model ImageManager */
  434 + // Get the module instance
  435 + $module = Module::getInstance();
  436 +
  437 + // Check if the model belongs to this user
  438 + if ($module->setBlameableBehavior) {
  439 + // Check if the user and record ID match
  440 + if (Yii::$app->user->id != $model->createdBy) {
  441 + throw new NotFoundHttpException(Yii::t('imagemanager', 'The requested image does not exist.'));
  442 + }
  443 + }
  444 +
  445 + return $model;
  446 + } else {
  447 + throw new NotFoundHttpException(Yii::t('imagemanager', 'The requested image does not exist.'));
  448 + }
  449 + }
  450 +
  451 + }
... ...
artweb/artbox-core/components/imagemanager/docs/images/img_doc-image-manager-crop.jpg 0 → 100755

75.7 KB

artweb/artbox-core/components/imagemanager/docs/images/img_doc-image-manager.jpg 0 → 100755

62.9 KB

artweb/artbox-core/components/imagemanager/docs/images/img_doc-image-widget-popup.jpg 0 → 100755

67.8 KB

artweb/artbox-core/components/imagemanager/docs/images/img_doc-image-widget.jpg 0 → 100755

10 KB

artweb/artbox-core/components/imagemanager/messages/de/imagemanager.php 0 → 100755
  1 +<?php
  2 + return [
  3 + 'Are you sure you want to delete this image?' => 'Wollen Sie dieses Bild wirklich löschen?',
  4 + 'Are you sure you want to detach the image?' => 'Wollen Sie dieses Bild wirklich lösen?',
  5 + 'Cancel' => 'Annullieren',
  6 + 'Created' => 'Erstellt',
  7 + 'Crop' => 'Zuschneiden',
  8 + 'Crop and select' => 'Zuschneiden und auswählen',
  9 + 'Delete' => 'Löschen',
  10 + 'File hash' => 'File hash',
  11 + 'File name' => 'File Name',
  12 + 'Modified' => 'Geändert',
  13 + 'Search' => 'Suchen',
  14 + 'Select' => 'Auswählen',
  15 + 'Image manager' => 'Image manager',
  16 + 'Upload' => 'Upload',
  17 + ];
... ...
artweb/artbox-core/components/imagemanager/messages/en/imagemanager.php 0 → 100755
  1 +<?php
  2 + return [
  3 + 'Are you sure you want to delete this image?' => 'Are you sure you want to delete this image?',
  4 + 'Are you sure you want to detach the image?' => 'Are you sure you want to detach the image?',
  5 + 'Cancel' => 'Cancel',
  6 + 'Created' => 'Created',
  7 + 'Crop' => 'Crop',
  8 + 'Crop and select' => 'Crop and select',
  9 + 'Delete' => 'Delete',
  10 + 'File hash' => 'File hash',
  11 + 'File name' => 'File name',
  12 + 'Modified' => 'Modified',
  13 + 'Search' => 'Search',
  14 + 'Select' => 'Select',
  15 + 'Image manager' => 'Image manager',
  16 + 'Upload' => 'Upload',
  17 + ];
... ...
artweb/artbox-core/components/imagemanager/messages/fr/imagemanager.php 0 → 100755
  1 +<?php
  2 + return [
  3 + 'Are you sure you want to delete this image?' => 'Voulez-vous vraiment effacer cet\'image?',
  4 + 'Are you sure you want to detach the image?' => 'Voules-vous détacher cet\'image?',
  5 + 'Cancel' => 'Annuler',
  6 + 'Created' => 'Crée',
  7 + 'Crop' => 'Ajuster',
  8 + 'Crop and select' => 'Ajuster et sélectionner',
  9 + 'Delete' => 'Effacer',
  10 + 'File hash' => 'Hash du fichier',
  11 + 'File name' => 'Nom du fichier',
  12 + 'Modified' => 'Modifié',
  13 + 'Search' => 'Rechercher',
  14 + 'Select' => 'Sélectionner',
  15 + 'Image manager' => 'Image manager',
  16 + 'Upload' => 'Upload',
  17 + ];
... ...
artweb/artbox-core/components/imagemanager/messages/it/imagemanager.php 0 → 100755
  1 +<?php
  2 + return [
  3 + 'Are you sure you want to delete this image?' => 'Vuole veramente cancellare questa immagine?',
  4 + 'Are you sure you want to detach the image?' => 'Vuole distaccare questa immagine?',
  5 + 'Cancel' => 'Cancellre',
  6 + 'Created' => 'Creato',
  7 + 'Crop' => 'Tagliare a formato',
  8 + 'Crop and select' => 'Tagliare a formato e selezionare',
  9 + 'Delete' => 'Cancellare',
  10 + 'File hash' => 'File hash',
  11 + 'File name' => 'Nome del file',
  12 + 'Modified' => 'Modificato',
  13 + 'Search' => 'Ricerca',
  14 + 'Select' => 'Selezionare',
  15 + 'Image manager' => 'Image manager',
  16 + 'Upload' => 'Upload',
  17 + ];
... ...
artweb/artbox-core/components/imagemanager/messages/nl/imagemanager.php 0 → 100755
  1 +<?php
  2 + return [
  3 + 'Are you sure you want to delete this image?' => 'Weet je zeker dat je de afbeelding wilt verwijderen?',
  4 + 'Are you sure you want to detach the image?' => 'Weet je zeker dat je de afbeelding wilt losmaken?',
  5 + 'The requested image does not exist.' => 'De gevraagde afbeelding bestaat niet.',
  6 + 'Cancel' => 'Annuleer',
  7 + 'Created' => 'Aangemaakt',
  8 + 'Created by' => 'Gemaakt door',
  9 + 'Crop' => 'Bijsnijden',
  10 + 'Crop and select' => 'Bijsnijden en selecteren',
  11 + 'Delete' => 'Verwijderen',
  12 + 'File hash' => 'Bestand hash',
  13 + 'File name' => 'Bestandsnaam',
  14 + 'Modified' => 'Gewijzigd',
  15 + 'Modified by' => 'Gewijzigd door',
  16 + 'Search' => 'Zoeken',
  17 + 'Select' => 'Selecteer',
  18 + 'Image manager' => 'Image manager',
  19 + 'Upload' => 'Upload',
  20 + ];
0 21 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/messages/ru/imagemanager.php 0 → 100755
  1 +<?php
  2 + return [
  3 + 'Are you sure you want to delete this image?' => 'Вы действительно хотите удалить изображение?',
  4 + 'Are you sure you want to detach the image?' => 'Вы действительно хотите открепить изображение?',
  5 + 'Cancel' => 'Отменить',
  6 + 'Created' => 'Создано',
  7 + 'Crop' => 'Обрезать',
  8 + 'Crop and select' => 'Обрезать и выбрать',
  9 + 'Delete' => 'Удалить',
  10 + 'File hash' => 'Хеш файла',
  11 + 'File name' => 'Имя файла',
  12 + 'Modified' => 'Измененл',
  13 + 'Search' => 'Поиск',
  14 + 'Select' => 'Выбрать',
  15 + 'Image manager' => 'Менеджер изображений',
  16 + 'Upload' => 'Загрузить',
  17 + 'Save' => 'Сохранить',
  18 + ];
0 19 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/migrations/m160622_085710_create_ImageManager_table.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + /**
  6 + * Handles the creation for table `ImageManager`.
  7 + */
  8 + class m160622_085710_create_ImageManager_table extends Migration
  9 + {
  10 + /**
  11 + * @inheritdoc
  12 + */
  13 + public function up()
  14 + {
  15 + //ImageManager: create table
  16 + $this->createTable(
  17 + 'ImageManager',
  18 + [
  19 + 'id' => $this->primaryKey(),
  20 + 'fileName' => $this->string(128)
  21 + ->notNull(),
  22 + 'fileHash' => $this->string(32)
  23 + ->notNull(),
  24 + 'created' => $this->datetime()
  25 + ->notNull(),
  26 + 'modified' => $this->datetime(),
  27 + ]
  28 + );
  29 +
  30 + //ImageManager: alter id column
  31 + $this->alterColumn('ImageManager', 'id', 'INT(10) UNSIGNED NOT NULL AUTO_INCREMENT');
  32 +
  33 + }
  34 +
  35 + /**
  36 + * @inheritdoc
  37 + */
  38 + public function down()
  39 + {
  40 + $this->dropTable('ImageManager');
  41 + }
  42 + }
0 43 \ No newline at end of file
... ...
artweb/artbox-core/components/imagemanager/migrations/m170223_113221_addBlameableBehavior.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170223_113221_addBlameableBehavior extends Migration
  6 + {
  7 + public function up()
  8 + {
  9 + $this->addColumn(
  10 + 'ImageManager',
  11 + 'createdBy',
  12 + $this->integer(10)
  13 + ->unsigned()
  14 + ->null()
  15 + ->defaultValue(null)
  16 + );
  17 + $this->addColumn(
  18 + 'ImageManager',
  19 + 'modifiedBy',
  20 + $this->integer(10)
  21 + ->unsigned()
  22 + ->null()
  23 + ->defaultValue(null)
  24 + );
  25 + }
  26 +
  27 + public function down()
  28 + {
  29 + echo "m170223_113221_addBlameableBehavior cannot be reverted.\n";
  30 +
  31 + return false;
  32 + }
  33 + }
... ...
artweb/artbox-core/components/imagemanager/models/ImageManager.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components\imagemanager\models;
  4 +
  5 + use artbox\core\components\imagemanager\Module;
  6 + use Yii;
  7 + use yii\db\ActiveQuery;
  8 + use yii\db\ActiveRecord;
  9 + use yii\db\Expression;
  10 + use yii\behaviors\TimestampBehavior;
  11 + use yii\behaviors\BlameableBehavior;
  12 +
  13 + /**
  14 + * This is the model class for table "ImageManager".
  15 + *
  16 + * @property integer $id
  17 + * @property string $fileName
  18 + * @property string $fileHash
  19 + * @property string $created
  20 + * @property string $modified
  21 + * @property string $createdBy
  22 + * @property string $modifiedBy
  23 + */
  24 + class ImageManager extends ActiveRecord
  25 + {
  26 +
  27 + /**
  28 + * Set Created date to now
  29 + */
  30 + public function behaviors()
  31 + {
  32 + $aBehaviors = [];
  33 +
  34 + // Add the time stamp behavior
  35 + $aBehaviors[] = [
  36 + 'class' => TimestampBehavior::className(),
  37 + 'createdAtAttribute' => 'created',
  38 + 'updatedAtAttribute' => 'modified',
  39 + 'value' => new Expression('NOW()'),
  40 + ];
  41 +
  42 + // Check if we need blamable behavior
  43 + if (Yii::$app->getModule('imagemanager')->setBlameableBehavior) {
  44 + $aBehaviors[] = [
  45 + 'class' => BlameableBehavior::className(),
  46 + 'createdByAttribute' => 'createdBy',
  47 + 'updatedByAttribute' => 'modifiedBy',
  48 + ];
  49 + }
  50 +
  51 + return $aBehaviors;
  52 + }
  53 +
  54 + /**
  55 + * @inheritdoc
  56 + */
  57 + public static function tableName()
  58 + {
  59 + return 'ImageManager';
  60 + }
  61 +
  62 + /**
  63 + * @inheritdoc
  64 + */
  65 + public function rules()
  66 + {
  67 + return [
  68 + [
  69 + [
  70 + 'fileName',
  71 + 'fileHash',
  72 + ],
  73 + 'required',
  74 + ],
  75 + [
  76 + [
  77 + 'created',
  78 + 'modified',
  79 + ],
  80 + 'safe',
  81 + ],
  82 + [
  83 + [ 'fileName' ],
  84 + 'string',
  85 + 'max' => 128,
  86 + ],
  87 + [
  88 + [ 'fileHash' ],
  89 + 'string',
  90 + 'max' => 32,
  91 + ],
  92 + ];
  93 + }
  94 +
  95 + /**
  96 + * @inheritdoc
  97 + */
  98 + public function attributeLabels()
  99 + {
  100 + return [
  101 + 'id' => Yii::t('imagemanager', 'ID'),
  102 + 'fileName' => Yii::t('imagemanager', 'File Name'),
  103 + 'fileHash' => Yii::t('imagemanager', 'File Hash'),
  104 + 'created' => Yii::t('imagemanager', 'Created'),
  105 + 'modified' => Yii::t('imagemanager', 'Modified'),
  106 + 'createdBy' => Yii::t('imagemanager', 'Created by'),
  107 + 'modifiedBy' => Yii::t('imagemanager', 'Modified by'),
  108 + ];
  109 + }
  110 +
  111 + /**
  112 + * Get image path private
  113 + *
  114 + * @return string|null If image file exists the path to the image, if file does not exists null
  115 + */
  116 + public function getImagePathPrivate()
  117 + {
  118 + //set default return
  119 + $return = null;
  120 + //set media path
  121 + $sMediaPath = \Yii::$app->imagemanager->mediaPath;
  122 + $sFileExtension = pathinfo($this->fileName, PATHINFO_EXTENSION);
  123 + //get image file path
  124 + $sImageFilePath = $sMediaPath . '/' . $this->id . '_' . $this->fileHash . '.' . $sFileExtension;
  125 + //check file exists
  126 + if (file_exists($sImageFilePath)) {
  127 + $return = $sImageFilePath;
  128 + }
  129 + return $return;
  130 + }
  131 +
  132 + /**
  133 + * Get image data dimension/size
  134 + *
  135 + * @return array The image sizes
  136 + */
  137 + public function getImageDetails()
  138 + {
  139 + //set default return
  140 + $return = [
  141 + 'width' => 0,
  142 + 'height' => 0,
  143 + 'size' => 0,
  144 + ];
  145 + //set media path
  146 + $sMediaPath = \Yii::$app->imagemanager->mediaPath;
  147 + $sFileExtension = pathinfo($this->fileName, PATHINFO_EXTENSION);
  148 + //get image file path
  149 + $sImageFilePath = $sMediaPath . '/' . $this->id . '_' . $this->fileHash . '.' . $sFileExtension;
  150 + //check file exists
  151 + if (file_exists($sImageFilePath)) {
  152 + $aImageDimension = getimagesize($sImageFilePath);
  153 + $return[ 'width' ] = isset($aImageDimension[ 0 ]) ? $aImageDimension[ 0 ] : 0;
  154 + $return[ 'height' ] = isset($aImageDimension[ 1 ]) ? $aImageDimension[ 1 ] : 0;
  155 + $return[ 'size' ] = Yii::$app->formatter->asShortSize(filesize($sImageFilePath), 2);
  156 + }
  157 + return $return;
  158 + }
  159 +
  160 + /**
  161 + * @return ActiveQuery
  162 + */
  163 + public function getLanguages()
  164 + {
  165 + return ImageManagerLang::find()
  166 + ->where(
  167 + [
  168 + 'image_id' => $this->id,
  169 + ]
  170 + )
  171 + ->joinWith('language')
  172 + ->where(
  173 + [
  174 + 'language.status' => true,
  175 + ]
  176 + );
  177 + }
  178 + }
... ...
artweb/artbox-core/components/imagemanager/models/ImageManagerLang.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components\imagemanager\models;
  4 +
  5 + use artbox\core\models\Language;
  6 + use Yii;
  7 + use yii\db\ActiveRecord;
  8 +
  9 + /**
  10 + * This is the model class for table "ImageManagerLang".
  11 + *
  12 + * @property integer $image_id
  13 + * @property integer $language_id
  14 + * @property string $title
  15 + * @property string $alt
  16 + * @property string $description
  17 + * @property ImageManager $image
  18 + * @property Language $language
  19 + */
  20 + class ImageManagerLang extends ActiveRecord
  21 + {
  22 + /**
  23 + * @inheritdoc
  24 + */
  25 + public static function tableName()
  26 + {
  27 + return 'ImageManagerLang';
  28 + }
  29 +
  30 + /**
  31 + * @inheritdoc
  32 + */
  33 + public static function primaryKey()
  34 + {
  35 + return [
  36 + 'image_id',
  37 + 'language_id',
  38 + ];
  39 + }
  40 +
  41 + /**
  42 + * @inheritdoc
  43 + */
  44 + public function rules()
  45 + {
  46 + return [
  47 + [
  48 + [
  49 + 'image_id',
  50 + 'language_id',
  51 + ],
  52 + 'integer',
  53 + ],
  54 + [
  55 + [
  56 + 'title',
  57 + 'alt',
  58 + 'description',
  59 + ],
  60 + 'string',
  61 + 'max' => 255,
  62 + ],
  63 + [
  64 + [
  65 + 'language_id',
  66 + 'image_id',
  67 + ],
  68 + 'unique',
  69 + 'targetAttribute' => [
  70 + 'language_id',
  71 + 'image_id',
  72 + ],
  73 + 'message' => 'The combination of Image ID and Language ID has already been taken.',
  74 + ],
  75 + [
  76 + [ 'image_id' ],
  77 + 'exist',
  78 + 'skipOnError' => true,
  79 + 'targetClass' => ImageManager::className(),
  80 + 'targetAttribute' => [ 'image_id' => 'id' ],
  81 + ],
  82 + [
  83 + [ 'language_id' ],
  84 + 'exist',
  85 + 'skipOnError' => true,
  86 + 'targetClass' => Language::className(),
  87 + 'targetAttribute' => [ 'language_id' => 'id' ],
  88 + ],
  89 + ];
  90 + }
  91 +
  92 + /**
  93 + * @inheritdoc
  94 + */
  95 + public function attributeLabels()
  96 + {
  97 + return [
  98 + 'image_id' => Yii::t('app', 'Image ID'),
  99 + 'language_id' => Yii::t('app', 'Language ID'),
  100 + 'title' => Yii::t('app', 'Title'),
  101 + 'alt' => Yii::t('app', 'Alt'),
  102 + 'description' => Yii::t('app', 'Description'),
  103 + ];
  104 + }
  105 +
  106 + /**
  107 + * @return \yii\db\ActiveQuery
  108 + */
  109 + public function getImage()
  110 + {
  111 + return $this->hasOne(ImageManager::className(), [ 'id' => 'image_id' ]);
  112 + }
  113 +
  114 + /**
  115 + * @return \yii\db\ActiveQuery
  116 + */
  117 + public function getLanguage()
  118 + {
  119 + return $this->hasOne(Language::className(), [ 'id' => 'language_id' ]);
  120 + }
  121 + }
... ...
artweb/artbox-core/components/imagemanager/models/ImageManagerSearch.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components\imagemanager\models;
  4 +
  5 + use Yii;
  6 + use yii\base\Model;
  7 + use yii\data\ActiveDataProvider;
  8 + use artbox\core\components\imagemanager\models\ImageManager;
  9 + use artbox\core\components\imagemanager\Module;
  10 +
  11 + /**
  12 + * ImageManagerSearch represents the model behind the search form about
  13 + * `common\modules\imagemanager\models\ImageManager`.
  14 + */
  15 + class ImageManagerSearch extends ImageManager
  16 + {
  17 + public $globalSearch;
  18 +
  19 + /**
  20 + * @inheritdoc
  21 + */
  22 + public function rules()
  23 + {
  24 + return [
  25 + [
  26 + [ 'globalSearch' ],
  27 + 'safe',
  28 + ],
  29 + ];
  30 + }
  31 +
  32 + /**
  33 + * @inheritdoc
  34 + */
  35 + public function scenarios()
  36 + {
  37 + // bypass scenarios() implementation in the parent class
  38 + return Model::scenarios();
  39 + }
  40 +
  41 + /**
  42 + * Creates data provider instance with search query applied
  43 + *
  44 + * @param array $params
  45 + *
  46 + * @return ActiveDataProvider
  47 + */
  48 + public function search($params)
  49 + {
  50 + $query = ImageManager::find();
  51 +
  52 + // add conditions that should always apply here
  53 +
  54 + $dataProvider = new ActiveDataProvider(
  55 + [
  56 + 'query' => $query,
  57 + 'pagination' => [
  58 + 'pagesize' => 100,
  59 + ],
  60 + 'sort' => [ 'defaultOrder' => [ 'created' => SORT_DESC ] ],
  61 + ]
  62 + );
  63 +
  64 + $this->load($params);
  65 +
  66 + if (!$this->validate()) {
  67 + // uncomment the following line if you do not want to return any records when validation fails
  68 + // $query->where('0=1');
  69 + return $dataProvider;
  70 + }
  71 +
  72 + // Get the module instance
  73 + $module = Module::getInstance();
  74 +
  75 + if ($module->setBlameableBehavior) {
  76 + $query->andWhere([ 'createdBy' => Yii::$app->user->id ]);
  77 + }
  78 +
  79 + $query->orFilterWhere(
  80 + [
  81 + 'like',
  82 + 'fileName',
  83 + $this->globalSearch,
  84 + ]
  85 + // )
  86 + // ->orFilterWhere(
  87 + // [
  88 + // 'like',
  89 + // 'created',
  90 + // $this->globalSearch,
  91 + // ]
  92 + // )
  93 + // ->orFilterWhere(
  94 + // [
  95 + // 'like',
  96 + // 'modified',
  97 + // $this->globalSearch,
  98 + // ]
  99 + );
  100 +
  101 + return $dataProvider;
  102 + }
  103 + }
... ...
artweb/artbox-core/components/imagemanager/views/default/index.php 0 → 100755
  1 +<?php
  2 + $this->title = "Image manager";
  3 +?>
  4 +<div class="imagemanager-default-index">
  5 + <p>Welcome to image manager</p>
  6 + <p>Install run migrate:</p>
  7 + <p><code>yii migrate --migrationPath=@noam148/imagemanager/migrations</code></p>
  8 +
  9 + <p><em>By noam148</em></p>
  10 +</div>
... ...
artweb/artbox-core/components/imagemanager/views/layouts/blank.php 0 → 100755
  1 +<?php
  2 +
  3 + /* @var $this \yii\web\View */
  4 + /* @var $content string */
  5 +
  6 + use yii\helpers\Html;
  7 +
  8 +?>
  9 +<?php $this->beginPage() ?>
  10 +<!DOCTYPE html>
  11 +<html lang="<?= Yii::$app->language ?>">
  12 + <head>
  13 + <meta charset="<?= Yii::$app->charset ?>">
  14 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
  15 + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
  16 + <?= Html::csrfMetaTags() ?>
  17 + <title><?= Html::encode($this->title) ?></title>
  18 + <?php $this->head() ?>
  19 + </head>
  20 + <body>
  21 + <?php $this->beginBody() ?>
  22 +
  23 + <?= $content; ?>
  24 +
  25 + <?php $this->endBody() ?>
  26 + </body>
  27 +</html>
  28 +<?php $this->endPage() ?>
... ...
artweb/artbox-core/components/imagemanager/views/manager/_image_info.php 0 → 100755
  1 +<?php
  2 +
  3 + /**
  4 + * @var View $this
  5 + * @var ImageManager $model
  6 + * @var ImageManagerLang $languages
  7 + */
  8 +
  9 + use artbox\core\components\imagemanager\models\ImageManager;
  10 + use artbox\core\components\imagemanager\models\ImageManagerLang;
  11 + use artbox\core\models\Language;
  12 + use yii\helpers\Html;
  13 + use yii\web\View;
  14 +
  15 +?>
  16 +
  17 +
  18 +<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
  19 +
  20 +
  21 + <?php
  22 +
  23 + foreach (Language::getActive() as $id => $language) { ?>
  24 +
  25 +
  26 + <div class="panel panel-default">
  27 + <div class="panel-heading" role="tab" id="heading<?= $id ?>">
  28 + <h4 class="panel-title">
  29 + <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse<?= $id ?>" aria-expanded="true" aria-controls="collapseOne">
  30 + <?= $language->name ?>
  31 + </a>
  32 + </h4>
  33 + </div>
  34 + <div id="collapse<?= $id ?>" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading<?= $id ?>">
  35 + <div class="panel-body">
  36 +
  37 + <?php
  38 + if (empty($languages[ $id ])) { ?>
  39 +
  40 + <div class="form-group">
  41 + <label for="title<?= $id ?>">Title</label>
  42 + <input name="image_info[<?= $language->id ?>][title]" type="text" class="form-control" id="title<?= $id ?>">
  43 + </div>
  44 +
  45 + <div class="form-group">
  46 + <label for="alt<?= $id ?>">Alt</label>
  47 + <input name="image_info[<?= $language->id ?>][alt]" type="text" class="form-control" id="alt<?= $id ?>">
  48 + </div>
  49 +
  50 + <div class="form-group">
  51 + <label for="description<?= $id ?>">Description</label>
  52 + <textarea class="form-control" name="image_info[<?= $language->id ?>][description]" id="description<?= $id ?>" cols="30" rows="10"></textarea>
  53 + </div>
  54 +
  55 + <?php } else { ?>
  56 +
  57 + <div class="form-group">
  58 + <label for="title<?= $id ?>">Title</label>
  59 + <input value="<?= $languages[ $id ]->title ?>" name="image_info[<?= $language->id ?>][title]" type="text" class="form-control" id="title<?= $id ?>">
  60 + </div>
  61 +
  62 + <div class="form-group">
  63 + <label for="alt<?= $id ?>">Alt</label>
  64 + <input value="<?= $languages[ $id ]->alt ?>" name="image_info[<?= $language->id ?>][alt]" type="text" class="form-control" id="alt<?= $id ?>">
  65 + </div>
  66 +
  67 + <div class="form-group">
  68 + <label for="description<?= $id ?>">Description</label>
  69 + <textarea class="form-control" name="image_info[<?= $language->id ?>][description]" id="description<?= $id ?>" cols="30" rows="10"><?= $languages[ $id ]->description ?></textarea>
  70 + </div>
  71 +
  72 + <?php } ?>
  73 + </div>
  74 + </div>
  75 + </div>
  76 +
  77 + <?php
  78 + }
  79 + echo Html::hiddenInput(
  80 + 'image_id',
  81 + $model->id
  82 + );
  83 +
  84 + ?>
  85 +
  86 +</div>
  87 +
  88 +
  89 +
... ...
artweb/artbox-core/components/imagemanager/views/manager/_item.php 0 → 100755
  1 +<div class="thumbnail">
  2 + <img src="<?= \Yii::$app->imagemanager->getImagePath($model->id, 300, 300) ?>" alt="<?= $model->fileName ?>">
  3 + <div class="filename"><?= $model->fileName ?></div>
  4 +</div>
... ...
artweb/artbox-core/components/imagemanager/views/manager/index.php 0 → 100755
  1 +<?php
  2 +
  3 + /**
  4 + * @var View $this
  5 + */
  6 +
  7 + use yii\helpers\Url;
  8 + use yii\helpers\Html;
  9 + use yii\web\View;
  10 + use yii\widgets\ListView;
  11 + use yii\widgets\Pjax;
  12 + use kartik\file\FileInput;
  13 + use yiister\gentelella\widgets\Panel;
  14 +
  15 + $this->title = Yii::t('imagemanager', 'Image manager');
  16 +
  17 +?>
  18 +
  19 +<?php $panel = Panel::begin(
  20 + [
  21 + 'header' => $this->title,
  22 + ]
  23 +) ?>
  24 +
  25 +<div id="module-imagemanager" class="container-fluid <?= $selectType ?>">
  26 + <div class="row">
  27 + <div class="col-xs-6 col-sm-10 col-image-editor">
  28 + <div class="image-cropper">
  29 + <div class="image-wrapper">
  30 + <img id="image-cropper"/>
  31 + </div>
  32 + <div class="action-buttons">
  33 + <a href="#" class="btn btn-primary apply-crop">
  34 + <i class="fa fa-crop"></i>
  35 + <span class="hidden-xs"><?= Yii::t('imagemanager', 'Crop') ?></span>
  36 + </a>
  37 + <?php if ($viewMode === "iframe"): ?>
  38 + <a href="#" class="btn btn-primary apply-crop-select">
  39 + <i class="fa fa-crop"></i>
  40 + <span class="hidden-xs"><?= Yii::t('imagemanager', 'Crop and select') ?></span>
  41 + </a>
  42 + <?php endif; ?>
  43 + <a href="#" class="btn btn-default cancel-crop">
  44 + <i class="fa fa-undo"></i>
  45 + <span class="hidden-xs"><?= Yii::t('imagemanager', 'Cancel') ?></span>
  46 + </a>
  47 + </div>
  48 + </div>
  49 + </div>
  50 + <div class="col-xs-6 col-sm-8 col-overview">
  51 + <?php Pjax::begin(
  52 + [
  53 + 'id' => 'pjax-mediamanager',
  54 + 'timeout' => '5000',
  55 + ]
  56 + ); ?>
  57 + <?= ListView::widget(
  58 + [
  59 + 'dataProvider' => $dataProvider,
  60 + 'itemOptions' => [ 'class' => 'item img-thumbnail' ],
  61 + 'layout' => "<div class='item-overview'>{items}</div> {pager}",
  62 + 'itemView' => function ($model, $key, $index, $widget) {
  63 + return $this->render("_item", [ 'model' => $model ]);
  64 + },
  65 + ]
  66 + ) ?>
  67 + <?php Pjax::end(); ?>
  68 + </div>
  69 + <div class="col-xs-6 col-sm-4 col-options">
  70 + <div class="form-group">
  71 + <?= Html::textInput(
  72 + 'input-mediamanager-search',
  73 + null,
  74 + [
  75 + 'id' => 'input-mediamanager-search',
  76 + 'class' => 'form-control',
  77 + 'placeholder' => Yii::t('imagemanager', 'Search') . '...',
  78 + ]
  79 + ) ?>
  80 + </div>
  81 +
  82 + <?php
  83 + if (Yii::$app->controller->module->canUploadImage):
  84 + ?>
  85 +
  86 + <?= FileInput::widget(
  87 + [
  88 + 'name' => 'imagemanagerFiles[]',
  89 + 'id' => 'imagemanager-files',
  90 + 'options' => [
  91 + 'multiple' => true,
  92 + 'accept' => 'image/*',
  93 + ],
  94 + 'pluginOptions' => [
  95 + 'uploadUrl' => Url::to([ 'manager/upload' ]),
  96 + 'allowedFileExtensions' => \Yii::$app->controller->module->allowedFileExtensions,
  97 + 'uploadAsync' => false,
  98 + 'showPreview' => false,
  99 + 'showRemove' => false,
  100 + 'showUpload' => false,
  101 + 'showCancel' => false,
  102 + 'browseClass' => 'btn btn-primary btn-block',
  103 + 'browseIcon' => '<i class="fa fa-upload"></i> ',
  104 + 'browseLabel' => Yii::t('imagemanager', 'Upload'),
  105 + ],
  106 + 'pluginEvents' => [
  107 + "filebatchselected" => "function(event, files){ $('.msg-invalid-file-extension').addClass('hide'); $(this).fileinput('upload'); }",
  108 + "filebatchuploadsuccess" => "function(event, data, previewId, index) {
  109 + imageManagerModule.uploadSuccess(data.jqXHR.responseJSON.imagemanagerFiles);
  110 + }",
  111 + "fileuploaderror" => "function(event, data) { $('.msg-invalid-file-extension').removeClass('hide'); }",
  112 + ],
  113 + ]
  114 + ) ?>
  115 +
  116 + <?php
  117 + endif;
  118 + ?>
  119 +
  120 + <div class="image-info hide">
  121 + <div class="thumbnail">
  122 + <img src="#">
  123 + </div>
  124 + <div class="edit-buttons">
  125 + <a href="#" class="btn btn-primary btn-block crop-image-item">
  126 + <i class="fa fa-crop"></i>
  127 + <span class="hidden-xs"><?= Yii::t('imagemanager', 'Crop') ?></span>
  128 + </a>
  129 + </div>
  130 + <div class="details">
  131 + <div class="fileName"></div>
  132 + <div class="created"></div>
  133 + <div class="fileSize"></div>
  134 + <div class="dimensions"><span class="dimension-width"></span> &times; <span class="dimension-height"></span>
  135 + </div>
  136 + <?php
  137 + if (Yii::$app->controller->module->canRemoveImage):
  138 + ?>
  139 + <a href="#" class="btn btn-xs btn-danger delete-image-item"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span> <?= Yii::t(
  140 + 'imagemanager',
  141 + 'Delete'
  142 + ) ?></a>
  143 + <?php
  144 + endif;
  145 + ?>
  146 +
  147 + <form id="save-image-info-form">
  148 + <div class="seo-info">
  149 +
  150 + </div>
  151 + <?= Html::button(
  152 + '<i class="glyphicon glyphicon-floppy-disk"></i> ' . \Yii::t('imagemanager', 'Save'),
  153 + [
  154 + 'class' => 'btn btn-success btn-xs',
  155 + 'id' => 'save-image-info',
  156 + ]
  157 + ) ?>
  158 + </form>
  159 + </div>
  160 +
  161 +
  162 + <?php if ($viewMode === "iframe"): ?>
  163 + <a href="#" class="btn btn-primary btn-block pick-image-item"><?= Yii::t('imagemanager', 'Select') ?></a>
  164 + <?php endif; ?>
  165 + </div>
  166 + </div>
  167 + </div>
  168 +</div>
  169 +<?php $panel::end() ?>
0 170 \ No newline at end of file
... ...
artweb/artbox-core/components/imageresize/ImageResize.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\components\imageresize;
  4 +
  5 + use Yii;
  6 + use yii\helpers\Url;
  7 + use yii\helpers\FileHelper;
  8 + use yii\imagine\Image;
  9 + use yii\base\Exception;
  10 + use Imagine\Image\Box;
  11 + use Imagine\Image\ManipulatorInterface;
  12 +
  13 + class ImageResize
  14 + {
  15 +
  16 + const IMAGE_OUTBOUND = ManipulatorInterface::THUMBNAIL_OUTBOUND;
  17 + const IMAGE_INSET = ManipulatorInterface::THUMBNAIL_INSET;
  18 +
  19 + /** @var string $cachePath path alias relative with webroot where the cache files are kept */
  20 + public $cachePath = 'assets/images';
  21 +
  22 + /** @var int $cacheExpire */
  23 + public $cacheExpire = 0;
  24 +
  25 + /** @var int $imageQuality */
  26 + public $imageQuality = 50;
  27 +
  28 + /** @var int $useFilename if true show filename in url */
  29 + public $useFilename = true;
  30 +
  31 + /** @var int $absoluteUrl if true include domain in url */
  32 + public $absoluteUrl = false;
  33 +
  34 + /**
  35 + * Creates and caches the image thumbnail and returns full path from thumbnail file.
  36 + *
  37 + * @param string $filePath to original file
  38 + * @param integer $width
  39 + * @param integer $height
  40 + * @param string $mode
  41 + * @param integer $quality (1 - 100 quality)
  42 + * @param string $chosenFileName (custome filename)
  43 + *
  44 + * @return string
  45 + * @throws Exception
  46 + */
  47 + public function generateImage(
  48 + $filePath,
  49 + $width,
  50 + $height,
  51 + $mode = "outbound",
  52 + $quality = null,
  53 + $chosenFileName = null
  54 + ) {
  55 + $filePath = FileHelper::normalizePath(Yii::getAlias($filePath));
  56 + if (!is_file($filePath)) {
  57 + throw new Exception("File $filePath doesn't exist");
  58 + }
  59 +
  60 + //set resize mode
  61 + $resizeMode = null;
  62 + switch ($mode) {
  63 + case "outbound":
  64 + $resizeMode = ImageResize::IMAGE_OUTBOUND;
  65 + break;
  66 + case "inset":
  67 + $resizeMode = ImageResize::IMAGE_INSET;
  68 + break;
  69 + default:
  70 + throw new Exception('generateImage $mode is not valid choose for "outbound" or "inset"');
  71 + }
  72 +
  73 + //create some vars
  74 + $cachePath = Yii::getAlias('@webroot/' . $this->cachePath);
  75 + //get fileinfo
  76 + $aFileInfo = pathinfo($filePath);
  77 + //set default filename
  78 + $sFileHash = md5($filePath . $width . $height . $resizeMode . filemtime($filePath));
  79 + $imageFileName = null;
  80 + //if $this->useFilename set to true? use seo friendly name
  81 + if ($this->useFilename === true) {
  82 + //set hash and default name
  83 + $sFileHashShort = substr($sFileHash, 0, 6);
  84 + $sFileName = $aFileInfo[ 'filename' ];
  85 + //set choosen filename if $chosenFileName not null.
  86 + if ($chosenFileName !== null) {
  87 + $sFileName = preg_replace('/(\.\w+)$/', '', $chosenFileName);
  88 + }
  89 + //replace for seo friendly file name
  90 + $sFilenameReplace = preg_replace("/[^\w\.\-]+/", '-', $sFileName);
  91 + //set filename
  92 + $imageFileName = $sFileHashShort . "_" . $sFilenameReplace;
  93 + //else use file hash as filename
  94 + } else {
  95 + $imageFileName = $sFileHash;
  96 + }
  97 +
  98 + $imageFileExt = "." . $aFileInfo[ 'extension' ];
  99 + $imageFilePath = $cachePath . DIRECTORY_SEPARATOR . substr($imageFileName, 0, 2);
  100 + $imageFile = $imageFilePath . DIRECTORY_SEPARATOR . $imageFileName . $imageFileExt;
  101 +
  102 + if (file_exists($imageFile)) {
  103 + if ($this->cacheExpire !== 0 && ( time() - filemtime($imageFile) ) > $this->cacheExpire) {
  104 + unlink($imageFile);
  105 + } else {
  106 + return $imageFile;
  107 + }
  108 + }
  109 + //if dir not exist create cache edir
  110 + if (!is_dir($imageFilePath)) {
  111 + FileHelper::createDirectory($imageFilePath, 0755);
  112 + }
  113 + //create image
  114 + $box = new Box($width, $height);
  115 + $image = Image::getImagine()
  116 + ->open($filePath);
  117 + $image = $image->thumbnail($box, $resizeMode);
  118 +
  119 + $options = [
  120 + 'quality' => 100,
  121 + ];
  122 + $image->save($imageFile, $options);
  123 + return $imageFile;
  124 + }
  125 +
  126 + /**
  127 + * Creates and caches the image and returns URL from resized file.
  128 + *
  129 + * @param string $filePath to original file
  130 + * @param integer $width
  131 + * @param integer $height
  132 + * @param string $mode
  133 + * @param integer $quality (1 - 100 quality)
  134 + * @param string $fileName (custome filename)
  135 + *
  136 + * @return string
  137 + */
  138 + public function getUrl($filePath, $width, $height, $mode = "outbound", $quality = null, $fileName = null)
  139 + {
  140 + //get original file
  141 + $normalizePath = FileHelper::normalizePath(Yii::getAlias($filePath));
  142 + //get cache url
  143 + $cacheUrl = Yii::getAlias($this->cachePath);
  144 + //generate file
  145 + $resizedFilePath = self::generateImage($normalizePath, $width, $height, $mode, $quality, $fileName);
  146 + //get resized file
  147 + $normalizeResizedFilePath = FileHelper::normalizePath($resizedFilePath);
  148 + $resizedFileName = pathinfo($normalizeResizedFilePath, PATHINFO_BASENAME);
  149 + //get url
  150 + $sFileUrl = Url::to(
  151 + '@web/' . $cacheUrl . '/' . substr($resizedFileName, 0, 2) . '/' . $resizedFileName,
  152 + $this->absoluteUrl
  153 + );
  154 + //return path
  155 + return $sFileUrl;
  156 + }
  157 +
  158 + /**
  159 + * Clear cache directory.
  160 + *
  161 + * @return bool
  162 + */
  163 + public function clearCache()
  164 + {
  165 + $cachePath = Yii::getAlias('@webroot/' . $this->cachePath);
  166 + //remove dir
  167 + FileHelper::removeDirectory($cachePath);
  168 + //creat dir
  169 + return FileHelper::createDirectory($cachePath, 0755);
  170 + }
  171 +
  172 + }
... ...
artweb/artbox-core/composer.json 0 → 100755
  1 +{
  2 + "name": "artweb/artbox-core",
  3 + "description": "Artbox core extension",
  4 + "license": "BSD-3-Clause",
  5 + "minimum-stability": "dev",
  6 + "type": "yii2-extension",
  7 + "require": {
  8 + "php": ">=7.0",
  9 + "yiisoft/yii2": "~2.0",
  10 + "yiisoft/yii2-imagine": "~2.0",
  11 + "yiisoft/yii2-bootstrap": "~2.0",
  12 + "yiisoft/yii2-swiftmailer": "~2.0",
  13 + "yiister/yii2-gentelella": "~1.0",
  14 + "2amigos/yii2-tinymce-widget": "~1.0",
  15 + "bower-asset/amcharts": "*",
  16 + "kartik-v/yii2-widget-fileinput": "*"
  17 + },
  18 + "autoload": {
  19 + "psr-4": {
  20 + "artbox\\core\\": ""
  21 + }
  22 + }
  23 +}
0 24 \ No newline at end of file
... ...
artweb/artbox-core/controllers/AliasController.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\controllers;
  4 +
  5 + use artbox\catalog\models\Filter;
  6 + use artbox\core\helpers\SlugHelper;
  7 + use artbox\core\models\Language;
  8 + use Yii;
  9 + use artbox\core\models\Alias;
  10 + use artbox\core\models\AliasSearch;
  11 + use yii\filters\AccessControl;
  12 + use yii\helpers\Json;
  13 + use yii\web\Controller;
  14 + use yii\web\NotFoundHttpException;
  15 + use yii\filters\VerbFilter;
  16 +
  17 + /**
  18 + * AliasController implements the CRUD actions for Alias model.
  19 + */
  20 + class AliasController extends Controller
  21 + {
  22 + /**
  23 + * @return bool|string
  24 + */
  25 + public function getViewPath()
  26 + {
  27 + return \Yii::getAlias('@artbox/core/views/alias');
  28 + }
  29 + /**
  30 + * @inheritdoc
  31 + */
  32 + public function behaviors()
  33 + {
  34 + return [
  35 + 'access' => [
  36 + 'class' => AccessControl::className(),
  37 + 'rules' => [
  38 + [
  39 + 'actions' => [
  40 + 'login',
  41 + 'error',
  42 + ],
  43 + 'allow' => true,
  44 + ],
  45 + [
  46 + 'allow' => true,
  47 + 'roles' => [ '@' ],
  48 + ],
  49 + ],
  50 + ],
  51 + 'verbs' => [
  52 + 'class' => VerbFilter::className(),
  53 + 'actions' => [// 'change-password' => [ 'post' ],
  54 + ],
  55 + ],
  56 + ];
  57 + }
  58 +
  59 + /**
  60 + * Lists all Alias models.
  61 + *
  62 + * @return mixed
  63 + */
  64 + public function actionIndex()
  65 + {
  66 + $languages = Language::find()
  67 + ->select(
  68 + [
  69 + 'name',
  70 + 'id',
  71 + ]
  72 + )
  73 + ->where([ 'status' => 1 ])
  74 + ->asArray()
  75 + ->indexBy('id')
  76 + ->column();
  77 + $entities = Alias::find()
  78 + ->select('entity')
  79 + ->where(
  80 + [
  81 + 'not',
  82 + [ 'entity' => null ],
  83 + ]
  84 + )
  85 + ->distinct()
  86 + ->indexBy('entity')
  87 + ->column();
  88 + $searchModel = new AliasSearch();
  89 + $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
  90 +
  91 + return $this->render(
  92 + 'index',
  93 + [
  94 + 'searchModel' => $searchModel,
  95 + 'dataProvider' => $dataProvider,
  96 + 'languages' => $languages,
  97 + 'entities' => $entities,
  98 + ]
  99 + );
  100 + }
  101 +
  102 + /**
  103 + * Displays a single Alias model.
  104 + *
  105 + * @param integer $id
  106 + *
  107 + * @return mixed
  108 + */
  109 + public function actionView($id)
  110 + {
  111 + return $this->render(
  112 + 'view',
  113 + [
  114 + 'model' => $this->findModel($id),
  115 + ]
  116 + );
  117 + }
  118 +
  119 + /**
  120 + * Creates a new Alias model.
  121 + * If creation is successful, the browser will be redirected to the 'view' alias.
  122 + *
  123 + * @param string $url
  124 + *
  125 +*@return mixed
  126 + */
  127 + public function actionCreate(string $url = null)
  128 + {
  129 + $languages = Language::find()
  130 + ->select(
  131 + [
  132 + 'name',
  133 + 'id',
  134 + ]
  135 + )
  136 + ->where([ 'status' => 1 ])
  137 + ->asArray()
  138 + ->indexBy('id')
  139 + ->column();
  140 + $model = new Alias(
  141 + [
  142 + 'scenario' => Alias::SCENARIO_CREATE,
  143 + ]
  144 + );
  145 + if ($model->load(Yii::$app->request->post())) {
  146 + if ($model->save()) {
  147 + return $this->redirect(
  148 + [
  149 + 'view',
  150 + 'id' => $model->id,
  151 + ]
  152 + );
  153 + }
  154 + }
  155 +
  156 + if (!empty($url)) {
  157 + $urlArray = explode('/', trim($url, '/'));
  158 +
  159 + $route = Json::encode(
  160 + [
  161 + 'category/view',
  162 + 'filter' => $urlArray[ 2 ],
  163 + 'category' => $urlArray[ 1 ],
  164 + ]
  165 + );
  166 +
  167 + $model->route = $route;
  168 + $model->entity = Filter::className();
  169 + $model->fields = $url;
  170 + }
  171 +
  172 + return $this->render(
  173 + 'create',
  174 + [
  175 + 'model' => $model,
  176 + 'languages' => $languages,
  177 + ]
  178 + );
  179 + }
  180 +
  181 + /**
  182 + * Updates an existing Alias model.
  183 + * If update is successful, the browser will be redirected to the 'view' alias.
  184 + *
  185 + * @param integer $id
  186 + *
  187 + * @return mixed
  188 + */
  189 + public function actionUpdate($id)
  190 + {
  191 + $model = $this->findModel($id);
  192 + $model->scenario = Alias::SCENARIO_UPDATE;
  193 +
  194 + if ($model->load(Yii::$app->request->post())) {
  195 + if ($model->save()) {
  196 + return $this->redirect(
  197 + [
  198 + 'view',
  199 + 'id' => $model->id,
  200 + ]
  201 + );
  202 + }
  203 + }
  204 +
  205 + return $this->render(
  206 + 'update',
  207 + [
  208 + 'model' => $model,
  209 + ]
  210 + );
  211 + }
  212 +
  213 + /**
  214 + * Deletes an existing Alias model.
  215 + * If deletion is successful, the browser will be redirected to the 'index' alias.
  216 + *
  217 + * @param integer $id
  218 + *
  219 + * @return mixed
  220 + */
  221 + public function actionDelete($id)
  222 + {
  223 + $this->findModel($id)
  224 + ->delete();
  225 +
  226 + return $this->redirect([ 'index' ]);
  227 + }
  228 +
  229 + /**
  230 + * Get unique slug from $text
  231 + *
  232 + * @param $text
  233 + * @param int|null $languageId
  234 + *
  235 + * @return string
  236 + */
  237 + public function actionSlugify($text, int $languageId = null)
  238 + {
  239 + $response = \Yii::$app->response;
  240 + $response->format = $response::FORMAT_JSON;
  241 + $slug = SlugHelper::slugify($text);
  242 + return SlugHelper::unify($slug, null, $languageId);
  243 + }
  244 +
  245 + /**
  246 + * Finds the Alias model based on its primary key value.
  247 + * If the model is not found, a 404 HTTP exception will be thrown.
  248 + *
  249 + * @param integer $id
  250 + *
  251 + * @return Alias the loaded model
  252 + * @throws NotFoundHttpException if the model cannot be found
  253 + */
  254 + protected function findModel($id)
  255 + {
  256 + if (( $model = Alias::findOne($id) ) !== null) {
  257 + return $model;
  258 + } else {
  259 + throw new NotFoundHttpException('The requested alias does not exist.');
  260 + }
  261 + }
  262 + }
... ...
artweb/artbox-core/controllers/FeedbackController.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\controllers;
  4 +
  5 + use artbox\core\widgets\FeedbackWidget;
  6 + use Yii;
  7 + use artbox\core\models\Feedback;
  8 + use yii\data\ActiveDataProvider;
  9 + use yii\filters\AccessControl;
  10 + use yii\helpers\Html;
  11 + use yii\web\Controller;
  12 + use yii\web\NotFoundHttpException;
  13 + use yii\filters\VerbFilter;
  14 + use yii\web\Response;
  15 +
  16 + /**
  17 + * FeedbackController implements the CRUD actions for Feedback model.
  18 + */
  19 + class FeedbackController extends Controller
  20 + {
  21 + /**
  22 + * @return bool|string
  23 + */
  24 + public function getViewPath()
  25 + {
  26 + return \Yii::getAlias('@artbox/core/views/feedback');
  27 + }
  28 + /**
  29 + * @inheritdoc
  30 + */
  31 + public function behaviors()
  32 + {
  33 + return [
  34 + 'access' => [
  35 + 'class' => AccessControl::className(),
  36 + 'rules' => [
  37 + [
  38 + 'actions' => [
  39 + 'login',
  40 + 'error',
  41 + ],
  42 + 'allow' => true,
  43 + ],
  44 + [
  45 + 'allow' => true,
  46 + 'roles' => [ '@' ],
  47 + ],
  48 + ],
  49 + ],
  50 + 'verbs' => [
  51 + 'class' => VerbFilter::className(),
  52 + 'actions' => [// 'change-password' => [ 'post' ],
  53 + ],
  54 + ],
  55 + ];
  56 + }
  57 +
  58 + /**
  59 + * Lists all Feedback models.
  60 + *
  61 + * @return mixed
  62 + */
  63 + public function actionIndex()
  64 + {
  65 + $dataProvider = new ActiveDataProvider(
  66 + [
  67 + 'query' => Feedback::find()->orderBy('created_at DESC'),
  68 + ]
  69 + );
  70 +
  71 + return $this->render(
  72 + 'index',
  73 + [
  74 + 'dataProvider' => $dataProvider,
  75 + ]
  76 + );
  77 + }
  78 +
  79 + /**
  80 + * Displays a single Feedback model.
  81 + *
  82 + * @param integer $id
  83 + *
  84 + * @return mixed
  85 + */
  86 + public function actionView($id)
  87 + {
  88 + $model = $this->findModel($id);
  89 +
  90 + $model->status = true;
  91 + $model->save(false, [ 'status' ]);
  92 +
  93 + return $this->render(
  94 + 'view',
  95 + [
  96 + 'model' => $model,
  97 + ]
  98 + );
  99 + }
  100 +
  101 + /**
  102 + * Creates a new Feedback model.
  103 + * If creation is successful, the browser will be redirected to the 'view' page.
  104 + *
  105 + * @return mixed
  106 + */
  107 + public function actionCreate()
  108 + {
  109 + $model = new Feedback();
  110 +
  111 + if ($model->load(Yii::$app->request->post()) && $model->save()) {
  112 + return $this->redirect(
  113 + [
  114 + 'view',
  115 + 'id' => $model->id,
  116 + ]
  117 + );
  118 + } else {
  119 + return $this->render(
  120 + 'create',
  121 + [
  122 + 'model' => $model,
  123 + ]
  124 + );
  125 + }
  126 + }
  127 +
  128 + /**
  129 + * Updates an existing Feedback model.
  130 + * If update is successful, the browser will be redirected to the 'view' page.
  131 + *
  132 + * @param integer $id
  133 + *
  134 + * @return mixed
  135 + */
  136 + public function actionUpdate($id)
  137 + {
  138 + $model = $this->findModel($id);
  139 +
  140 + $model->status = true;
  141 + $model->save(false, [ 'status' ]);
  142 +
  143 + if ($model->load(Yii::$app->request->post()) && $model->save()) {
  144 + return $this->redirect('index');
  145 + } else {
  146 + return $this->render(
  147 + 'update',
  148 + [
  149 + 'model' => $model,
  150 + ]
  151 + );
  152 + }
  153 + }
  154 +
  155 + /**
  156 + * Deletes an existing Feedback model.
  157 + * If deletion is successful, the browser will be redirected to the 'index' page.
  158 + *
  159 + * @param integer $id
  160 + *
  161 + * @return mixed
  162 + */
  163 + public function actionDelete($id)
  164 + {
  165 + $this->findModel($id)
  166 + ->delete();
  167 +
  168 + return $this->redirect([ 'index' ]);
  169 + }
  170 +
  171 + public function actionViewed($id)
  172 + {
  173 + if (Yii::$app->request->isPost) {
  174 + $model = $this->findModel($id);
  175 +
  176 + Yii::$app->response->format = Response::FORMAT_JSON;
  177 +
  178 + $model->status = true;
  179 + if ($model->save(false, [ 'status' ])) {
  180 +
  181 + $widget = FeedbackWidget::widget();
  182 +
  183 + return [
  184 + 'text' => Html::tag(
  185 + 'span',
  186 + '',
  187 + [
  188 + 'class' => 'glyphicon glyphicon-ok',
  189 + ]
  190 + ),
  191 + 'message' => [
  192 + 'title' => Yii::t('core', 'Notification') . ':',
  193 + 'text' => Yii::t('core', 'Status changed'),
  194 + ],
  195 + 'widget' => $widget,
  196 + ];
  197 + }
  198 + }
  199 + return [];
  200 + }
  201 +
  202 + /**
  203 + * Finds the Feedback model based on its primary key value.
  204 + * If the model is not found, a 404 HTTP exception will be thrown.
  205 + *
  206 + * @param integer $id
  207 + *
  208 + * @return Feedback the loaded model
  209 + * @throws NotFoundHttpException if the model cannot be found
  210 + */
  211 + protected function findModel($id)
  212 + {
  213 + if (( $model = Feedback::findOne($id) ) !== null) {
  214 + return $model;
  215 + } else {
  216 + throw new NotFoundHttpException('The requested page does not exist.');
  217 + }
  218 + }
  219 + }
... ...
artweb/artbox-core/controllers/PageCategoryController.php 0 → 100644
  1 +<?php
  2 +
  3 + namespace artbox\core\controllers;
  4 +
  5 + use Yii;
  6 + use artbox\core\models\PageCategory;
  7 + use artbox\core\models\PageCategorySearch;
  8 + use yii\web\Controller;
  9 + use yii\web\NotFoundHttpException;
  10 + use yii\filters\VerbFilter;
  11 + use yii\web\Response;
  12 + use yii\filters\AccessControl;
  13 +
  14 + /**
  15 + * PageCategoryController implements the CRUD actions for PageCategory model.
  16 + */
  17 + class PageCategoryController extends Controller
  18 + {
  19 + /**
  20 + * @inheritdoc
  21 + */
  22 + public function behaviors()
  23 + {
  24 + return [
  25 + 'verbs' => [
  26 + 'class' => VerbFilter::className(),
  27 + 'actions' => [
  28 + 'delete' => [ 'POST' ],
  29 + ],
  30 + ],
  31 + 'access' => [
  32 + 'class' => AccessControl::className(),
  33 + 'rules' => [
  34 + [
  35 + 'actions' => [
  36 + 'login',
  37 + 'error',
  38 + ],
  39 + 'allow' => true,
  40 + ],
  41 + [
  42 + 'allow' => true,
  43 + 'roles' => [ '@' ],
  44 + ],
  45 + ],
  46 + ],
  47 + ];
  48 + }
  49 +
  50 + /**
  51 + * @inheritdoc
  52 + */
  53 + public function getViewPath()
  54 + {
  55 + return '@artbox/core/views/page-category';
  56 + }
  57 +
  58 + /**
  59 + * Lists all PageCategory models.
  60 + *
  61 + * @return mixed
  62 + */
  63 + public function actionIndex()
  64 + {
  65 + $searchModel = new PageCategorySearch();
  66 + $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
  67 +
  68 + return $this->render(
  69 + 'index',
  70 + [
  71 + 'searchModel' => $searchModel,
  72 + 'dataProvider' => $dataProvider,
  73 + ]
  74 + );
  75 + }
  76 +
  77 + /**
  78 + * Displays a single PageCategory model.
  79 + *
  80 + * @param integer $id
  81 + *
  82 + * @return mixed
  83 + */
  84 + public function actionView($id)
  85 + {
  86 + return $this->render(
  87 + 'view',
  88 + [
  89 + 'model' => $this->findModel($id),
  90 + ]
  91 + );
  92 + }
  93 +
  94 + /**
  95 + * Creates a new PageCategory model.
  96 + * If creation is successful, the browser will be redirected to the 'view' page.
  97 + *
  98 + * @return mixed
  99 + */
  100 + public function actionCreate()
  101 + {
  102 + $model = new PageCategory();
  103 + $model->generateLangs();
  104 +
  105 + if ($model->loadWithLangs(Yii::$app->request) && $model->saveWithLangs()) {
  106 + return $this->redirect(
  107 + [
  108 + 'view',
  109 + 'id' => $model->id,
  110 + ]
  111 + );
  112 + } else {
  113 + return $this->render(
  114 + 'create',
  115 + [
  116 + 'model' => $model,
  117 + 'modelLangs' => $model->modelLangs,
  118 + ]
  119 + );
  120 + }
  121 + }
  122 +
  123 + /**
  124 + * Updates an existing PageCategory model.
  125 + * If update is successful, the browser will be redirected to the 'view' page.
  126 + *
  127 + * @param integer $id
  128 + *
  129 + * @return mixed
  130 + */
  131 + public function actionUpdate($id)
  132 + {
  133 + $model = $this->findModel($id);
  134 + $model->generateLangs();
  135 +
  136 + if ($model->loadWithLangs(Yii::$app->request) && $model->saveWithLangs()) {
  137 + return $this->redirect(
  138 + [
  139 + 'view',
  140 + 'id' => $model->id,
  141 + ]
  142 + );
  143 + } else {
  144 + return $this->render(
  145 + 'update',
  146 + [
  147 + 'model' => $model,
  148 + 'modelLangs' => $model->modelLangs,
  149 + ]
  150 + );
  151 + }
  152 + }
  153 +
  154 + /**
  155 + * Deletes an existing PageCategory model.
  156 + * If deletion is successful, the browser will be redirected to the 'index' page.
  157 + *
  158 + * @param integer $id
  159 + *
  160 + * @return mixed
  161 + */
  162 + public function actionDelete($id)
  163 + {
  164 + $this->findModel($id)
  165 + ->delete();
  166 +
  167 + return $this->redirect([ 'index' ]);
  168 + }
  169 +
  170 + /**
  171 + * Finds the PageCategory model based on its primary key value.
  172 + * If the model is not found, a 404 HTTP exception will be thrown.
  173 + *
  174 + * @param integer $id
  175 + *
  176 + * @return PageCategory the loaded model
  177 + * @throws NotFoundHttpException if the model cannot be found
  178 + */
  179 + protected function findModel($id)
  180 + {
  181 + if (( $model = PageCategory::findOne($id) ) !== null) {
  182 + return $model;
  183 + } else {
  184 + throw new NotFoundHttpException('The requested page does not exist.');
  185 + }
  186 + }
  187 +
  188 + /**
  189 + * Returnes an array of matched categories,
  190 + * response must be in format:
  191 + * $out = [
  192 + * 'results' => [
  193 + * [
  194 + * 'id' => 1,
  195 + * 'text' => 'First',
  196 + * ],
  197 + * [
  198 + * 'id' => 2,
  199 + * 'text' => 'Second'
  200 + * ],
  201 + * ],
  202 + * ];
  203 + * ! array key must be 'id' and 'text' !
  204 + *
  205 + * @param null $q
  206 + * @return array
  207 + */
  208 + public function actionList($q = null)
  209 + {
  210 + \Yii::$app->response->format = Response::FORMAT_JSON;
  211 + $out = [
  212 + 'results' => [
  213 + [
  214 + 'id' => '',
  215 + 'text' => '',
  216 + ],
  217 + ],
  218 + ];
  219 + if (!is_null($q)) {
  220 + $categories = PageCategory::find()
  221 + ->joinWith('lang')
  222 + ->select(
  223 + [
  224 + 'id',
  225 + 'text' => 'page_category_lang.title',
  226 + ]
  227 + )
  228 + ->andFilterWhere(
  229 + [
  230 + 'ilike',
  231 + 'page_category_lang.title',
  232 + $q,
  233 + ]
  234 + )
  235 + ->limit(20)
  236 + ->asArray()
  237 + ->all();
  238 +
  239 + if (!empty($categories)) {
  240 + $out[ 'results' ] = $categories;
  241 + }
  242 + }
  243 +
  244 + return $out;
  245 + }
  246 + }
... ...
artweb/artbox-core/controllers/PageController.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\controllers;
  4 +
  5 + use artbox\core\models\PageCategory;
  6 + use Yii;
  7 + use artbox\core\models\Page;
  8 + use artbox\core\models\PageSearch;
  9 + use yii\filters\AccessControl;
  10 + use yii\helpers\ArrayHelper;
  11 + use yii\web\Controller;
  12 + use yii\web\NotFoundHttpException;
  13 + use yii\filters\VerbFilter;
  14 +
  15 + /**
  16 + * PageController implements the CRUD actions for Page model.
  17 + */
  18 + class PageController extends Controller
  19 + {
  20 + /**
  21 + * @return bool|string
  22 + */
  23 + public function getViewPath()
  24 + {
  25 + return \Yii::getAlias('@artbox/core/views/page');
  26 + }
  27 + /**
  28 + * @inheritdoc
  29 + */
  30 + public function behaviors()
  31 + {
  32 + return [
  33 + 'access' => [
  34 + 'class' => AccessControl::className(),
  35 + 'rules' => [
  36 + [
  37 + 'actions' => [
  38 + 'login',
  39 + 'error',
  40 + ],
  41 + 'allow' => true,
  42 + ],
  43 + [
  44 + 'allow' => true,
  45 + 'roles' => [ '@' ],
  46 + ],
  47 + ],
  48 + ],
  49 + 'verbs' => [
  50 + 'class' => VerbFilter::className(),
  51 + 'actions' => [],
  52 + ],
  53 + ];
  54 + }
  55 +
  56 + /**
  57 + * Lists all Page models.
  58 + *
  59 + * @return mixed
  60 + */
  61 + public function actionIndex()
  62 + {
  63 + $searchModel = new PageSearch();
  64 + $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
  65 +
  66 + return $this->render(
  67 + 'index',
  68 + [
  69 + 'searchModel' => $searchModel,
  70 + 'dataProvider' => $dataProvider,
  71 + ]
  72 + );
  73 + }
  74 +
  75 + /**
  76 + * Displays a single Page model.
  77 + *
  78 + * @param integer $id
  79 + *
  80 + * @return mixed
  81 + */
  82 + public function actionView($id)
  83 + {
  84 + return $this->render(
  85 + 'view',
  86 + [
  87 + 'model' => $this->findModel($id),
  88 + ]
  89 + );
  90 + }
  91 +
  92 + /**
  93 + * Creates a new Page model.
  94 + * If creation is successful, the browser will be redirected to the 'view' page.
  95 + *
  96 + * @return mixed
  97 + */
  98 + public function actionCreate()
  99 + {
  100 + $model = new Page();
  101 + $model->generateLangs();
  102 +
  103 + $model->categoryIds = [];
  104 +
  105 + if ($model->loadWithLangs(\Yii::$app->request)) {
  106 + if ($model->saveWithLangs()) {
  107 +
  108 + $categories = PageCategory::find()
  109 + ->where([ 'id' => \Yii::$app->request->post('categoryIds') ])
  110 + ->all();
  111 +
  112 + $model->linkMany('categories', $categories);
  113 +
  114 + $model->saveImages(\Yii::$app->request->post());
  115 +
  116 + return $this->redirect(
  117 + [
  118 + 'view',
  119 + 'id' => $model->id,
  120 + ]
  121 + );
  122 + }
  123 + }
  124 + return $this->render(
  125 + 'create',
  126 + [
  127 + 'model' => $model,
  128 + 'modelLangs' => $model->modelLangs,
  129 + ]
  130 + );
  131 + }
  132 +
  133 + /**
  134 + * Updates an existing Page model.
  135 + * If update is successful, the browser will be redirected to the 'view' page.
  136 + *
  137 + * @param integer $id
  138 + *
  139 + * @return mixed
  140 + */
  141 + public function actionUpdate($id)
  142 + {
  143 + $model = $this->findModel($id);
  144 + $model->generateLangs();
  145 +
  146 + $model->categoryIds = ArrayHelper::map(
  147 + $model->categories,
  148 + 'id',
  149 + 'lang.title'
  150 + );
  151 +
  152 + if ($model->loadWithLangs(\Yii::$app->request)) {
  153 + if ($model->saveWithLangs()) {
  154 +
  155 + $categories = PageCategory::find()
  156 + ->where([ 'id' => \Yii::$app->request->post('categoryIds') ])
  157 + ->all();
  158 +
  159 + $model->linkMany('categories', $categories);
  160 +
  161 + $model->saveImages(\Yii::$app->request->post());
  162 +
  163 + return $this->redirect(
  164 + [
  165 + 'view',
  166 + 'id' => $model->id,
  167 + ]
  168 + );
  169 + }
  170 + }
  171 + return $this->render(
  172 + 'update',
  173 + [
  174 + 'model' => $model,
  175 + 'modelLangs' => $model->modelLangs,
  176 + ]
  177 + );
  178 + }
  179 +
  180 + /**
  181 + * Deletes an existing Page model.
  182 + * If deletion is successful, the browser will be redirected to the 'index' page.
  183 + *
  184 + * @param integer $id
  185 + *
  186 + * @return mixed
  187 + */
  188 + public function actionDelete($id)
  189 + {
  190 + $this->findModel($id)
  191 + ->delete();
  192 +
  193 + return $this->redirect([ 'index' ]);
  194 + }
  195 +
  196 + /**
  197 + * Finds the Page model based on its primary key value.
  198 + * If the model is not found, a 404 HTTP exception will be thrown.
  199 + *
  200 + * @param integer $id
  201 + *
  202 + * @return array|\yii\db\ActiveRecord|Page
  203 + * @throws NotFoundHttpException if the model cannot be found
  204 + */
  205 + protected function findModel($id)
  206 + {
  207 + $model = Page::find()
  208 + ->with(
  209 + [
  210 + 'lang',
  211 + 'categories.lang',
  212 + ]
  213 + )
  214 + ->where([ 'id' => $id ])
  215 + ->one();
  216 +
  217 + if ($model !== null) {
  218 + return $model;
  219 + } else {
  220 + throw new NotFoundHttpException('The requested page does not exist.');
  221 + }
  222 + }
  223 + }
... ...
artweb/artbox-core/controllers/ProfileController.php 0 → 100755
  1 +<?php
  2 + namespace artbox\core\controllers;
  3 +
  4 + use artbox\core\behaviors\LinkBehavior;
  5 + use artbox\core\models\ChangePassword;
  6 + use artbox\core\models\User;
  7 + use artbox\core\models\UserData;
  8 + use yii\base\InvalidConfigException;
  9 + use yii\filters\AccessControl;
  10 + use yii\filters\VerbFilter;
  11 + use yii\web\Controller;
  12 +
  13 + /**
  14 + * Class ProfileController
  15 + *
  16 + * @package artbox\core\controllers
  17 + */
  18 + class ProfileController extends Controller
  19 + {
  20 + /**
  21 + * @inheritdoc
  22 + */
  23 + public function behaviors()
  24 + {
  25 + return [
  26 + 'access' => [
  27 + 'class' => AccessControl::className(),
  28 + 'rules' => [
  29 + [
  30 + 'actions' => [
  31 + 'login',
  32 + 'error',
  33 + ],
  34 + 'allow' => true,
  35 + ],
  36 + [
  37 + 'allow' => true,
  38 + 'roles' => [ '@' ],
  39 + ],
  40 + ],
  41 + ],
  42 + 'verbs' => [
  43 + 'class' => VerbFilter::className(),
  44 + 'actions' => [// 'change-password' => [ 'post' ],
  45 + ],
  46 + ],
  47 + ];
  48 + }
  49 + /**
  50 + * @return bool|string
  51 + */
  52 + public function getViewPath()
  53 + {
  54 + return \Yii::getAlias('@artbox/core/views/profile');
  55 + }
  56 +
  57 + /**
  58 + * User profile page, that allows to change UserData and password.
  59 + *
  60 + * @param \artbox\core\models\ChangePassword|null $changePasswordModel
  61 + * @param \artbox\core\models\UserData|null $userData
  62 + *
  63 + * @return string
  64 + * @throws \yii\base\InvalidConfigException
  65 + */
  66 + public function actionIndex(ChangePassword $changePasswordModel = null, UserData $userData = null)
  67 + {
  68 + /**
  69 + * @var User $user
  70 + */
  71 + $user = \Yii::$app->user->identity;
  72 + /**
  73 + * @var LinkBehavior $userDataBehavior
  74 + */
  75 + if (empty( $userData )) {
  76 + if (( $userDataBehavior = $user->getBehavior('userData') ) === null) {
  77 + throw new InvalidConfigException(
  78 + \Yii::t('core', '$app->user->identity class must have LinkBehavior to UserData model')
  79 + );
  80 + }
  81 + $userDataBehavior->ensureExistance();
  82 + $userData = $userDataBehavior->getLinkObject();
  83 + }
  84 + if (empty( $changePasswordModel )) {
  85 + /**
  86 + * @var ChangePassword $changePasswordModel
  87 + */
  88 + $changePasswordModel = \Yii::createObject(ChangePassword::className());
  89 + }
  90 + return $this->render(
  91 + 'index',
  92 + [
  93 + 'user' => $user,
  94 + 'userData' => $userData,
  95 + 'changePasswordModel' => $changePasswordModel,
  96 + ]
  97 + );
  98 + }
  99 +
  100 + /**
  101 + * Change User password
  102 + *
  103 + * @return string|\yii\web\Response
  104 + */
  105 + public function actionChangePassword()
  106 + {
  107 + if (empty( \Yii::$app->request->post() )) {
  108 + return $this->redirect([ 'index' ]);
  109 + }
  110 + /**
  111 + * @var ChangePassword $model
  112 + */
  113 + $model = \Yii::createObject(ChangePassword::className());
  114 + $success = false;
  115 + if ($model->load(\Yii::$app->request->post()) && $model->validate()) {
  116 + if ($model->validatePassword()) {
  117 + if (( $success = $model->saveChanges() ) === true) {
  118 + \Yii::$app->session->setFlash('success', \Yii::t('core', 'Password was successfully changed.'));
  119 + }
  120 + }
  121 + }
  122 + if (!$success) {
  123 + \Yii::$app->session->setFlash('error', \Yii::t('core', 'Password change failed.'));
  124 + }
  125 + $model->oldPassword = $model->newPassword = $model->newPasswordRepeat = null;
  126 + return $this->actionIndex($model);
  127 + }
  128 +
  129 + /**
  130 + * Update UserData
  131 + *
  132 + * @return string|\yii\web\Response
  133 + * @throws \yii\base\InvalidConfigException
  134 + */
  135 + public function actionUpdate()
  136 + {
  137 + if (empty( \Yii::$app->request->post() )) {
  138 + return $this->redirect([ 'index' ]);
  139 + }
  140 + /**
  141 + * @var User $user
  142 + */
  143 + $user = \Yii::$app->user->identity;
  144 + /**
  145 + * @var LinkBehavior $userDataBehavior
  146 + */
  147 + if (( $userDataBehavior = $user->getBehavior('userData') ) === null) {
  148 + throw new InvalidConfigException(
  149 + \Yii::t('core', '$app->user->identity class must have LinkBehavior to UserData model')
  150 + );
  151 + }
  152 + $userDataBehavior->ensureExistance();
  153 + $model = $userDataBehavior->getLinkObject();
  154 + $success = false;
  155 + if ($model->load(\Yii::$app->request->post()) && $model->validate()) {
  156 + if (( $success = $model->save() ) === true) {
  157 + \Yii::$app->session->setFlash(
  158 + 'success',
  159 + \Yii::t('core', 'Personal information was successfully changed.')
  160 + );
  161 + }
  162 + }
  163 + if (!$success) {
  164 + \Yii::$app->session->setFlash('error', \Yii::t('core', 'Personal information change failed.'));
  165 + }
  166 + return $this->actionIndex(null, $model);
  167 + }
  168 + }
  169 +
0 170 \ No newline at end of file
... ...
artweb/artbox-core/controllers/SeoController.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\controllers;
  4 +
  5 + use yii\filters\AccessControl;
  6 + use yii\web\Controller;
  7 + use yii\filters\VerbFilter;
  8 +
  9 + /**
  10 + * SeoController contains actions to satisfy SEO needs of the website.
  11 + */
  12 + class SeoController extends Controller
  13 + {
  14 + /**
  15 + * @return bool|string
  16 + */
  17 + public function getViewPath()
  18 + {
  19 + return \Yii::getAlias('@artbox/core/views/seo');
  20 + }
  21 + /**
  22 + * @inheritdoc
  23 + */
  24 + public function behaviors()
  25 + {
  26 + return [
  27 + 'access' => [
  28 + 'class' => AccessControl::className(),
  29 + 'rules' => [
  30 + [
  31 + 'actions' => [
  32 + 'login',
  33 + 'error',
  34 + ],
  35 + 'allow' => true,
  36 + ],
  37 + [
  38 + 'allow' => true,
  39 + 'roles' => [ '@' ],
  40 + ],
  41 + ],
  42 + ],
  43 + 'verbs' => [
  44 + 'class' => VerbFilter::className(),
  45 + 'actions' => [],
  46 + ],
  47 + ];
  48 + }
  49 +
  50 + /**
  51 + * To be done.
  52 + *
  53 + * @return mixed
  54 + */
  55 + public function actionIndex()
  56 + {
  57 + return $this->render('index');
  58 + }
  59 + }
... ...
artweb/artbox-core/controllers/SitemapController.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\controllers;
  4 +
  5 + use artbox\core\models\SitemapDynamic;
  6 + use artbox\core\models\SitemapStatic;
  7 + use artbox\core\components\Sitemap;
  8 + use yii\bootstrap\ActiveForm;
  9 + use yii\bootstrap\Html;
  10 + use yii\filters\AccessControl;
  11 + use yii\helpers\Json;
  12 + use yii\web\Controller;
  13 +
  14 + /**
  15 + * Class SitemapController
  16 + */
  17 + class SitemapController extends Controller
  18 + {
  19 + /**
  20 + * @inheritdoc
  21 + */
  22 + public function behaviors()
  23 + {
  24 + return [
  25 + 'access' => [
  26 + 'class' => AccessControl::className(),
  27 + 'rules' => [
  28 + [
  29 + 'actions' => [
  30 + 'login',
  31 + 'error',
  32 + ],
  33 + 'allow' => true,
  34 + ],
  35 + [
  36 + 'allow' => true,
  37 + 'roles' => [ '@' ],
  38 + ],
  39 + ],
  40 + ],
  41 + ];
  42 + }
  43 +
  44 + /**
  45 + * Action to configure sitemap of the website
  46 + *
  47 + * @return string
  48 + */
  49 + public function actionIndex()
  50 + {
  51 + return $this->render('index');
  52 + }
  53 +
  54 + /**
  55 + * Action to configure sitemap of the website
  56 + *
  57 + * @return string
  58 + */
  59 + public function actionUpdate()
  60 + {
  61 + /**
  62 + * @var Sitemap $sitemap
  63 + */
  64 + $request = \Yii::$app->request;
  65 + // ***** Generate SitemapDynamic models for every entity in Sitemap component
  66 + $sitemap = \Yii::$app->get('sitemap');
  67 + $entities = $sitemap->entities;
  68 + /**
  69 + * @var SitemapDynamic[] $entity_models
  70 + */
  71 + $entity_models = [];
  72 + foreach ($entities as $entity) {
  73 + $entity_model = new SitemapDynamic();
  74 + $entity_model->entity = $entity[ 'class' ];
  75 + $entity_model->status = SitemapDynamic::STATUS_DISABLED;
  76 + $entity_models[] = $entity_model;
  77 + }
  78 + // ***** <<< End
  79 + if ($request->isPost) {
  80 + $success = false;
  81 + // ***** Create SitemapStatic models from POST and delete existing
  82 + $models = [];
  83 + $index = 1;
  84 + foreach ($request->post('SitemapStatic') as $item) {
  85 + $model = new SitemapStatic();
  86 + if ($model->load($item, '') && $model->validate()) {
  87 + $model->id = $index++;
  88 + $models[] = $model;
  89 + }
  90 + }
  91 + if (!empty($models)) {
  92 + $old = SitemapStatic::find()
  93 + ->all();
  94 + foreach ($old as $item) {
  95 + $item->delete();
  96 + }
  97 + foreach ($models as $model) {
  98 + $model->save(false);
  99 + $success = true;
  100 + }
  101 + }
  102 + // ***** <<< End
  103 + // ***** Create SitemapDynamic models from POST and delete existing
  104 +
  105 + /**
  106 + * @var SitemapDynamic[] $old_entity_models
  107 + */
  108 + $old_entity_models = SitemapDynamic::find()
  109 + ->all();
  110 + foreach ($old_entity_models as $old_entity_model) {
  111 + $old_entity_model->delete();
  112 + }
  113 + $index = 1;
  114 + $entity_models = [];
  115 + foreach ($request->post('SitemapDynamic') as $item) {
  116 + $entity = new SitemapDynamic();
  117 + if ($entity->load($item, '') && $entity->validate()) {
  118 + $entity->id = $index++;
  119 + $entity->save(false);
  120 + $entity_models[] = $entity;
  121 + $success = true;
  122 + }
  123 + }
  124 + if ($success) {
  125 + if ($request->post('action', '') == 'generate') {
  126 + if ($sitemap->generateXML()) {
  127 + \Yii::$app->session->setFlash(
  128 + 'success',
  129 + \Yii::t(
  130 + 'core',
  131 + 'Карта сайта сгенерированна в ' . \Yii::getAlias(
  132 + $sitemap->path . '.'
  133 + )
  134 + )
  135 + );
  136 + }
  137 + }
  138 + return $this->redirect([ 'index' ]);
  139 + }
  140 + // ***** <<< End
  141 + } else {
  142 + // ***** Find existing SitemapStatic models
  143 + $models = SitemapStatic::find()
  144 + ->all();
  145 + if (empty($models)) {
  146 + $models = [ new SitemapStatic() ];
  147 + }
  148 + // ***** <<< End
  149 + // ***** Fill SitemapDynamic models from Sitemap component with existing models
  150 + /**
  151 + * @var SitemapDynamic[] $old_entity_models
  152 + */
  153 + $old_entity_models = SitemapDynamic::find()
  154 + ->indexBy('entity')
  155 + ->all();
  156 + foreach ($entity_models as $index => $entity_model) {
  157 + if (isset($old_entity_models[ $entity_model->entity ])) {
  158 + $entity_model->status = $old_entity_models[ $entity_model->entity ]->status;
  159 + $entity_model->priority = $old_entity_models[ $entity_model->entity ]->priority;
  160 + $entity_model->frequency = $old_entity_models[ $entity_model->entity ]->frequency;
  161 + }
  162 + }
  163 + // ***** <<< End
  164 + }
  165 + return $this->render(
  166 + 'update',
  167 + [
  168 + 'models' => $models,
  169 + 'entity_models' => $entity_models,
  170 + ]
  171 + );
  172 + }
  173 +
  174 + /**
  175 + * Create activeField for static sitemap
  176 + *
  177 + * @return string
  178 + */
  179 + public function actionCreateStatic()
  180 + {
  181 + $content = '';
  182 + $request = \Yii::$app->request;
  183 + $formId = $request->get('formId');
  184 + $count = $request->get('count');
  185 + if (empty($formId) || empty($count)) {
  186 + return $this->renderContent($content);
  187 + }
  188 + $model = new SitemapStatic();
  189 + $form = new ActiveForm();
  190 + $content .= $form->field(
  191 + $model,
  192 + "[$count]url",
  193 + [
  194 + 'options' => [
  195 + 'class' => 'form-group col-xs-5 col-sm-6',
  196 + ],
  197 + ]
  198 + )
  199 + ->textInput()
  200 + ->render();
  201 + $content .= $form->field(
  202 + $model,
  203 + "[$count]frequency",
  204 + [
  205 + 'options' => [
  206 + 'class' => 'form-group col-xs-3 col-sm-3',
  207 + ],
  208 + ]
  209 + )
  210 + ->dropDownList(
  211 + [
  212 + 'always' => 'always',
  213 + 'hourly' => 'hourly',
  214 + 'daily' => 'daily',
  215 + 'weekly' => 'weekly',
  216 + 'monthly' => 'monthly',
  217 + 'yearly' => 'yearly',
  218 + 'never' => 'never',
  219 + ]
  220 + )
  221 + ->render();
  222 + $content .= $form->field(
  223 + $model,
  224 + "[$count]priority",
  225 + [
  226 + 'options' => [
  227 + 'class' => 'form-group col-xs-3 col-sm-2',
  228 + ],
  229 + ]
  230 + )
  231 + ->textInput()
  232 + ->render();
  233 + $content .= Html::icon(
  234 + 'minus',
  235 + [
  236 + 'class' => 'col-xs-1 field-group-remove',
  237 + 'onclick' => 'sitemap_remove(this)',
  238 + ]
  239 + );
  240 + foreach ($form->attributes as $index => $attribute) {
  241 + $content .= Html::script("$('#w0').yiiActiveForm('add', " . Json::htmlEncode($attribute) . ");");
  242 + }
  243 + $content = Html::tag(
  244 + 'div',
  245 + $content,
  246 + [
  247 + 'class' => 'row field-group',
  248 + ]
  249 + );
  250 + $this->layout = false;
  251 + return $this->renderContent($content);
  252 + }
  253 +
  254 + /**
  255 + * Generate sitemap XML to Sitemap::$path
  256 + *
  257 + * @return bool
  258 + */
  259 + public function actionGenerate()
  260 + {
  261 + $response = \Yii::$app->response;
  262 + $response->format = $response::FORMAT_JSON;
  263 + /**
  264 + * @var Sitemap $sitemap
  265 + */
  266 + $sitemap = \Yii::$app->get('sitemap');
  267 + return $sitemap->generateXML();
  268 + }
  269 + }
  270 +
0 271 \ No newline at end of file
... ...
artweb/artbox-core/controllers/SlideController.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\controllers;
  4 +
  5 + use artbox\core\models\Slide;
  6 + use artbox\core\models\Slider;
  7 + use artbox\core\models\SlideSearch;
  8 + use Yii;
  9 + use yii\filters\AccessControl;
  10 + use yii\web\Controller;
  11 + use yii\web\NotFoundHttpException;
  12 + use yii\filters\VerbFilter;
  13 +
  14 + /**
  15 + * SlideController implements the CRUD actions for Slide model.
  16 + */
  17 + class SlideController extends Controller
  18 + {
  19 + /**
  20 + * @inheritdoc
  21 + */
  22 + public function behaviors()
  23 + {
  24 + return [
  25 + 'access' => [
  26 + 'class' => AccessControl::className(),
  27 + 'rules' => [
  28 + [
  29 + 'actions' => [
  30 + 'login',
  31 + 'error',
  32 + ],
  33 + 'allow' => true,
  34 + ],
  35 + [
  36 + 'allow' => true,
  37 + 'roles' => [ '@' ],
  38 + ],
  39 + ],
  40 + ],
  41 + 'verbs' => [
  42 + 'class' => VerbFilter::className(),
  43 + 'actions' => [
  44 + 'delete' => [ 'POST' ],
  45 + ],
  46 + ],
  47 + ];
  48 + }
  49 +
  50 + /**
  51 + * Lists all Slide models.
  52 + *
  53 + * @param int $slider_id
  54 + *
  55 + * @return mixed
  56 + */
  57 + public function actionIndex($slider_id)
  58 + {
  59 + $slider = $this->findSlider($slider_id);
  60 + $searchModel = new SlideSearch();
  61 + $dataProvider = $searchModel->search(Yii::$app->request->queryParams, $slider);
  62 +
  63 + return $this->render(
  64 + 'index',
  65 + [
  66 + 'searchModel' => $searchModel,
  67 + 'dataProvider' => $dataProvider,
  68 + 'slider' => $slider,
  69 + ]
  70 + );
  71 + }
  72 +
  73 + /**
  74 + * Displays a single Slide model.
  75 + *
  76 + * @param integer $id
  77 + *
  78 + * @return mixed
  79 + */
  80 + public function actionView($id)
  81 + {
  82 + return $this->render(
  83 + 'view',
  84 + [
  85 + 'model' => $this->findModel($id),
  86 + ]
  87 + );
  88 + }
  89 +
  90 + /**
  91 + * Creates a new Slide model.
  92 + * If creation is successful, the browser will be redirected to the 'view' page.
  93 + *
  94 + * @param int $slider_id
  95 + *
  96 + * @return mixed
  97 + */
  98 + public function actionCreate(int $slider_id)
  99 + {
  100 + $slider = $this->findSlider($slider_id);
  101 +
  102 + $model = new Slide();
  103 + $model->generateLangs();
  104 +
  105 + if ($model->loadWithLangs(\Yii::$app->request)) {
  106 + if ($model->saveWithLangs()) {
  107 + return $this->redirect(
  108 + [
  109 + 'view',
  110 + 'id' => $model->id,
  111 + ]
  112 + );
  113 + }
  114 + }
  115 + return $this->render(
  116 + 'create',
  117 + [
  118 + 'model' => $model,
  119 + 'modelLangs' => $model->modelLangs,
  120 + 'slider' => $slider,
  121 + ]
  122 + );
  123 + }
  124 +
  125 + /**
  126 + * Updates an existing Slide model.
  127 + * If update is successful, the browser will be redirected to the 'view' page.
  128 + *
  129 + * @param integer $id
  130 + *
  131 + * @return mixed
  132 + */
  133 + public function actionUpdate($id)
  134 + {
  135 + $model = $this->findModel($id);
  136 + $model->generateLangs();
  137 +
  138 + $slider = $this->findSlider($model->slider_id);
  139 +
  140 + if ($model->loadWithLangs(\Yii::$app->request)) {
  141 + if ($model->saveWithLangs()) {
  142 + return $this->redirect(
  143 + [
  144 + 'view',
  145 + 'id' => $model->id,
  146 + ]
  147 + );
  148 + }
  149 + }
  150 + return $this->render(
  151 + 'update',
  152 + [
  153 + 'model' => $model,
  154 + 'modelLangs' => $model->modelLangs,
  155 + 'slider' => $slider,
  156 + ]
  157 + );
  158 + }
  159 +
  160 + /**
  161 + * Deletes an existing Slide model.
  162 + * If deletion is successful, the browser will be redirected to the 'index' page.
  163 + *
  164 + * @param integer $id
  165 + *
  166 + * @return mixed
  167 + */
  168 + public function actionDelete($id)
  169 + {
  170 + $this->findModel($id)
  171 + ->delete();
  172 +
  173 + return $this->redirect([ 'index' ]);
  174 + }
  175 +
  176 + /**
  177 + * Finds the Slide model based on its primary key value.
  178 + * If the model is not found, a 404 HTTP exception will be thrown.
  179 + *
  180 + * @param integer $id
  181 + *
  182 + * @return Slide the loaded model
  183 + * @throws NotFoundHttpException if the model cannot be found
  184 + */
  185 + protected function findModel($id)
  186 + {
  187 + if (( $model = Slide::findOne($id) ) !== null) {
  188 + return $model;
  189 + } else {
  190 + throw new NotFoundHttpException('The requested page does not exist.');
  191 + }
  192 + }
  193 +
  194 + /**
  195 + * Finds the Slider model based on its primary key value.
  196 + * If the model is not found, a 404 HTTP exception will be thrown.
  197 + *
  198 + * @param integer $id
  199 + *
  200 + * @return Slider the loaded model
  201 + * @throws NotFoundHttpException if the model cannot be found
  202 + */
  203 + protected function findSlider($id)
  204 + {
  205 + if (( $model = Slider::findOne($id) ) !== null) {
  206 + return $model;
  207 + } else {
  208 + throw new NotFoundHttpException('The requested page does not exist.');
  209 + }
  210 + }
  211 + }
... ...
artweb/artbox-core/controllers/SliderController.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\controllers;
  4 +
  5 + use artbox\core\models\Slider;
  6 + use artbox\core\models\SliderSearch;
  7 + use Yii;
  8 + use yii\filters\AccessControl;
  9 + use yii\web\Controller;
  10 + use yii\web\NotFoundHttpException;
  11 + use yii\filters\VerbFilter;
  12 +
  13 + /**
  14 + * SliderController implements the CRUD actions for Slider model.
  15 + */
  16 + class SliderController extends Controller
  17 + {
  18 + /**
  19 + * @inheritdoc
  20 + */
  21 + public function behaviors()
  22 + {
  23 + return [
  24 + 'access' => [
  25 + 'class' => AccessControl::className(),
  26 + 'rules' => [
  27 + [
  28 + 'actions' => [
  29 + 'login',
  30 + 'error',
  31 + ],
  32 + 'allow' => true,
  33 + ],
  34 + [
  35 + 'allow' => true,
  36 + 'roles' => [ '@' ],
  37 + ],
  38 + ],
  39 + ],
  40 + 'verbs' => [
  41 + 'class' => VerbFilter::className(),
  42 + 'actions' => [
  43 + 'delete' => [ 'POST' ],
  44 + ],
  45 + ],
  46 + ];
  47 + }
  48 +
  49 + /**
  50 + * Lists all Slider models.
  51 + *
  52 + * @return mixed
  53 + */
  54 + public function actionIndex()
  55 + {
  56 + $searchModel = new SliderSearch();
  57 + $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
  58 +
  59 + return $this->render(
  60 + 'index',
  61 + [
  62 + 'searchModel' => $searchModel,
  63 + 'dataProvider' => $dataProvider,
  64 + ]
  65 + );
  66 + }
  67 +
  68 + /**
  69 + * Displays a single Slider model.
  70 + *
  71 + * @param integer $id
  72 + *
  73 + * @return mixed
  74 + */
  75 + public function actionView($id)
  76 + {
  77 + return $this->render(
  78 + 'view',
  79 + [
  80 + 'model' => $this->findModel($id),
  81 + ]
  82 + );
  83 + }
  84 +
  85 + /**
  86 + * Creates a new Slider model.
  87 + * If creation is successful, the browser will be redirected to the 'view' page.
  88 + *
  89 + * @return mixed
  90 + */
  91 + public function actionCreate()
  92 + {
  93 + $model = new Slider();
  94 +
  95 + if ($model->load(Yii::$app->request->post()) && $model->save()) {
  96 + return $this->redirect(
  97 + [
  98 + 'view',
  99 + 'id' => $model->id,
  100 + ]
  101 + );
  102 + } else {
  103 + return $this->render(
  104 + 'create',
  105 + [
  106 + 'model' => $model,
  107 + ]
  108 + );
  109 + }
  110 + }
  111 +
  112 + /**
  113 + * Updates an existing Slider model.
  114 + * If update is successful, the browser will be redirected to the 'view' page.
  115 + *
  116 + * @param integer $id
  117 + *
  118 + * @return mixed
  119 + */
  120 + public function actionUpdate($id)
  121 + {
  122 + $model = $this->findModel($id);
  123 +
  124 + if ($model->load(Yii::$app->request->post()) && $model->save()) {
  125 + return $this->redirect(
  126 + [
  127 + 'view',
  128 + 'id' => $model->id,
  129 + ]
  130 + );
  131 + } else {
  132 + return $this->render(
  133 + 'update',
  134 + [
  135 + 'model' => $model,
  136 + ]
  137 + );
  138 + }
  139 + }
  140 +
  141 + /**
  142 + * Deletes an existing Slider model.
  143 + * If deletion is successful, the browser will be redirected to the 'index' page.
  144 + *
  145 + * @param integer $id
  146 + *
  147 + * @return mixed
  148 + */
  149 + public function actionDelete($id)
  150 + {
  151 + $this->findModel($id)
  152 + ->delete();
  153 +
  154 + return $this->redirect([ 'index' ]);
  155 + }
  156 +
  157 + /**
  158 + * Finds the Slider model based on its primary key value.
  159 + * If the model is not found, a 404 HTTP exception will be thrown.
  160 + *
  161 + * @param integer $id
  162 + *
  163 + * @return Slider the loaded model
  164 + * @throws NotFoundHttpException if the model cannot be found
  165 + */
  166 + protected function findModel($id)
  167 + {
  168 + if (( $model = Slider::findOne($id) ) !== null) {
  169 + return $model;
  170 + } else {
  171 + throw new NotFoundHttpException('The requested page does not exist.');
  172 + }
  173 + }
  174 + }
... ...
artweb/artbox-core/exceptions/AliasOverwriteException.php 0 → 100644
  1 +<?php
  2 +
  3 + namespace artbox\core\exceptions;
  4 +
  5 + use yii\base\Exception;
  6 +
  7 + /**
  8 + * Class AliasOverwriteException
  9 + *
  10 + * @package artbox\core\exceptions
  11 + */
  12 + class AliasOverwriteException extends Exception
  13 + {
  14 + /**
  15 + * @return string
  16 + */
  17 + public function getName()
  18 + {
  19 + return 'Alias was already setted';
  20 + }
  21 + }
0 22 \ No newline at end of file
... ...
artweb/artbox-core/filters/IsAjaxFilter.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\filters;
  4 +
  5 + use Yii;
  6 + use yii\base\ActionEvent;
  7 + use yii\base\Behavior;
  8 + use yii\web\Controller;
  9 + use yii\web\MethodNotAllowedHttpException;
  10 +
  11 + /**
  12 + * Class IsAjaxFilter
  13 + *
  14 + * @package artbox\core\filters
  15 + */
  16 + class IsAjaxFilter extends Behavior
  17 + {
  18 + /**
  19 + * @var array
  20 + */
  21 + public $actions = [];
  22 +
  23 + /**
  24 + * Declares event handlers for the [[owner]]'s events.
  25 + *
  26 + * @return array events (array keys) and the corresponding event handler methods (array values).
  27 + */
  28 + public function events()
  29 + {
  30 + return [ Controller::EVENT_BEFORE_ACTION => 'beforeAction' ];
  31 + }
  32 +
  33 + /**
  34 + * @param ActionEvent $event
  35 + *
  36 + * @return bool
  37 + * @throws MethodNotAllowedHttpException when the request method is not allowed.
  38 + */
  39 + public function beforeAction($event)
  40 + {
  41 + $action = $event->action->id;
  42 + if (!in_array($action, $this->actions)) {
  43 + return $event->isValid;
  44 + }
  45 +
  46 + if (!Yii::$app->request->isAjax) {
  47 + $event->isValid = false;
  48 + throw new MethodNotAllowedHttpException('Must be AJAX request only');
  49 + }
  50 +
  51 + return $event->isValid;
  52 + }
  53 + }
... ...
artweb/artbox-core/helpers/ImageHelper.php 0 → 100755
  1 +<?php
  2 + namespace artbox\core\helpers;
  3 +
  4 + use yii\base\InvalidConfigException;
  5 + use Yii;
  6 +
  7 + /**
  8 + * Class ImageHelper
  9 + *
  10 + * @package artbox\core\helpers
  11 + */
  12 + class ImageHelper
  13 + {
  14 + /**
  15 + * Parse $given path and creates image manipulator instance
  16 + *
  17 + * @param $path
  18 + *
  19 + * @return ImageManipulator
  20 + * @throws \yii\base\InvalidConfigException
  21 + */
  22 + public static function set($path)
  23 + {
  24 + self::checkDir();
  25 +
  26 + $path = Yii::getAlias($path);
  27 +
  28 + if (!file_exists($path) || empty($path)) {
  29 + $path = Yii::getAlias('@frontend/web/img/no-image.png');
  30 + }
  31 +
  32 + $matches = [];
  33 + if (!preg_match("~^(.+\/)([a-zA-Z0-9_-]+)\.(jpg|jpeg|gif|png)$~i", $path, $matches)) {
  34 + throw new InvalidConfigException('Wrong file path');
  35 + }
  36 + /**
  37 + * @var ImageManipulator $obj
  38 + */
  39 + $obj = Yii::createObject(
  40 + [
  41 + 'class' => ImageManipulator::className(),
  42 + 'fullPath' => $matches[ 0 ],
  43 + 'path' => $matches[ 1 ],
  44 + 'name' => $matches[ 2 ],
  45 + 'extension' => $matches[ 3 ],
  46 +
  47 + ]
  48 + );
  49 +
  50 + return $obj;
  51 + }
  52 +
  53 + /**
  54 + * Check if helper directory exists, if not - create it
  55 + */
  56 + protected static function checkDir()
  57 + {
  58 + $dir = Yii::getAlias('@storage/helper');
  59 + $stor = Yii::getAlias('@storage');
  60 +
  61 + if (!is_dir($stor)) {
  62 + mkdir($stor);
  63 + }
  64 + if (!is_dir($dir)) {
  65 + mkdir($dir);
  66 + }
  67 + }
  68 + }
0 69 \ No newline at end of file
... ...
artweb/artbox-core/helpers/ImageManipulator.php 0 → 100755
  1 +<?php
  2 + namespace artbox\core\helpers;
  3 +
  4 + use Imagine\Image\Box;
  5 + use Imagine\Image\ImageInterface;
  6 + use Imagine\Image\Palette\RGB;
  7 + use Imagine\Image\Point;
  8 + use yii\base\InvalidConfigException;
  9 + use yii\base\Object;
  10 + use yii\bootstrap\Html;
  11 + use yii\imagine\Image;
  12 +
  13 + /**
  14 + * Class ImageManipulator
  15 + *
  16 + * @package artbox\core\helpers
  17 + * @property ImageInterface $image
  18 + */
  19 + class ImageManipulator extends Object
  20 + {
  21 + const ACTION_RESIZE = 'resize';
  22 +
  23 + const ACTION_SET_WIDTH = 'set_width';
  24 +
  25 + const ACTION_SET_HEIGHT = 'set_height';
  26 +
  27 + const ACTION_CROP_RESIZE = 'crop_resize';
  28 +
  29 + const ACTION_CROP = 'crop';
  30 +
  31 + const ACTION_FILL_RESIZE = 'fill_resize';
  32 +
  33 + const ACTION_STRICT_RESIZE = 'strict_resize';
  34 +
  35 + /**
  36 + * Name of the file
  37 + */
  38 + public $name;
  39 +
  40 + /**
  41 + * Path without file name
  42 + */
  43 + public $path;
  44 +
  45 + /**
  46 + * File extension
  47 + */
  48 + public $extension;
  49 +
  50 + /**
  51 + * Full path to file
  52 + */
  53 + public $fullPath;
  54 +
  55 + /**
  56 + * The name of action to performe if file doen't exist
  57 + *
  58 + * @var string
  59 + */
  60 + protected $action;
  61 +
  62 + protected $actionWidth;
  63 +
  64 + protected $actionHeight;
  65 +
  66 + protected $actionColor;
  67 +
  68 + /**
  69 + * Prefix that will be added to file name
  70 + */
  71 + private $prefix;
  72 +
  73 + /**
  74 + * The image object
  75 + */
  76 + private $image;
  77 +
  78 + /**
  79 + * Initial width
  80 + */
  81 + private $width;
  82 +
  83 + /**
  84 + * Initial height
  85 + */
  86 + private $height;
  87 +
  88 + /**
  89 + * Default image quality
  90 + */
  91 + private $qualityValue = 100;
  92 +
  93 + /**
  94 + * Get size of image
  95 + *
  96 + * @param bool $force
  97 + *
  98 + * @return \Imagine\Image\BoxInterface
  99 + */
  100 + public function getSize($force = false)
  101 + {
  102 + /**
  103 + * @todo Change it to php: getimagesize() if $this->image is null
  104 + */
  105 + if ($force) {
  106 + $this->image = Image::getImagine()
  107 + ->open($this->fullPath);
  108 + }
  109 +
  110 + return $this->image->getSize();
  111 + }
  112 +
  113 + /**
  114 + * Open the image and store it, set initial width and height
  115 + */
  116 + public function init()
  117 + {
  118 + // $this->image = Image::getImagine()
  119 + // ->open($this->fullPath);
  120 + // $this->width = $this->image->getSize()
  121 + // ->getWidth();
  122 + // $this->height = $this->image->getSize()
  123 + // ->getHeight();
  124 + }
  125 +
  126 + /**
  127 + * Resize image, keeping aspect ratio
  128 + *
  129 + * @param int $width
  130 + * @param int $height
  131 + *
  132 + * @return $this
  133 + */
  134 + public function resize(int $width, int $height)
  135 + {
  136 + $this->prefix = $width . '_x_' . $height;
  137 +
  138 + $this->action = self::ACTION_RESIZE;
  139 +
  140 + $this->actionWidth = $width;
  141 + $this->actionHeight = $height;
  142 +
  143 + return $this;
  144 + }
  145 +
  146 + protected function perfomResize(int $width, int $height)
  147 + {
  148 + $this->image = $this->image->thumbnail(new Box($width, $height));
  149 +
  150 + return $this;
  151 +
  152 + }
  153 +
  154 + /**
  155 + * Resize to needed width, saving the proportion
  156 + *
  157 + * @param int $width
  158 + *
  159 + * @return $this
  160 + */
  161 + public function setWidth(int $width)
  162 + {
  163 + $this->prefix = 'w_' . $width;
  164 +
  165 + $this->action = self::ACTION_SET_WIDTH;
  166 +
  167 + $this->actionHeight = $width;
  168 +
  169 + return $this;
  170 + }
  171 +
  172 + protected function performSetWidth(int $width)
  173 + {
  174 + $height = round($this->height * $width / $this->width);
  175 +
  176 + $this->image = $this->image->thumbnail(new Box($width, $height));
  177 +
  178 + return $this;
  179 + }
  180 +
  181 + /**
  182 + * Resize to needed height, saving the proportion
  183 + *
  184 + * @param int $height
  185 + *
  186 + * @return $this
  187 + */
  188 + public function setHeight(int $height)
  189 + {
  190 + $this->prefix = 'h_' . $height;
  191 +
  192 + $this->action = self::ACTION_SET_HEIGHT;
  193 +
  194 + $this->actionHeight = $height;
  195 +
  196 + return $this;
  197 + }
  198 +
  199 + protected function performSetHeight(int $height)
  200 + {
  201 + $width = round($this->width * $height / $this->height);
  202 +
  203 + $this->image = $this->image->thumbnail(new Box($width, $height));
  204 +
  205 + return $this;
  206 + }
  207 +
  208 + /**
  209 + * First resize image by closest side, the crop out the rests
  210 + *
  211 + * @param int $width
  212 + * @param int $height
  213 + *
  214 + * @return $this
  215 + */
  216 + public function cropResize(int $width, int $height)
  217 + {
  218 + $this->prefix = 'cr_' . $width . '_x_' . $height;
  219 +
  220 + $this->action = self::ACTION_CROP_RESIZE;
  221 +
  222 + $this->actionHeight = $height;
  223 + $this->actionWidth = $width;
  224 +
  225 + return $this;
  226 + }
  227 +
  228 + protected function performCropResize(int $width, int $height)
  229 + {
  230 + if ($this->width / $this->height > $width / $height) {
  231 +
  232 + $this->image = $this->performSetHeight($height)->image;
  233 + $newWidth = $this->image->getSize()
  234 + ->getWidth();
  235 +
  236 + if ($newWidth - $width >= 0) {
  237 + $this->image = $this->image->crop(
  238 + new Point(round(( $newWidth - $width ) / 2), 0),
  239 + new Box($width, $height)
  240 + );
  241 + }
  242 + } else {
  243 + $this->image = $this->performSetWidth($width)->image;
  244 + $newHeight = $this->image->getSize()
  245 + ->getHeight();
  246 +
  247 + if ($newHeight - $height >= 0) {
  248 + $this->image = $this->image->crop(
  249 + new Point(0, round(( $newHeight - $height ) / 2)),
  250 + new Box($width, $height)
  251 + );
  252 + }
  253 + }
  254 +
  255 + return $this;
  256 + }
  257 +
  258 + /**
  259 + * Croup out needed box from the middle of image
  260 + *
  261 + * @param int $width
  262 + * @param int $height
  263 + *
  264 + * @return $this
  265 + */
  266 + public function crop(int $width, int $height)
  267 + {
  268 + $this->prefix = 'c_' . $width . '_x_' . $height;
  269 +
  270 + $this->action = self::ACTION_CROP;
  271 +
  272 + $this->actionWidth = $width;
  273 + $this->actionHeight = $height;
  274 +
  275 + return $this;
  276 + }
  277 +
  278 + protected function performCrop(int $width, int $height)
  279 + {
  280 + $this->image = $this->image->copy()
  281 + ->crop(
  282 + new Point(round($this->width - $width), round($this->height - $height)),
  283 + new Box($width, $height)
  284 + );
  285 +
  286 + return $this;
  287 + }
  288 +
  289 + /**
  290 + * Fits image in needed dimensions, empty area fiils with chosen color, default is white
  291 + *
  292 + * @param int $width
  293 + * @param int $height
  294 + * @param string $color
  295 + *
  296 + * @return $this
  297 + */
  298 + public function fillResize(int $width, int $height, string $color = '#FFFFFF')
  299 + {
  300 + $this->prefix = 'cf_' . $width . '_x_' . $height;
  301 +
  302 + $this->action = self::ACTION_FILL_RESIZE;
  303 +
  304 + $this->actionHeight = $height;
  305 + $this->actionWidth = $width;
  306 + $this->actionColor = $color;
  307 +
  308 + return $this;
  309 + }
  310 +
  311 + protected function performFillResize(int $width, int $height, string $color = '#FFFFFF')
  312 + {
  313 + $parent = Image::getImagine()
  314 + ->create(new Box($width, $height), ( new RGB() )->color($color));
  315 +
  316 + if ($this->width / $this->height > $width / $height) {
  317 + $this->performSetWidth($width);
  318 + $newHeight = $this->image->getSize()
  319 + ->getHeight();
  320 +
  321 + $this->image = $parent->paste(
  322 + $this->image,
  323 + new Point(
  324 + 0, round(
  325 + ( $height - $newHeight ) / 2
  326 + )
  327 + )
  328 + );
  329 +
  330 + } else {
  331 + $this->performSetHeight($height);
  332 + $newWidth = $this->image->getSize()
  333 + ->getWidth();
  334 +
  335 + $this->image = $parent->paste(
  336 + $this->image,
  337 + new Point(
  338 + round(
  339 + ( $width - $newWidth ) / 2
  340 + ), 0
  341 + )
  342 + );
  343 + }
  344 +
  345 + return $this;
  346 + }
  347 +
  348 + /**
  349 + * Resize image to needed size, without saving aspect ratio
  350 + *
  351 + * @param int $width
  352 + * @param int $height
  353 + *
  354 + * @return $this
  355 + */
  356 + public function strictResize(int $width, int $height)
  357 + {
  358 + $this->prefix = 'sr_' . $width . '_x_' . $height;
  359 +
  360 + $this->action = self::ACTION_STRICT_RESIZE;
  361 +
  362 + $this->actionWidth = $width;
  363 + $this->actionHeight = $height;
  364 +
  365 + return $this;
  366 + }
  367 +
  368 + protected function performStrictResize(int $width, int $height)
  369 + {
  370 + $this->image = $this->image->resize(new Box($width, $height));
  371 +
  372 + return $this;
  373 + }
  374 +
  375 + /**
  376 + * Sets the output image quality in percents, default is 100%
  377 + *
  378 + * @param int $quality
  379 + *
  380 + * @return $this
  381 + * @throws \yii\base\InvalidConfigException
  382 + */
  383 + public function quality(int $quality)
  384 + {
  385 + if ($quality <= 0 || $quality > 100) {
  386 + throw new InvalidConfigException('Wrong quality value');
  387 + }
  388 +
  389 + $this->qualityValue = $quality;
  390 +
  391 + $this->prefix .= '_q' . $quality;
  392 +
  393 + return $this;
  394 + }
  395 +
  396 + /**
  397 + * Save the image, and return path to it
  398 + *
  399 + * @return string
  400 + */
  401 + public function render()
  402 + {
  403 + $name = $this->name;
  404 + if (isset($this->prefix)) {
  405 + $name .= '_' . $this->prefix;
  406 + }
  407 + $path = \Yii::getAlias('@storage/helper/') . $name . '.' . $this->extension;
  408 + if (file_exists($path)) {
  409 + return '/storage/helper/' . $name . '.' . $this->extension;
  410 + }
  411 +
  412 + $this->performAction();
  413 +
  414 + $this->image->save(
  415 + $path,
  416 + [
  417 + 'quality' => $this->qualityValue,
  418 + ]
  419 + );
  420 +
  421 + unset($this->image);
  422 +
  423 + return '/storage/helper/' . $name . '.' . $this->extension;
  424 + }
  425 +
  426 + /**
  427 + * Save and return the image as html img string
  428 + *
  429 + * @param array $options
  430 + *
  431 + * @return string
  432 + */
  433 + public function renderImage(array $options = [])
  434 + {
  435 + return Html::img($this->render(), $options);
  436 + }
  437 +
  438 + protected function performAction()
  439 + {
  440 + $this->image = Image::getImagine()
  441 + ->open($this->fullPath);
  442 + $this->width = $this->image->getSize()
  443 + ->getWidth();
  444 + $this->height = $this->image->getSize()
  445 + ->getHeight();
  446 +
  447 + if ($this->action === self::ACTION_CROP) {
  448 + $this->performCrop($this->actionWidth, $this->actionHeight);
  449 + } elseif ($this->action === self::ACTION_STRICT_RESIZE) {
  450 + $this->performStrictResize($this->actionWidth, $this->actionHeight);
  451 + } elseif ($this->action === self::ACTION_CROP_RESIZE) {
  452 + $this->performCropResize($this->actionWidth, $this->actionHeight);
  453 + } elseif ($this->action === self::ACTION_FILL_RESIZE) {
  454 + $this->performFillResize($this->actionWidth, $this->actionHeight, $this->actionColor);
  455 + } elseif ($this->action === self::ACTION_RESIZE) {
  456 + $this->perfomResize($this->actionWidth, $this->actionHeight);
  457 + } elseif ($this->action === self::ACTION_SET_HEIGHT) {
  458 + $this->performSetHeight($this->actionHeight);
  459 + } elseif ($this->action === self::ACTION_SET_WIDTH) {
  460 + $this->performSetWidth($this->actionWidth);
  461 + }
  462 + }
  463 + }
0 464 \ No newline at end of file
... ...
artweb/artbox-core/helpers/SlugHelper.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\helpers;
  4 +
  5 + use artbox\core\models\Alias;
  6 + use artbox\core\models\Language;
  7 + use yii\helpers\Inflector;
  8 +
  9 + /**
  10 + * Class SlugHelper
  11 + * Class to work with slugs, transliteration and aliases
  12 + */
  13 + class SlugHelper
  14 + {
  15 + /**
  16 + * SlugHelper constructor. Private in order to restict instance creation.
  17 + */
  18 + private function __construct()
  19 + {
  20 + }
  21 +
  22 + /**
  23 + * Custom trasliteration rules.
  24 + *
  25 + * @param string $string string to translit
  26 + * @param string $setting all, letter, symbol possible variants
  27 + *
  28 + * @return string
  29 + */
  30 + static function translit(string $string, string $setting = 'all'): string
  31 + {
  32 + $letter = [
  33 +
  34 + 'а' => 'a',
  35 + 'б' => 'b',
  36 + 'в' => 'v',
  37 + 'г' => 'g',
  38 + 'д' => 'd',
  39 + 'е' => 'e',
  40 + 'ё' => 'e',
  41 + 'ж' => 'zh',
  42 + 'з' => 'z',
  43 + 'и' => 'i',
  44 + 'й' => 'y',
  45 + 'к' => 'k',
  46 + 'л' => 'l',
  47 + 'м' => 'm',
  48 + 'н' => 'n',
  49 + 'о' => 'o',
  50 + 'п' => 'p',
  51 + 'р' => 'r',
  52 + 'с' => 's',
  53 + 'т' => 't',
  54 + 'у' => 'u',
  55 + 'ф' => 'f',
  56 + 'х' => 'h',
  57 + 'ц' => 'c',
  58 + 'ч' => 'ch',
  59 + 'ш' => 'sh',
  60 + 'щ' => 'sch',
  61 + 'ь' => "",
  62 + 'ы' => 'y',
  63 + 'ъ' => "",
  64 + 'э' => 'e',
  65 + 'ю' => 'yu',
  66 + 'я' => 'ya',
  67 + 'ї' => 'yi',
  68 + 'є' => 'ye',
  69 + 'і' => 'ee',
  70 +
  71 + 'А' => 'A',
  72 + 'Б' => 'B',
  73 + 'В' => 'V',
  74 + 'Г' => 'G',
  75 + 'Д' => 'D',
  76 + 'Е' => 'E',
  77 + 'Ё' => 'E',
  78 + 'Ж' => 'Zh',
  79 + 'З' => 'Z',
  80 + 'И' => 'I',
  81 + 'Й' => 'Y',
  82 + 'К' => 'K',
  83 + 'Л' => 'L',
  84 + 'М' => 'M',
  85 + 'Н' => 'N',
  86 + 'О' => 'O',
  87 + 'П' => 'P',
  88 + 'Р' => 'R',
  89 + 'С' => 'S',
  90 + 'Т' => 'T',
  91 + 'У' => 'U',
  92 + 'Ф' => 'F',
  93 + 'Х' => 'H',
  94 + 'Ц' => 'C',
  95 + 'Ч' => 'Ch',
  96 + 'Ш' => 'Sh',
  97 + 'Щ' => 'Sch',
  98 + 'Ь' => "",
  99 + 'Ы' => 'Y',
  100 + 'Ъ' => "",
  101 + 'Э' => 'E',
  102 + 'Ю' => 'Yu',
  103 + 'Я' => 'Ya',
  104 + 'Ї' => 'Yi',
  105 + 'Є' => 'Ye',
  106 + 'І' => 'Ee',
  107 + ];
  108 +
  109 + $symbol = [
  110 + ' ' => '-',
  111 + "'" => '',
  112 + '"' => '',
  113 + '!' => '',
  114 + "@" => '',
  115 + '#' => '',
  116 + '$' => '',
  117 + "%" => '',
  118 + '^' => '',
  119 + ';' => '',
  120 + "*" => '',
  121 + '(' => '',
  122 + ')' => '',
  123 + "+" => '',
  124 + '~' => '',
  125 + '.' => '',
  126 + ',' => '-',
  127 + '?' => '',
  128 + '…' => '',
  129 + '№' => 'N',
  130 + '°' => '',
  131 + '`' => '',
  132 + '|' => '',
  133 + '&' => '-and-',
  134 + '<' => '',
  135 + '>' => '',
  136 + ];
  137 +
  138 + if ($setting == 'letter') {
  139 + $converter = $letter;
  140 + } else if ($setting == 'symbol') {
  141 + $converter = $symbol;
  142 + } else {
  143 + $converter = $letter + $symbol;
  144 + }
  145 +
  146 + $url = strtr($string, $converter);
  147 +
  148 + $url = str_replace("---", '-', $url);
  149 + $url = str_replace("--", '-', $url);
  150 +
  151 + return $url;
  152 + }
  153 +
  154 + /**
  155 + * Generate slug
  156 + *
  157 + * @param string $string string to translit
  158 + * @param bool $translit whether to use custom translit
  159 + * @param string $replacement
  160 + * @param bool $lowercase whether to lowercase result
  161 + *
  162 + * @see Inflector::slug()
  163 + * @return string
  164 + */
  165 + static function slugify(
  166 + string $string,
  167 + bool $translit = true,
  168 + string $replacement = '-',
  169 + bool $lowercase = true
  170 + ): string {
  171 + return Inflector::slug($translit ? SlugHelper::translit($string) : $string, $replacement, $lowercase);
  172 + }
  173 +
  174 + /**
  175 + * Get unique to alias table slug
  176 + *
  177 + * @param string $string string to translit
  178 + * @param \artbox\core\models\Alias $alias Current alias
  179 + * @param int|null $languageId
  180 + *
  181 + * @return string
  182 + */
  183 + static function unify(string $string, Alias $alias = null, int $languageId = null): string
  184 + {
  185 + $new_string = $string;
  186 + $suffix = 2;
  187 + while (!self::checkUnique($new_string, $alias, $languageId)) {
  188 + $new_string = $string . '-' . $suffix;
  189 + $suffix++;
  190 + }
  191 + return $new_string;
  192 + }
  193 +
  194 + /**
  195 + * Checks uniqueness of the slug
  196 + *
  197 + * @param string $string
  198 + * @param \artbox\core\models\Alias $alias
  199 + * @param int|null $languageId
  200 + *
  201 + * @return bool
  202 + */
  203 + private static function checkUnique(string $string, Alias $alias = null, int $languageId = null): bool
  204 + {
  205 + if (empty($languageId)) {
  206 + $languageId = Language::$current->id;
  207 + }
  208 + $query = Alias::find()
  209 + ->where(
  210 + [
  211 + 'value' => $string,
  212 + 'language_id' => $languageId,
  213 + ]
  214 + );
  215 + if (!empty($alias) && !$alias->isNewRecord) {
  216 + $query->andWhere(
  217 + [
  218 + 'not',
  219 + [ 'id' => $alias->id ],
  220 + ]
  221 + );
  222 + }
  223 + return !$query->exists();
  224 + }
  225 + }
  226 +
0 227 \ No newline at end of file
... ...
artweb/artbox-core/helpers/SlugifyDecorator.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\helpers;
  4 +
  5 + use yii\bootstrap\Html;
  6 + use yii\db\ActiveRecord;
  7 + use yii\helpers\Url;
  8 + use yii\widgets\ActiveField;
  9 +
  10 + /**
  11 + * Class SlugifyDecorator
  12 + * Decorator to add slugify button to the ActiveField
  13 + */
  14 + class SlugifyDecorator
  15 + {
  16 + /**
  17 + * ActiveField input template param
  18 + */
  19 + const INPUT_FIELD = '{input}';
  20 +
  21 + /**
  22 + * Decorate ActiveField input.
  23 + *
  24 + * @param \yii\widgets\ActiveField $field ActiveField to decorate
  25 + * @param array $url Url to get slug from
  26 + * @param \yii\widgets\ActiveField|null $attribute ActiveField to get value to slugify from
  27 + * @param bool $enableCancel Whether to generate Cancel button
  28 + * @param int|null $languageId
  29 + *
  30 + * @return \yii\widgets\ActiveField
  31 + */
  32 + public static function decorate(
  33 + ActiveField $field,
  34 + array $url = [ '/alias/slugify' ],
  35 + ActiveField $attribute = null,
  36 + bool $enableCancel = false,
  37 + int $languageId = null
  38 + ): ActiveField {
  39 + if (!$attribute) {
  40 + $attribute = $field;
  41 + }
  42 + $template = $field->template;
  43 + $input = self::INPUT_FIELD;
  44 + if (( $posBegin = strpos($template, $input) ) !== false) {
  45 + $posEnd = $posBegin + strlen($input);
  46 + $divBegin = Html::beginTag(
  47 + 'div',
  48 + [
  49 + 'class' => 'input-group',
  50 + ]
  51 + );
  52 + $divEnd = Html::tag(
  53 + 'span',
  54 + self::createButton(
  55 + $field,
  56 + $url,
  57 + $attribute,
  58 + $languageId
  59 + ) . ( $enableCancel ? self::createCancel(
  60 + $field
  61 + ) : '' ),
  62 + [
  63 + 'class' => 'input-group-btn',
  64 + ]
  65 + ) . Html::endTag('div');
  66 + $template = substr_replace($template, $divEnd, $posEnd, 0);
  67 + $template = substr_replace($template, $divBegin, $posBegin, 0);
  68 + $field->template = $template;
  69 + }
  70 + return $field;
  71 + }
  72 +
  73 + /**
  74 + * Create 'Slugify' button
  75 + *
  76 + * @param \yii\widgets\ActiveField $field
  77 + * @param array $url
  78 + * @param \yii\widgets\ActiveField $attribute
  79 + * @param int $languageId
  80 + *
  81 + * @return string
  82 + */
  83 + private static function createButton(
  84 + ActiveField $field,
  85 + array $url,
  86 + ActiveField $attribute,
  87 + int $languageId
  88 + ): string {
  89 + $options = [
  90 + 'data' => [
  91 + 'id' => Html::getInputId($field->model, $field->attribute),
  92 + 'attribute-id' => Html::getInputId($attribute->model, $attribute->attribute),
  93 + 'url' => Url::to($url),
  94 + 'language-id' => $languageId,
  95 + ],
  96 + 'class' => 'btn btn-info slugify_button',
  97 + ];
  98 + if ($field !== $attribute) {
  99 + $options[ 'data' ] = array_merge(
  100 + $options[ 'data' ],
  101 + [
  102 + 'toggle' => 'tooltip',
  103 + 'placement' => 'top',
  104 + 'original-title' => \Yii::t(
  105 + 'core',
  106 + 'Create slug from {field} field',
  107 + [
  108 + 'field' => $attribute->model->getAttributeLabel(
  109 + Html::getAttributeName($attribute->attribute)
  110 + ),
  111 + ]
  112 + ),
  113 + ]
  114 + );
  115 + }
  116 + return Html::button(
  117 + \Yii::t('core', 'Slugify'),
  118 + $options
  119 + );
  120 + }
  121 +
  122 + /**
  123 + * Create 'Cancel' button
  124 + *
  125 + * @param \yii\widgets\ActiveField $field
  126 + *
  127 + * @return string
  128 + */
  129 + private static function createCancel(
  130 + ActiveField $field
  131 + ): string {
  132 + /**
  133 + * @var ActiveRecord $model
  134 + */
  135 + $model = $field->model;
  136 + $options = [
  137 + 'data' => [
  138 + 'id' => Html::getInputId($model, $field->attribute),
  139 + 'value' => $model->getAttribute(Html::getAttributeName($field->attribute)),
  140 + ],
  141 + 'class' => 'btn btn-default slugify_cancel_button',
  142 + ];
  143 + return Html::button(
  144 + \Yii::t('core', 'Cancel'),
  145 + $options
  146 + );
  147 + }
  148 + }
  149 +
0 150 \ No newline at end of file
... ...
artweb/artbox-core/helpers/UnificatorHelper.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\helpers;
  4 +
  5 + class UnificatorHelper
  6 + {
  7 + /**
  8 + * Helper which returns unique value according to checker function
  9 + * Checker function must return boolean
  10 + *
  11 + * @param string $value
  12 + * @param callable $checker
  13 + *
  14 + * @return string
  15 + */
  16 + public static function unify(string $value, callable $checker): string
  17 + {
  18 + $baseVal = $value;
  19 + $index = 1;
  20 + do {
  21 + $result = call_user_func($checker, $value);
  22 + if (!$result) {
  23 + $value = $baseVal . ' ' . $index;
  24 + }
  25 + $index++;
  26 + } while (!$result);
  27 + return $value;
  28 + }
  29 + }
0 30 \ No newline at end of file
... ...
artweb/artbox-core/language_instruction.txt 0 → 100755
  1 +Как включить мультиязычность на сайте:
  2 +1. Запускаем миграцию: php yii migrate --migrationPath=common/modules/language/migrations
  3 +2. Добавляем в файл конфигурации:
  4 +'urlManager' => [
  5 + 'enablePrettyUrl' => true,
  6 + 'showScriptName' => false,
  7 + 'class'=>'artweb\artbox\language\components\LanguageUrlManager',
  8 + 'rules'=>[
  9 + '/' => 'site/index',
  10 + '<controller:\w+>/<action:\w+>/*'=>'<controller>/<action>',
  11 + ]
  12 +],
  13 +3. Добавляем в файл конфигурации:
  14 +'request' => [
  15 + 'class' => 'artweb\artbox\language\components\LanguageRequest'
  16 +],
  17 +4. Добавляем в файл конфигурации:
  18 +'language'=>'ru-RU',
  19 +'i18n' => [
  20 + 'translations' => [
  21 + '*' => [
  22 + 'class' => 'yii\i18n\PhpMessageSource',
  23 + 'basePath' => '@frontend/messages',
  24 + 'sourceLanguage' => 'en',
  25 + 'fileMap' => [
  26 + ],
  27 + ],
  28 + ],
  29 +],
  30 +5. Переводы писать в файл frontend\messages\{language}\app.php, где {language} - нужный язык, например ru.
  31 +6. Для вывода на странице сообщения с переводом используем функцию: Yii::t('app', {message}, $params = [], $language = null),
  32 + где {message} - нужное сообщение, $params - массив параметров, $language - нужный язык (по умолчанию используется текущий язык).
  33 +7. В наличие также виджет переключения языка: LanguagePicker::widget()
  34 +
  35 +
  36 +Как использовать мультиязычность для Active Record:
  37 +1. Создаем для таблицы {table} таблицу с языками {table_lang}.
  38 +2. Создаем для класса {Table} класс с языками {TableLang}.
  39 +3. Подключаеи для класса {Table} поведение LanguageBehavior:
  40 +public function behaviors() {
  41 + return [
  42 + 'language' => [
  43 + 'class' => LanguageBehavior::className(),
  44 + 'objectLang' => {TableLang}::className() // optional, default to {TableLang}::className()
  45 + 'ownerKey' => {Table}->id //optional, default to {Table}->primaryKey()[0]
  46 + 'langKey' => {TableLang}->table_id //optional, default to {Table}->tableName().'_id'
  47 + ],
  48 + ];
  49 +}
  50 +3.1. PHPDoc для {Table}:
  51 + * * From language behavior *
  52 + * @property {TableLang} $lang
  53 + * @property {TableLang}[] $langs
  54 + * @property {TableLang} $objectLang
  55 + * @property string $ownerKey
  56 + * @property string $langKey
  57 + * @property {TableLang}[] $modelLangs
  58 + * @property bool $transactionStatus
  59 + * @method string getOwnerKey()
  60 + * @method void setOwnerKey(string $value)
  61 + * @method string getLangKey()
  62 + * @method void setLangKey(string $value)
  63 + * @method ActiveQuery getLangs()
  64 + * @method ActiveQuery getLang( integer $language_id )
  65 + * @method {TableLang}[] generateLangs()
  66 + * @method void loadLangs(Request $request)
  67 + * @method bool linkLangs()
  68 + * @method bool saveLangs()
  69 + * @method bool getTransactionStatus()
  70 + * @method bool loadWithLangs( Request $request )
  71 + * @method bool saveWithLangs()
  72 + * * End language behavior *
  73 + * @see LanguageBehavior
  74 +3.2. Убрать language behavior с наследуемых таблиц от {Table} ({TableSearch}...)
  75 +4. Доступные полезные методы:
  76 + {Table}->getLangs() - получить все текущие {TableLang} для {Table} проиндексированные по language_id
  77 + {Table}->getLang($language_id = NULL) - получить {TableLang} для определенного языка (default: текущий язык) для {Table}
  78 + {Table}->generateLangs() - получить массив {TableLang} под каждый язык, включая существующие записи, для {Table}
  79 + {Table}->loadLangs($request) - заполнить массив {TableLang} данными с POST
  80 + {Table}->linkLangs() - связать каждый элемент массива {TableLang} с текущей {Table}
  81 + {Table}->saveLangs() - провалидировать и сохранить каждый элемент массива {TableLang}
  82 +5. Добавить поля в форму (к примеру через Bootstrap Tabs).
  83 + В наличии:
  84 + LanguageForm::widget([
  85 + 'modelLangs' => {TableLang}[],
  86 + 'formView' => string,
  87 + 'form' => ActiveForm,
  88 + ]);
  89 +6. Обрабатывать данные в контроллере.
  90 + 1. После создания/поиска {Table} создаем/находим языковые модели {Table}->generateLangs()
  91 + 2. При POST запросе загружаем данные в языковые модели {Table}->loadWithLangs(Request $request)
  92 + 3. Для сохранения используем метод {Table}->saveWithLangs(). Он вернет true если сохранение модели и всех языковых моделей прошло успешно.
  93 +7. Получать данные на публичной части сайта через {Table}->lang.
... ...
artweb/artbox-core/messages/en/core.php 0 → 100755
  1 +<?php
  2 + return [
  3 + ];
0 4 \ No newline at end of file
... ...
artweb/artbox-core/messages/ru/core.php 0 → 100755
  1 +<?php
  2 + return [
  3 + 'My website' => 'Мой вебсайт',
  4 + 'Main' => 'Главная',
  5 + 'Static pages' => 'Статические страницы',
  6 + 'SEO' => 'SEO',
  7 + 'Seo pages' => 'Seo страницы',
  8 + 'Robots' => 'Роботы',
  9 + 'Codes' => 'Коды',
  10 + 'Sitemap' => 'Карта сайта',
  11 + 'Welcome,' => 'Добро пожаловать,',
  12 + 'Change name' => 'Изменить имя',
  13 + 'Change image' => 'Изменить изображение',
  14 + 'Google Analytics Key' => 'Ключ Google аналитики',
  15 + 'Google analytics code' => 'Код Google аналитики',
  16 + 'Yandex metrics code' => 'Код Яндекс метрики',
  17 + 'Tag Manager code' => 'Код Tag Manager',
  18 + 'Phone' => 'Телефон',
  19 + 'Additional phone' => 'Дополнительный телефон',
  20 + 'Skype' => 'Skype',
  21 + 'Company name' => 'Название компании',
  22 + 'Email' => 'Email',
  23 + 'House' => 'Дом',
  24 + 'Street' => 'Улица',
  25 + 'Office' => 'Офис',
  26 + 'City' => 'Город',
  27 + 'Country' => 'Страна',
  28 + 'Latitude' => 'Широта',
  29 + 'Longitude' => 'Долгота',
  30 + 'Facebook' => 'Facebook',
  31 + 'VK' => 'VK',
  32 + 'Google' => 'Google',
  33 + 'Twitter' => 'Твиттер',
  34 + 'Company logo' => 'Логотип компании',
  35 + 'About us' => 'О нас',
  36 + 'Odnoklassniki' => 'Одноклассники',
  37 + 'ID' => 'ID',
  38 + 'Model' => 'Модель',
  39 + 'Status' => 'Статус',
  40 + 'Priority' => 'Приоритет',
  41 + 'Frequency' => 'Частота',
  42 + 'Url' => 'Url',
  43 + 'Contact phone for website' => 'Контактный телефон для сайта',
  44 + 'Contact email for website' => 'Контактный email для сайта',
  45 + 'Save' => 'Сохранить',
  46 + 'Social' => 'Соц. сети',
  47 + 'Contact' => 'Контактная информация',
  48 + 'Feedbacks' => 'Обратная связь',
  49 + 'Create Feedback' => 'Написать отзыв',
  50 + 'Pages' => 'Страницы',
  51 + 'Settings saved' => 'Настройки сохранены',
  52 + 'Robots saved' => 'Роботы сохранены',
  53 + 'Codes saved successfully' => 'Коды успешно сохранены',
  54 + 'Update sitemap' => 'Обновить карту сайта',
  55 + 'Dynamic pages' => 'Динамические страницы',
  56 + 'Save and generate' => 'Сохранить и сгенерировать',
  57 + 'Add field' => 'Добавить поле',
  58 + 'Title' => 'Заголовок',
  59 + 'Aliases' => "Псевдонимы",
  60 + 'Create {item}' => 'Создать {item}',
  61 + 'Value' => 'Значение',
  62 + 'Route' => 'Путь',
  63 + 'Search' => 'Поиск',
  64 + 'View generated sitemap.xml' => 'Посмотреть сгенерированный sitemap.xml',
  65 + 'Generate' => 'Сгенерировать',
  66 + 'Edit' => 'Редактировать',
  67 + 'Use in menu' => 'Отображение в меню',
  68 + 'Sort' => 'Сортировка',
  69 + "Doesn't look like robots" => 'Не похоже на робота',
  70 + 'Meta robots' => 'Meta роботы',
  71 + 'H1' => 'H1',
  72 + 'Description' => 'Описание',
  73 + 'Seo text' => 'Seo текст',
  74 + 'Entity' => 'Entity',
  75 + 'Available fields' => 'Доступные поля',
  76 + 'Language' => 'Язык',
  77 + 'Old password' => 'Старый пароль',
  78 + 'New password' => 'Новый пароль',
  79 + 'New password repeat' => 'Повторите новый пароль',
  80 + 'Provided old password doesn\'t match real password.' => 'При условии, что старый пароль не соответствует нынешнему.',
  81 + 'id' => 'ID',
  82 + 'name' => 'Имя',
  83 + 'phone' => 'Телефон',
  84 + 'created_at' => 'Создано',
  85 + 'ip' => 'IP',
  86 + 'url' => 'Url',
  87 + 'status' => 'Статус',
  88 + 'message' => 'Сообщение',
  89 + 'email' => 'Email',
  90 + 'Language ID' => 'ID языка',
  91 + 'Local' => 'Локально',
  92 + 'Name' => 'Имя',
  93 + 'Default' => 'По-умолчанию',
  94 + 'Date Create' => 'Дата создания',
  95 + 'Date Update' => 'Дата обновления',
  96 + 'The combination of Page ID and Language ID has already been taken.' => 'Комбинация из ID страницы и ID языка уже имеется.',
  97 + 'page_id' => 'ID страницы',
  98 + 'language_id' => 'ID языка',
  99 + 'Body' => 'Тело',
  100 + 'Alias' => 'псевдоним',
  101 + 'Mr.' => 'Г-н.',
  102 + 'Anonymous' => 'Аноним',
  103 + 'User ID' => 'ID пользователя',
  104 + 'Surname' => 'Фамилия',
  105 + 'Image' => 'Изображение',
  106 + 'Created At' => 'Создано',
  107 + 'Updated At' => 'Обновлено',
  108 + 'Visited At' => 'Последнее посещение',
  109 + 'Page' => 'страницу',
  110 + 'page_title' => 'Заголовок',
  111 + 'page_in_menu' => 'Отображение в меню',
  112 + 'page_sort' => 'Сортировка',
  113 + 'Create slug from {field} field' => 'Сгенерировать псевдоним из поля "{field}"',
  114 + 'Slugify' => 'Сгенерировать',
  115 + 'Create' => 'Создать',
  116 + 'Creating aliases by hand may cause bugs for your website. Use it only if you know what are you doing!' => 'Собственноручное создание псевдонимов может отразиться на работе вашего сайта. Используйте это, если вы действительно понимаете что делаете!',
  117 + 'Notification' => 'Оповещение',
  118 + 'Alias Value' => 'Значение псевдонима',
  119 + 'Update Category' => 'Обновить категорию',
  120 + 'Brand Title' => 'Заголовок бренда',
  121 + 'Upload Document' => 'Загрузить документ',
  122 + 'Send' => 'Отправить',
  123 + 'Common' => 'Общее',
  124 + 'Options' => 'Опции',
  125 + 'Gallery' => 'Галерея',
  126 + 'Add' => 'Добавить',
  127 + 'Product option group complementary' => 'Дополнительные группы опций товара',
  128 + 'Is Filter' => 'Является фильтром',
  129 + 'Search for a categories ...' => 'Поиск категорий ..',
  130 + 'Product option group exclude' => 'Исключения группы опций товара',
  131 + 'Variant option group exclude' => 'Исключения группы варианта товара',
  132 + 'Option Groups' => 'Группы опций',
  133 + 'Image Id' => 'ID изображения',
  134 + 'Body Preview' => 'Предпросмотр',
  135 + 'Author ID' => 'ID автора',
  136 + 'Parent ID' => 'Родительский ID',
  137 + 'Count' => 'Количество',
  138 +
  139 + ];
0 140 \ No newline at end of file
... ...
artweb/artbox-core/migrations/m170309_000000_user.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170309_000000_user extends Migration
  6 + {
  7 + public function safeUp()
  8 + {
  9 + $tableOptions = null;
  10 + if ($this->db->driverName === 'mysql') {
  11 + // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
  12 + $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
  13 + }
  14 +
  15 + $this->createTable(
  16 + 'user',
  17 + [
  18 + 'id' => $this->primaryKey(),
  19 + 'username' => $this->string()
  20 + ->notNull()
  21 + ->unique(),
  22 + 'auth_key' => $this->string(32)
  23 + ->notNull(),
  24 + 'password_hash' => $this->string()
  25 + ->notNull(),
  26 + 'password_reset_token' => $this->string()
  27 + ->unique(),
  28 + 'email' => $this->string()
  29 + ->notNull()
  30 + ->unique(),
  31 +
  32 + 'status' => $this->smallInteger()
  33 + ->notNull()
  34 + ->defaultValue(10),
  35 + 'created_at' => $this->integer()
  36 + ->notNull(),
  37 + 'updated_at' => $this->integer()
  38 + ->notNull(),
  39 + ],
  40 + $tableOptions
  41 + );
  42 + }
  43 +
  44 + public function safeDown()
  45 + {
  46 + $this->dropTable('user');
  47 + }
  48 + }
... ...
artweb/artbox-core/migrations/m170309_000001_feedback.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170309_000001_feedback extends Migration
  6 + {
  7 + public function safeUp()
  8 + {
  9 + $this->createTable(
  10 + 'feedback',
  11 + [
  12 + 'id' => $this->primaryKey(),
  13 + 'name' => $this->string(255),
  14 + 'email' => $this->string(255),
  15 + 'phone' => $this->string(255),
  16 + 'message' => $this->text(),
  17 + 'created_at' => $this->integer(32),
  18 + 'ip' => $this->string(255),
  19 + 'url' => $this->string(255),
  20 + 'status' => $this->boolean()
  21 + ->notNull()
  22 + ->defaultValue(false),
  23 + ]
  24 + );
  25 + }
  26 +
  27 + public function safeDown()
  28 + {
  29 + $this->dropTable('feedback');
  30 + }
  31 + }
... ...
artweb/artbox-core/migrations/m170309_000002_language.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170309_000002_language extends Migration
  6 + {
  7 + public function safeUp()
  8 + {
  9 + $this->createTable(
  10 + 'language',
  11 + [
  12 + 'id' => $this->primaryKey(),
  13 + 'url' => $this->string(255)
  14 + ->notNull(),
  15 + 'local' => $this->string(255)
  16 + ->notNull(),
  17 + 'name' => $this->string(255)
  18 + ->notNull(),
  19 + 'default' => $this->boolean()
  20 + ->notNull()
  21 + ->defaultValue(false),
  22 + 'created_at' => $this->integer(32)
  23 + ->notNull(),
  24 + 'updated_at' => $this->integer(32)
  25 + ->notNull(),
  26 + 'status' => $this->boolean()
  27 + ->notNull()
  28 + ->defaultValue(false),
  29 + ]
  30 + );
  31 +
  32 + $this->batchInsert(
  33 + 'language',
  34 + [
  35 + 'url',
  36 + 'local',
  37 + 'name',
  38 + 'default',
  39 + 'created_at',
  40 + 'updated_at',
  41 + 'status',
  42 + ],
  43 + [
  44 + [
  45 + 'en',
  46 + 'en-EN',
  47 + 'English',
  48 + true,
  49 + 0,
  50 + 0,
  51 + true,
  52 + ],
  53 + [
  54 + 'ru',
  55 + 'ru-RU',
  56 + 'Русский',
  57 + false,
  58 + 0,
  59 + 0,
  60 + true,
  61 + ],
  62 + [
  63 + 'ua',
  64 + 'ua-UA',
  65 + 'Українська',
  66 + false,
  67 + 0,
  68 + 0,
  69 + false,
  70 + ],
  71 + ]
  72 + );
  73 + }
  74 +
  75 + public function safeDown()
  76 + {
  77 + $this->dropTable('language');
  78 + }
  79 + }
... ...
artweb/artbox-core/migrations/m170309_000003_alias.php 0 → 100755
  1 +<?php
  2 +
  3 +use yii\db\Migration;
  4 +
  5 +class m170309_000003_alias extends Migration
  6 +{
  7 + public function safeUp()
  8 + {
  9 + $this->createTable(
  10 + 'alias',
  11 + [
  12 + 'id'=> $this->primaryKey(),
  13 + 'value'=> $this->string()->notNull(),
  14 + ]
  15 + );
  16 + }
  17 +
  18 + public function safeDown()
  19 + {
  20 + $this->dropTable('alias');
  21 + }
  22 +}
... ...
artweb/artbox-core/migrations/m170309_000004_page.php 0 → 100755
  1 +<?php
  2 +
  3 +use yii\db\Migration;
  4 +
  5 +class m170309_000004_page extends Migration
  6 +{
  7 + public function safeUp()
  8 + {
  9 + $this->createTable(
  10 + 'page',
  11 + [
  12 + 'id'=> $this->primaryKey(),
  13 + 'in_menu'=> $this->boolean()->notNull()->defaultValue(false),
  14 + ]
  15 + );
  16 + }
  17 +
  18 + public function safeDown()
  19 + {
  20 + $this->dropTable('page');
  21 + }
  22 +}
... ...
artweb/artbox-core/migrations/m170309_000005_page_lang.php 0 → 100755
  1 +<?php
  2 +
  3 +use yii\db\Migration;
  4 +
  5 +class m170309_000005_page_lang extends Migration
  6 +{
  7 + public function safeUp()
  8 + {
  9 + $this->createTable(
  10 + 'page_lang',
  11 + [
  12 + 'page_id'=> $this->integer(32)->notNull(),
  13 + 'language_id'=> $this->integer(32)->notNull(),
  14 + 'title'=> $this->string(255)->notNull(),
  15 + 'body'=> $this->text()->notNull(),
  16 + 'meta_title'=> $this->string(255)->null()->defaultValue(null),
  17 + 'meta_description'=> $this->string(255)->null()->defaultValue(null),
  18 + 'seo_text'=> $this->text()->null()->defaultValue(null),
  19 + 'h1'=> $this->string(255)->null()->defaultValue(null),
  20 + 'alias_id'=> $this->integer()->notNull(),
  21 + 'PRIMARY KEY(page_id, language_id)',
  22 + ]
  23 + );
  24 + $this->createIndex('page_lang_alias_id','page_lang','alias_id',true);
  25 + }
  26 +
  27 + public function safeDown()
  28 + {
  29 + $this->dropIndex('page_lang_alias_id', 'page_lang');
  30 + $this->dropTable('page_lang');
  31 + }
  32 +}
... ...
artweb/artbox-core/migrations/m170309_000006_relations.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170309_000006_relations extends Migration
  6 + {
  7 + public function safeUp()
  8 + {
  9 + $this->addForeignKey(
  10 + 'fk_page_lang_alias_id',
  11 + 'page_lang',
  12 + 'alias_id',
  13 + 'alias',
  14 + 'id',
  15 + 'RESTRICT',
  16 + 'CASCADE'
  17 + );
  18 + $this->addForeignKey(
  19 + 'fk_page_lang_language_id',
  20 + 'page_lang',
  21 + 'language_id',
  22 + 'language',
  23 + 'id',
  24 + 'CASCADE',
  25 + 'CASCADE'
  26 + );
  27 + $this->addForeignKey(
  28 + 'fk_page_lang_page_id',
  29 + 'page_lang',
  30 + 'page_id',
  31 + 'page',
  32 + 'id',
  33 + 'CASCADE',
  34 + 'CASCADE'
  35 + );
  36 + }
  37 +
  38 + public function safeDown()
  39 + {
  40 + $this->dropForeignKey('fk_page_lang_alias_id', 'page_lang');
  41 + $this->dropForeignKey('fk_page_lang_language_id', 'page_lang');
  42 + $this->dropForeignKey('fk_page_lang_page_id', 'page_lang');
  43 + }
  44 + }
... ...
artweb/artbox-core/migrations/m170313_092544_create_user_data_table.php 0 → 100755
  1 +<?php
  2 +
  3 +use yii\db\Migration;
  4 +
  5 +/**
  6 + * Handles the creation of table `user_data`.
  7 + */
  8 +class m170313_092544_create_user_data_table extends Migration
  9 +{
  10 + /**
  11 + * @inheritdoc
  12 + */
  13 + public function safeUp()
  14 + {
  15 + $this->createTable('user_data', [
  16 + 'user_id' => $this->integer()->notNull(),
  17 + 'name' => $this->string(),
  18 + 'surname' => $this->string(),
  19 + 'image' => $this->string(),
  20 + 'email' => $this->string(),
  21 + 'phone' => $this->string(),
  22 + 'created_at' => $this->integer(),
  23 + 'updated_at' => $this->integer(),
  24 + 'visited_at' => $this->integer(),
  25 + ]);
  26 +
  27 + $this->addForeignKey('user_data_to_user', 'user_data', 'user_id', 'user', 'id', 'CASCADE', 'CASCADE');
  28 + $this->createIndex('user_id_uk', 'user_data', 'user_id', true);
  29 + }
  30 +
  31 + /**
  32 + * @inheritdoc
  33 + */
  34 + public function safeDown()
  35 + {
  36 + $this->dropTable('user_data');
  37 + }
  38 +}
... ...
artweb/artbox-core/migrations/m170316_103134_page_lang_drop_not_null.php 0 → 100755
  1 +<?php
  2 +
  3 + use artbox\core\models\PageLang;
  4 + use yii\db\Migration;
  5 +
  6 + class m170316_103134_page_lang_drop_not_null extends Migration
  7 + {
  8 + public function safeUp()
  9 + {
  10 + $this->dropForeignKey(
  11 + 'fk_page_lang_alias_id',
  12 + 'page_lang'
  13 + );
  14 + $this->execute("ALTER TABLE public.page_lang ALTER COLUMN alias_id DROP NOT NULL");
  15 + $this->addForeignKey(
  16 + 'fk_page_lang_alias_id',
  17 + 'page_lang',
  18 + 'alias_id',
  19 + 'alias',
  20 + 'id',
  21 + 'SET NULL',
  22 + 'CASCADE'
  23 + );
  24 + }
  25 +
  26 + public function safeDown()
  27 + {
  28 + PageLang::deleteAll(
  29 + [
  30 + 'alias_id' => null,
  31 + ]
  32 + );
  33 + $this->dropForeignKey(
  34 + 'fk_page_lang_alias_id',
  35 + 'page_lang'
  36 + );
  37 + $this->addForeignKey(
  38 + 'fk_page_lang_alias_id',
  39 + 'page_lang',
  40 + 'alias_id',
  41 + 'alias',
  42 + 'id',
  43 + 'RESTRICT',
  44 + 'CASCADE'
  45 + );
  46 + $this->execute("ALTER TABLE public.page_lang ALTER COLUMN alias_id SET NOT NULL");
  47 + }
  48 + }
... ...
artweb/artbox-core/migrations/m170316_180155_alias_seo_fields.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170316_180155_alias_seo_fields extends Migration
  6 + {
  7 + public function safeUp()
  8 + {
  9 + $this->addColumn('alias', 'route', $this->string());
  10 + $this->addColumn('alias', 'title', $this->string());
  11 + $this->addColumn('alias', 'description', $this->text());
  12 + $this->addColumn('alias', 'h1', $this->string());
  13 + $this->addColumn('alias', 'robots', $this->string());
  14 + $this->addColumn('alias', 'seo_text', $this->text());
  15 + }
  16 +
  17 + public function safeDown()
  18 + {
  19 + $this->dropColumn('alias', 'route');
  20 + $this->dropColumn('alias', 'title');
  21 + $this->dropColumn('alias', 'description');
  22 + $this->dropColumn('alias', 'h1');
  23 + $this->dropColumn('alias', 'robots');
  24 + $this->dropColumn('alias', 'seo_text');
  25 + }
  26 + }
... ...
artweb/artbox-core/migrations/m170316_181841_page_lang_remove_seo_fields.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170316_181841_page_lang_remove_seo_fields extends Migration
  6 + {
  7 + public function safeUp()
  8 + {
  9 + $this->dropColumn('page_lang', 'meta_title');
  10 + $this->dropColumn('page_lang', 'meta_description');
  11 + $this->dropColumn('page_lang', 'seo_text');
  12 + $this->dropColumn('page_lang', 'h1');
  13 + }
  14 +
  15 + public function safeDown()
  16 + {
  17 + $this->addColumn('page_lang', 'meta_title', $this->string());
  18 + $this->addColumn('page_lang', 'meta_description', $this->string());
  19 + $this->addColumn('page_lang', 'seo_text', $this->text());
  20 + $this->addColumn('page_lang', 'h1', $this->string());
  21 + }
  22 + }
... ...
artweb/artbox-core/migrations/m170317_104310_alias_add_entity_column.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170317_104310_alias_add_entity_column extends Migration
  6 + {
  7 + public function safeUp()
  8 + {
  9 + $this->addColumn('alias', 'entity', $this->string());
  10 + }
  11 +
  12 + public function safeDown()
  13 + {
  14 + $this->dropColumn('alias', 'entity');
  15 + }
  16 + }
... ...
artweb/artbox-core/migrations/m170317_155203_alias_add_fields_column.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170317_155203_alias_add_fields_column extends Migration
  6 + {
  7 + public function safeUp()
  8 + {
  9 + $this->addColumn('alias', 'fields', $this->text());
  10 + }
  11 +
  12 + public function safeDown()
  13 + {
  14 + $this->dropColumn('alias', 'fields');
  15 + }
  16 + }
0 17 \ No newline at end of file
... ...
artweb/artbox-core/migrations/m170317_155204_create_ImageManager_table.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + /**
  6 + * Handles the creation for table `ImageManager`.
  7 + */
  8 + class m170317_155204_create_ImageManager_table extends Migration
  9 + {
  10 + /**
  11 + * @inheritdoc
  12 + */
  13 + public function safeUp()
  14 + {
  15 + $this->createTable(
  16 + 'ImageManager',
  17 + [
  18 + 'id' => $this->primaryKey(),
  19 + 'fileName' => $this->string(128)
  20 + ->notNull(),
  21 + 'fileHash' => $this->string(32)
  22 + ->notNull(),
  23 + 'created' => $this->dateTime()
  24 + ->notNull(),
  25 + 'modified' => $this->dateTime(),
  26 + ]
  27 + );
  28 + }
  29 +
  30 + /**
  31 + * @inheritdoc
  32 + */
  33 + public function safeDown()
  34 + {
  35 + $this->dropTable('ImageManager');
  36 + }
  37 + }
0 38 \ No newline at end of file
... ...
artweb/artbox-core/migrations/m170317_155205_addBlameableBehavior.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170317_155205_addBlameableBehavior extends Migration
  6 + {
  7 + public function safeUp()
  8 + {
  9 + $this->addColumn(
  10 + 'ImageManager',
  11 + 'createdBy',
  12 + $this->integer(10)
  13 + ->unsigned()
  14 + ->null()
  15 + ->defaultValue(null)
  16 + );
  17 + $this->addColumn(
  18 + 'ImageManager',
  19 + 'modifiedBy',
  20 + $this->integer(10)
  21 + ->unsigned()
  22 + ->null()
  23 + ->defaultValue(null)
  24 + );
  25 + }
  26 +
  27 + public function safeDown()
  28 + {
  29 + $this->dropColumn('ImageManager', 'createdBy');
  30 + $this->dropColumn('ImageManager', 'modifiedBy');
  31 + }
  32 + }
... ...
artweb/artbox-core/migrations/m170327_134400_alias_add_language_column.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170327_134400_alias_add_language_column extends Migration
  6 + {
  7 + public function safeUp()
  8 + {
  9 + $this->addColumn('alias', 'language_id', $this->integer());
  10 + $this->addForeignKey('alias_to_language', 'alias', 'language_id', 'language', 'id', 'SET NULL', 'CASCADE');
  11 + }
  12 +
  13 + public function safeDown()
  14 + {
  15 + $this->dropForeignKey('alias_to_language', 'alias');
  16 + $this->dropColumn('alias', 'language_id');
  17 + }
  18 + }
... ...
artweb/artbox-core/migrations/m170405_095957_page_add_column_sort.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170405_095957_page_add_column_sort extends Migration
  6 + {
  7 + public function safeUp()
  8 + {
  9 + $this->addColumn(
  10 + 'page',
  11 + 'sort',
  12 + $this->integer()
  13 + ->defaultValue(0)
  14 + );
  15 + }
  16 +
  17 + public function safeDown()
  18 + {
  19 + $this->dropColumn('page', 'sort');
  20 + }
  21 + }
... ...
artweb/artbox-core/migrations/m170502_151419_insert_aliases.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m170502_151419_insert_aliases extends Migration
  6 + {
  7 + public function safeUp()
  8 + {
  9 + $this->batchInsert(
  10 + 'alias',
  11 + [
  12 + 'value',
  13 + 'route',
  14 + 'title',
  15 + 'description',
  16 + 'h1',
  17 + 'language_id',
  18 + ],
  19 + [
  20 + [
  21 + 'home',
  22 + '{"0":"site/index"}',
  23 + 'Home page title',
  24 + 'Home page description',
  25 + 'Home page header',
  26 + 1,
  27 + ],
  28 + [
  29 + 'domashnyaya',
  30 + '{"0":"site/index"}',
  31 + 'Домашняя страница',
  32 + 'Описание домашней страницы',
  33 + 'Заголовок домашней страницы',
  34 + 2,
  35 + ],
  36 + [
  37 + 'domashnya',
  38 + '{"0":"site/index"}',
  39 + 'Домашня сторінка',
  40 + 'Опис домашньої сторінки',
  41 + 'Заголовок домашньої сторінки',
  42 + 3,
  43 + ],
  44 + ]
  45 + );
  46 + }
  47 +
  48 + public function safeDown()
  49 + {
  50 +
  51 + }
  52 + }
... ...
artweb/artbox-core/migrations/m170619_095632_create_ImageManagerLang_table.php 0 → 100755
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + /**
  6 + * Handles the creation of table `ImageManagerLang`.
  7 + */
  8 + class m170619_095632_create_ImageManagerLang_table extends Migration
  9 + {
  10 + /**
  11 + * @inheritdoc
  12 + */
  13 + public function up()
  14 + {
  15 + $this->createTable(
  16 + 'ImageManagerLang',
  17 + [
  18 + 'image_id' => $this->integer(),
  19 + 'language_id' => $this->integer(),
  20 + 'title' => $this->string(),
  21 + 'alt' => $this->string(),
  22 + 'description' => $this->string(),
  23 + ]
  24 + );
  25 +
  26 + $this->addForeignKey(
  27 + 'image_fk',
  28 + 'ImageManagerLang',
  29 + 'image_id',
  30 + 'ImageManager',
  31 + 'id',
  32 + 'CASCADE',
  33 + 'CASCADE'
  34 + );
  35 +
  36 + $this->addForeignKey(
  37 + 'language_fk',
  38 + 'ImageManagerLang',
  39 + 'language_id',
  40 + 'language',
  41 + 'id',
  42 + 'CASCADE',
  43 + 'CASCADE'
  44 + );
  45 +
  46 + $this->createIndex(
  47 + 'img_lang_uk',
  48 + 'ImageManagerLang',
  49 + [
  50 + 'language_id',
  51 + 'image_id',
  52 + ],
  53 + true
  54 + );
  55 + }
  56 +
  57 + /**
  58 + * @inheritdoc
  59 + */
  60 + public function down()
  61 + {
  62 + $this->dropTable('ImageManagerLang');
  63 + }
  64 + }
... ...
artweb/artbox-core/migrations/m170717_142042_add_gallery_column_to_page_table.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\db\Migration;
  4 +
  5 +/**
  6 + * Handles adding gallery to table `page`.
  7 + */
  8 +class m170717_142042_add_gallery_column_to_page_table extends Migration
  9 +{
  10 + /**
  11 + * @inheritdoc
  12 + */
  13 + public function up()
  14 + {
  15 + $this->addColumn('page', 'gallery', $this->string());
  16 + }
  17 +
  18 + /**
  19 + * @inheritdoc
  20 + */
  21 + public function down()
  22 + {
  23 + $this->dropColumn('page', 'gallery');
  24 + }
  25 +}
... ...
artweb/artbox-core/migrations/m170718_134346_create_page_category_table.php 0 → 100644
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + /**
  6 + * Handles the creation of table `page_category`.
  7 + */
  8 + class m170718_134346_create_page_category_table extends Migration
  9 + {
  10 + /**
  11 + * @inheritdoc
  12 + */
  13 + public function up()
  14 + {
  15 + $this->createTable(
  16 + 'page_category',
  17 + [
  18 + 'id' => $this->primaryKey(),
  19 + 'sort' => $this->integer(),
  20 + 'status' => $this->boolean(),
  21 + ]
  22 + );
  23 + }
  24 +
  25 + /**
  26 + * @inheritdoc
  27 + */
  28 + public function down()
  29 + {
  30 + $this->dropTable('page_category');
  31 + }
  32 + }
... ...
artweb/artbox-core/migrations/m170718_134355_create_page_category_lang_table.php 0 → 100644
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + /**
  6 + * Handles the creation of table `page_category_lang`.
  7 + */
  8 + class m170718_134355_create_page_category_lang_table extends Migration
  9 + {
  10 + /**
  11 + * @inheritdoc
  12 + */
  13 + public function up()
  14 + {
  15 + $this->createTable(
  16 + 'page_category_lang',
  17 + [
  18 + 'title' => $this->string(),
  19 + 'language_id' => $this->integer(),
  20 + 'page_category_id' => $this->integer(),
  21 + ]
  22 + );
  23 +
  24 + $this->addForeignKey(
  25 + 'lang_fk',
  26 + 'page_category_lang',
  27 + 'language_id',
  28 + 'language',
  29 + 'id',
  30 + 'CASCADE',
  31 + 'CASCADE'
  32 + );
  33 +
  34 + $this->addForeignKey(
  35 + 'category_fk',
  36 + 'page_category_lang',
  37 + 'page_category_id',
  38 + 'page_category',
  39 + 'id',
  40 + 'CASCADE',
  41 + 'CASCADE'
  42 + );
  43 +
  44 + $this->createIndex(
  45 + 'pcat_lang_uk',
  46 + 'page_category_lang',
  47 + [
  48 + 'language_id',
  49 + 'page_category_id',
  50 + ],
  51 + true
  52 + );
  53 + }
  54 +
  55 + /**
  56 + * @inheritdoc
  57 + */
  58 + public function down()
  59 + {
  60 + $this->dropIndex(
  61 + 'pcat_lang_uk',
  62 + 'page_category_lang'
  63 + );
  64 +
  65 + $this->dropForeignKey(
  66 + 'category_fk',
  67 + 'page_category_lang'
  68 + );
  69 +
  70 + $this->dropForeignKey(
  71 + 'lang_fk',
  72 + 'page_category_lang'
  73 + );
  74 +
  75 + $this->dropTable('page_category_lang');
  76 + }
  77 + }
... ...
artweb/artbox-core/migrations/m170718_155356_create_page_to_category_table.php 0 → 100644
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + /**
  6 + * Handles the creation of table `page_to_category`.
  7 + */
  8 + class m170718_155356_create_page_to_category_table extends Migration
  9 + {
  10 + /**
  11 + * @inheritdoc
  12 + */
  13 + public function up()
  14 + {
  15 + $this->createTable(
  16 + 'page_to_category',
  17 + [
  18 + 'page_id' => $this->integer(),
  19 + 'category_id' => $this->integer(),
  20 + ]
  21 + );
  22 +
  23 + $this->addForeignKey('page_fk', 'page_to_category', 'page_id', 'page', 'id', 'CASCADE', 'CASCADE');
  24 +
  25 + $this->addForeignKey(
  26 + 'cat_fk',
  27 + 'page_to_category',
  28 + 'category_id',
  29 + 'page_category',
  30 + 'id',
  31 + 'CASCADE',
  32 + 'CASCADE'
  33 + );
  34 +
  35 + $this->createIndex(
  36 + 'page_cat_uk',
  37 + 'page_to_category',
  38 + [
  39 + 'page_id',
  40 + 'category_id',
  41 + ],
  42 + true
  43 + );
  44 + }
  45 +
  46 + /**
  47 + * @inheritdoc
  48 + */
  49 + public function down()
  50 + {
  51 + $this->dropIndex(
  52 + 'page_cat_uk',
  53 + 'page_to_category'
  54 + );
  55 +
  56 + $this->dropForeignKey(
  57 + 'cat_fk',
  58 + 'page_to_category'
  59 + );
  60 + $this->dropForeignKey('page_fk', 'page_to_category');
  61 +
  62 + $this->dropTable('page_to_category');
  63 + }
  64 + }
... ...
artweb/artbox-core/models/Alias.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\models;
  4 +
  5 + use artbox\core\helpers\SlugHelper;
  6 + use artbox\core\models\interfaces\AliasInterface;
  7 + use Yii;
  8 + use yii\base\InvalidParamException;
  9 + use yii\db\ActiveRecord;
  10 + use yii\helpers\Json;
  11 +
  12 + /**
  13 + * This is the model class for table "alias".
  14 + *
  15 + * @property integer $id
  16 + * @property string $value
  17 + * @property string $route
  18 + * @property string $title
  19 + * @property string $description
  20 + * @property string $h1
  21 + * @property string $robots
  22 + * @property string $seo_text
  23 + * @property string $entity
  24 + * @property string $fields
  25 + * @property integer $language_id
  26 + */
  27 + class Alias extends ActiveRecord implements AliasInterface
  28 + {
  29 +
  30 + const SCENARIO_CREATE = 'create';
  31 + const SCENARIO_UPDATE = 'update';
  32 +
  33 + /**
  34 + * @inheritdoc
  35 + */
  36 + public static function tableName()
  37 + {
  38 + return 'alias';
  39 + }
  40 +
  41 + public function scenarios()
  42 + {
  43 + $scenarios = parent::scenarios();
  44 + $scenarios[ self::SCENARIO_CREATE ] = [
  45 + 'value',
  46 + 'route',
  47 + 'title',
  48 + 'description',
  49 + 'h1',
  50 + 'robots',
  51 + 'seo_text',
  52 + 'language_id',
  53 + 'entity',
  54 + ];
  55 + $scenarios[ self::SCENARIO_UPDATE ] = [
  56 + 'value',
  57 + 'title',
  58 + 'description',
  59 + 'h1',
  60 + 'robots',
  61 + 'seo_text',
  62 + ];
  63 + return $scenarios;
  64 + }
  65 +
  66 + /**
  67 + * @inheritdoc
  68 + */
  69 + public function rules()
  70 + {
  71 + return [
  72 + [
  73 + [ 'value' ],
  74 + 'required',
  75 + ],
  76 + [
  77 + [
  78 + 'value',
  79 + 'title',
  80 + 'robots',
  81 + 'h1',
  82 + 'route',
  83 + 'entity',
  84 + ],
  85 + 'string',
  86 + 'max' => 255,
  87 + ],
  88 + [
  89 + [
  90 + 'description',
  91 + 'seo_text',
  92 + ],
  93 + 'string',
  94 + ],
  95 + [
  96 + [ 'value' ],
  97 + 'filter',
  98 + 'filter' => function ($value) {
  99 + return SlugHelper::slugify($value);
  100 + },
  101 + ],
  102 + [
  103 + [ 'robots' ],
  104 + 'match',
  105 + 'pattern' => '~^(no)?index\s?\,\s?(no)?follow$~',
  106 + 'message' => Yii::t('core', "Doesn't look like robots"),
  107 + ],
  108 + [
  109 + [ 'robots' ],
  110 + 'match',
  111 + 'pattern' => '~^(no)?index\s?\,\s?(no)?follow$~',
  112 + 'message' => Yii::t('core', "Doesn't look like robots"),
  113 + ],
  114 + [
  115 + [ 'language_id' ],
  116 + 'integer',
  117 + ],
  118 + [
  119 + [ 'language_id' ],
  120 + 'exist',
  121 + 'targetClass' => Language::className(),
  122 + 'targetAttribute' => 'id',
  123 + ],
  124 + // [
  125 + // [ 'route' ],
  126 + // 'match',
  127 + // 'pattern' => '/^{[\'"]0[\'"]:["\'][\w-\/]+["\'][,\w\s\'":]*}$/',
  128 + // ],
  129 + [
  130 + [
  131 + 'route',
  132 + 'language_id',
  133 + ],
  134 + 'unique',
  135 + 'targetAttribute' => [
  136 + 'route',
  137 + 'language_id',
  138 + ],
  139 + ],
  140 + ];
  141 + }
  142 +
  143 + /**
  144 + * @inheritdoc
  145 + */
  146 + public function attributeLabels()
  147 + {
  148 + return [
  149 + 'id' => Yii::t('core', 'ID'),
  150 + 'value' => Yii::t('core', 'Value'),
  151 + 'route' => Yii::t('core', 'Route'),
  152 + 'title' => Yii::t('core', 'Title'),
  153 + 'robots' => Yii::t('core', 'Meta robots'),
  154 + 'h1' => Yii::t('core', 'H1'),
  155 + 'description' => Yii::t('core', 'Description'),
  156 + 'seo_text' => Yii::t('core', 'Seo text'),
  157 + 'entity' => Yii::t('core', 'Entity'),
  158 + 'fields' => Yii::t('core', 'Available fields'),
  159 + 'language_id' => Yii::t('core', 'Language'),
  160 + ];
  161 + }
  162 +
  163 + /**
  164 + * Check $fields property availability in $entity class and return only validated fields.
  165 + *
  166 + * @return array
  167 + */
  168 + public function getCheckedFields()
  169 + {
  170 + /**
  171 + * @var ActiveRecord $model
  172 + */
  173 +
  174 + $model = \Yii::createObject($this->entity);
  175 + $fields = Json::decode($this->fields);
  176 +
  177 + $checked = [];
  178 + if ($fields !== null) {
  179 + foreach ($fields as $field => $fieldTitle) {
  180 + $currentField = explode('.', $field);
  181 + $result = $model;
  182 + foreach ($currentField as $index => $item) {
  183 + if (($index + 1) < count($currentField)) {
  184 + $result = $result->getRelation($item, false);
  185 + if (empty($result)) {
  186 + break;
  187 + } else {
  188 + $result = \Yii::createObject($result->modelClass);
  189 + }
  190 + } else {
  191 + if ($result->canGetProperty($item)) {
  192 + $checked[$field] = $fieldTitle;
  193 + }
  194 + }
  195 + }
  196 + }
  197 + }
  198 + return $checked;
  199 + }
  200 +
  201 + /**
  202 + * Find one alias model by url
  203 + *
  204 + * @param string $url
  205 + * @param \artbox\core\models\Language $language
  206 + *
  207 + * @return array|\artbox\core\models\Alias|null
  208 + */
  209 + public static function findUrl(string $url, Language $language)
  210 + {
  211 + return self::find()
  212 + ->where([ 'value' => ltrim($url, '/') ])
  213 + ->andWhere([ 'language_id' => $language->id ])
  214 + ->andWhere([
  215 + '!=',
  216 + 'value', 'home'
  217 + ])
  218 + ->one();
  219 + }
  220 +
  221 + /**
  222 + * @param array $route
  223 + * @param \artbox\core\models\Language $language
  224 + *
  225 + * @return array|\artbox\core\models\Alias|null
  226 + */
  227 + public static function findRoute(array $route, Language $language)
  228 + {
  229 + try {
  230 + $encodedRoute = Json::encode(
  231 + $route,
  232 + JSON_FORCE_OBJECT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
  233 + );
  234 + } catch (InvalidParamException $exception) {
  235 + return null;
  236 + }
  237 + $query = self::find()
  238 + ->where(
  239 + [
  240 + 'route' => $encodedRoute,
  241 + ]
  242 + );
  243 + $query->andWhere([ 'language_id' => $language->id ]);
  244 + return $query->one();
  245 + }
  246 +
  247 + public function getTitle(): string
  248 + {
  249 + return strval($this->title);
  250 + }
  251 +
  252 + public function getDesc(): string
  253 + {
  254 + return strval($this->description);
  255 + }
  256 +
  257 + public function getH1(): string
  258 + {
  259 + return strval($this->h1);
  260 + }
  261 +
  262 + public function getText(): string
  263 + {
  264 + return strval($this->seo_text);
  265 + }
  266 +
  267 + public function getRobots(): string
  268 + {
  269 + return strval($this->robots);
  270 + }
  271 + public function getFields(): string
  272 + {
  273 + return strval($this->fields);
  274 + }
  275 + public function getSeoText(): string
  276 + {
  277 + return strval($this->seo_text);
  278 + }
  279 + public function getId()
  280 + {
  281 + return $this->id;
  282 + }
  283 + }
... ...
artweb/artbox-core/models/AliasSearch.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\models;
  4 +
  5 + use yii\base\Model;
  6 + use yii\data\ActiveDataProvider;
  7 +
  8 + /**
  9 + * AliasSearch represents the model behind the search form about `artbox\core\models\Alias`.
  10 + */
  11 + class AliasSearch extends Alias
  12 + {
  13 +
  14 + public $search;
  15 + public $static;
  16 + public $entity;
  17 +
  18 + /**
  19 + * @inheritdoc
  20 + */
  21 + public function rules()
  22 + {
  23 + return [
  24 + [
  25 + [
  26 + 'search',
  27 + 'entity',
  28 + ],
  29 + 'string',
  30 + ],
  31 + [
  32 + [ 'language_id' ],
  33 + 'integer',
  34 + ],
  35 + [
  36 + [ 'static' ],
  37 + 'boolean',
  38 + ],
  39 + ];
  40 + }
  41 +
  42 + /**
  43 + * @inheritdoc
  44 + */
  45 + public function scenarios()
  46 + {
  47 + // bypass scenarios() implementation in the parent class
  48 + return Model::scenarios();
  49 + }
  50 +
  51 + /**
  52 + * @inheritdoc
  53 + */
  54 + public function behaviors()
  55 + {
  56 + return [];
  57 + }
  58 +
  59 + /**
  60 + * Creates data provider instance with search query applied
  61 + *
  62 + * @param array $params
  63 + *
  64 + * @return ActiveDataProvider
  65 + */
  66 + public function search($params)
  67 + {
  68 + $query = Alias::find();
  69 +
  70 + // add conditions that should always apply here
  71 +
  72 + $dataProvider = new ActiveDataProvider(
  73 + [
  74 + 'query' => $query,
  75 + ]
  76 + );
  77 +
  78 + $this->load($params);
  79 +
  80 + if (!$this->validate()) {
  81 + // uncomment the following line if you do not want to return any records when validation fails
  82 + // $query->where('0=1');
  83 + return $dataProvider;
  84 + }
  85 +
  86 + // grid filtering conditions
  87 + $query->andFilterWhere(
  88 + [
  89 + 'entity' => $this->entity,
  90 + ]
  91 + );
  92 +
  93 + $query->andFilterWhere(
  94 + [
  95 + 'ilike',
  96 + 'value',
  97 + $this->search,
  98 + ]
  99 + );
  100 +
  101 + // If language_id == 0, search for records with null language
  102 + if ($this->language_id === '0') {
  103 + $query->andWhere(
  104 + [
  105 + 'language_id' => null,
  106 + ]
  107 + );
  108 + } else {
  109 + $query->andFilterWhere(
  110 + [
  111 + 'language_id' => $this->language_id,
  112 + ]
  113 + );
  114 + }
  115 +
  116 + // If language_id == 0, search for records without entities
  117 + if ($this->static === '0') {
  118 + $query->andWhere(
  119 + [
  120 + 'entity' => null,
  121 + ]
  122 + );
  123 + } elseif ($this->static === '1') {
  124 + $query->andWhere(
  125 + [
  126 + 'not',
  127 + [
  128 + 'entity' => null,
  129 + ],
  130 + ]
  131 + );
  132 + }
  133 +
  134 + return $dataProvider;
  135 + }
  136 + }
... ...
artweb/artbox-core/models/ChangePassword.php 0 → 100755
  1 +<?php
  2 + namespace artbox\core\models;
  3 +
  4 + use yii\base\Model;
  5 +
  6 + class ChangePassword extends Model
  7 + {
  8 + /**
  9 + * @var string $oldPassword
  10 + */
  11 + public $oldPassword;
  12 + /**
  13 + * @var string $newPassword
  14 + */
  15 + public $newPassword;
  16 + /**
  17 + * @var string $newPasswordRepeat
  18 + */
  19 + public $newPasswordRepeat;
  20 +
  21 + /**
  22 + * @inheritdoc
  23 + */
  24 + public function attributeLabels()
  25 + {
  26 + return [
  27 + 'oldPassword' => \Yii::t('core', 'Old password'),
  28 + 'newPassword' => \Yii::t('core', 'New password'),
  29 + 'newPasswordRepeat' => \Yii::t('core', 'New password repeat'),
  30 + ];
  31 + }
  32 +
  33 + /**
  34 + * @inheritdoc
  35 + */
  36 + public function rules()
  37 + {
  38 + return [
  39 + [
  40 + [
  41 + 'oldPassword',
  42 + 'newPassword',
  43 + 'newPasswordRepeat',
  44 + ],
  45 + 'required',
  46 + ],
  47 + [
  48 + [
  49 + 'oldPassword',
  50 + 'newPassword',
  51 + 'newPasswordRepeat',
  52 + ],
  53 + 'string',
  54 + 'length' => [
  55 + 6,
  56 + 255,
  57 + ],
  58 + ],
  59 + [
  60 + [ 'newPasswordRepeat' ],
  61 + 'compare',
  62 + 'compareAttribute' => 'newPassword',
  63 + ],
  64 + ];
  65 + }
  66 +
  67 + /**
  68 + * Validate old password.
  69 + *
  70 + * @return bool True if password valid, otherwise false
  71 + */
  72 + public function validatePassword()
  73 + {
  74 + /**
  75 + * @var User $user
  76 + */
  77 + $user = \Yii::$app->user->identity;
  78 + $result = $user->validatePassword($this->oldPassword);
  79 + if (!$result) {
  80 + $this->addError('oldPassword', \Yii::t('core', 'Provided old password doesn\'t match real password.'));
  81 + }
  82 + return $result;
  83 + }
  84 +
  85 + /**
  86 + * Save new password
  87 + *
  88 + * @return bool True if successfully saved
  89 + */
  90 + public function saveChanges()
  91 + {
  92 + /**
  93 + * @var User $user
  94 + */
  95 + $user = \Yii::$app->user->identity;
  96 + $user->setPassword($this->newPassword);
  97 + $user->generateAuthKey();
  98 + return $user->save();
  99 + }
  100 + }
0 101 \ No newline at end of file
... ...
artweb/artbox-core/models/DummyAlias.php 0 → 100755
  1 +<?php
  2 +
  3 + namespace artbox\core\models;
  4 +
  5 + use artbox\core\models\interfaces\AliasInterface;
  6 + use yii\base\Object;
  7 +
  8 + class DummyAlias extends Object implements AliasInterface
  9 + {
  10 + public $title = '';
  11 +
  12 + public $desc = '';
  13 +
  14 + public $h1 = '';
  15 +
  16 + public $text = '';
  17 +
  18 + public $robots = '';
  19 +
  20 + public $seoText = '';
  21 +
  22 + public function getTitle(): string
  23 + {
  24 + return $this->title;
  25 + }
  26 +
  27 + public function getDesc(): string
  28 + {
  29 + return $this->desc;
  30 + }
  31 +
  32 + public function getH1(): string
  33 + {
  34 + return $this->h1;
  35 + }
  36 +
  37 + public function getText(): string
  38 + {
  39 + return $this->text;
  40 + }
  41 +
  42 + public function getRobots(): string
  43 + {
  44 + return $this->robots;
  45 + }
  46 + public function getFields(): string
  47 + {
  48 + return '';
  49 + }
  50 + public function getSeoText(): string
  51 + {
  52 + return $this->seoText;
  53 + }
  54 + public function getId()
  55 + {
  56 + return null;
  57 + }
  58 + }
0 59 \ No newline at end of file
... ...