Commit 326af91906814cb519afeb0bc752c70e0be82b79
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.
| 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 | ... | ... |
| 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. | ... | ... |
| 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 | +``` | ... | ... |
| 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 | ... | ... |
| 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 | + } | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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
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">×</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('(?:[\?&]|&)' + 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
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> × <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 | + } | ... | ... |
| 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 | ... | ... |
| 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 | + } | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | + } | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |
| 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. | ... | ... |
| 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 | + } | ... | ... |
| 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 | + } | ... | ... |
| 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 | + } | ... | ... |
| 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 | ... | ... |
| 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 | ... | ... |