diff --git a/common/config/.gitignore b/common/config/.gitignore new file mode 100644 index 0000000..22258e4 --- /dev/null +++ b/common/config/.gitignore @@ -0,0 +1 @@ +main-local.php \ No newline at end of file diff --git a/common/models/Media.php b/common/models/Media.php new file mode 100644 index 0000000..6860c0d --- /dev/null +++ b/common/models/Media.php @@ -0,0 +1,124 @@ + 'png, gif, jpeg, jpg', 'skipOnEmpty' => true], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => Yii::t('app', 'ID'), + 'hash' => Yii::t('app', 'Hash'), + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getArticleCategoryMedia() + { + return $this->hasMany(ArticleCategoryMedia::className(), ['media_id' => 'id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getArticleMedia() + { + return $this->hasMany(ArticleMedia::className(), ['media_id' => 'id']); + } + + public function getArticle() + { + return $this->hasMany(Article::className(), ['id' => 'article_id'])->via('articleMedia'); + } + + public function upload() + { + if(!empty($this->imageFile) && $this->validate('imageFile')) + { + $uploaddir = \Yii::getAlias('@saveImageDir'); + $this->hash = md5_file($this->imageFile->tempName).\Yii::$app->security->generateRandomString(5); + $this->extension = $this->imageFile->extension; + if(is_dir($uploaddir.$this->hash)) { + return false; + } else { + if(!mkdir($uploaddir.$this->hash, 0755)) { + return false; + } + } + $this->imageFile->saveAs($uploaddir.$this->hash.'/original.'.$this->imageFile->extension, false); + if($this->save(false)) { + return true; + } else { + $this->addError('imageFile', \Yii::t('app', 'Cannot load file')); + return false; + } + } else { + return false; + } + } + + public function delete() + { + $uploaddir = \Yii::getAlias('@saveImageDir'); + if(is_dir($uploaddir.$this->hash)) { + $this->removeDir($uploaddir.$this->hash); + } + return parent::delete(); + } + + public function removeDir($dir) + { + if($objs = glob($dir."/*")) { + foreach($objs as $obj) { + is_dir($obj) ? removeDir($obj) : unlink($obj); + } + } + rmdir($dir); + } +} diff --git a/common/modules/blog/models/Article.php b/common/modules/blog/models/Article.php new file mode 100644 index 0000000..b9bd15e --- /dev/null +++ b/common/modules/blog/models/Article.php @@ -0,0 +1,161 @@ + Autocomplete::className(), + 'attributes' => [ + 'translit' => ['code'], + ] + ] + ]; + } + /** + * @inheritdoc + */ + public function rules() + { + return [ + [['sort', 'parent_id', 'active', 'comments', 'voting'], 'integer'], + [['create_at', 'update_at'], 'safe'], + [['code'], 'required'], + [['code', 'tags'], 'string'] + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => Yii::t('app', 'ID'), + 'sort' => Yii::t('app', 'Sort'), + 'create_at' => Yii::t('app', 'Create At'), + 'update_at' => Yii::t('app', 'Update At'), + 'code' => Yii::t('app', 'Code'), + 'author' => Yii::t('app', 'Author'), + 'tags' => Yii::t('app', 'Tags'), + 'parent_id' => Yii::t('app', 'Parent ID'), + 'active' => Yii::t('app', 'Active'), + 'comments' => Yii::t('app', 'Comments'), + 'voting' => Yii::t('app', 'Voting'), + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getParent() + { + return $this->hasOne(Article::className(), ['id' => 'parent_id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getArticles() + { + return $this->hasMany(Article::className(), ['parent_id' => 'id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getAuthor0() + { + return $this->hasOne(User::className(), ['id' => 'author']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getArticleLangs() + { + return $this->hasMany(ArticleLang::className(), ['article_id' => 'id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getArticleMedia() + { + return $this->hasMany(ArticleMedia::className(), ['article_id' => 'id']); + } + + public function getMedia() + { + return $this->hasMany(Media::className(), ['id' => 'media_id'])->via('articleMedia'); + } + /** + * @return \yii\db\ActiveQuery + */ + public function getArticleToCategories() + { + return $this->hasMany(ArticleToCategory::className(), ['article_id' => 'id']); + } + + public function getArticleCategories() + { + return $this->hasMany(ArticleCategory::className(), ['id' => 'category_id'])->viaTable('article_to_category', ['article_id' => 'id']); + } + + public static function findArticleDropdown($id) + { + $query = new Query(); + return $query->select(['l.name', 'a.id']) + ->from(['article a']) + ->leftJoin(['article_lang l'], 'a.id = l.article_id') + ->where(['l.lang_id' => 0, 'a.active' => 1]) + ->andWhere(['not', ['a.id' => $id]]) + ->indexBy('a.id') + ->column(); + } + + public function getArticleCategoriesArray() + { + return $this->getArticleToCategories()->select('category_id')->column(); + } +} diff --git a/common/modules/blog/models/ArticleCategory.php b/common/modules/blog/models/ArticleCategory.php new file mode 100644 index 0000000..6fd39e9 --- /dev/null +++ b/common/modules/blog/models/ArticleCategory.php @@ -0,0 +1,133 @@ + Autocomplete::className(), + 'attributes' => [ + 'translit' => ['code'], + ] + ] + ]; + } + /** + * @inheritdoc + */ + public function rules() + { + return [ + [['active', 'sort', 'parent_id'], 'integer'], + [['code'], 'required'], + [['code', 'tags'], 'string'], + [['created_at', 'updated_at'], 'safe'], + [['active'], 'boolean'], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => Yii::t('app', 'ID'), + 'active' => Yii::t('app', 'Active'), + 'sort' => Yii::t('app', 'Sort'), + 'code' => Yii::t('app', 'Code'), + 'created_at' => Yii::t('app', 'Created At'), + 'updated_at' => Yii::t('app', 'Updated At'), + 'tags' => Yii::t('app', 'Tags'), + 'parent_id' => Yii::t('app', 'Parent ID'), + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getArticles() + { + return $this->hasMany(Article::className(), ['category_id' => 'id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getParent() + { + return $this->hasOne(ArticleCategory::className(), ['id' => 'parent_id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getArticleCategories() + { + return $this->hasMany(ArticleCategory::className(), ['parent_id' => 'id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getArticleCategoryLangs() + { + return $this->hasMany(ArticleCategoryLang::className(), ['category_id' => 'id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getArticleCategoryMedia() + { + return $this->hasMany(ArticleCategoryMedia::className(), ['category_id' => 'id']); + } + + public static function findArticleCategoryDropdown($id) + { + $query = new Query(); + return $query->select(['l.name', 'c.id']) + ->from(['article_category c']) + ->leftJoin(['article_category_lang l'], 'c.id = l.category_id') + ->where(['l.lang_id' => 0, 'c.active' => 1]) + ->andWhere(['not', ['c.id' => $id]]) + ->indexBy('id') + ->column(); + } + +} diff --git a/common/modules/blog/models/ArticleCategoryLang.php b/common/modules/blog/models/ArticleCategoryLang.php new file mode 100644 index 0000000..10a5c97 --- /dev/null +++ b/common/modules/blog/models/ArticleCategoryLang.php @@ -0,0 +1,102 @@ + Autocomplete::className(), + 'attributes' => [ + 'repeat' => [['preview', 'text', false, 5, true, '...']], + ] + ] + ]; + } + /** + * @inheritdoc + */ + public function rules() + { + return [ + [['lang_id', 'category_id'], 'integer'], + [['text', 'name'], 'required'], + [['text', 'preview', 'seo_url', 'name', 'meta_title', 'meta_descr', 'meta_keywords', 'h1_tag', 'tags'], 'string'], + ['seo_url', function($attribute, $params) { + $pattern = "/^[a-zA-Z\d_-]+$/"; + if(!preg_match($pattern, $this->$attribute)) { + $this->addError($attribute, Yii::t('app', "Pattern doesn't match.")); + } + }] + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => Yii::t('app', 'ID'), + 'lang_id' => Yii::t('app', 'Lang ID'), + 'category_id' => Yii::t('app', 'Category ID'), + 'text' => Yii::t('app', 'Text'), + 'preview' => Yii::t('app', 'Preview'), + 'seo_url' => Yii::t('app', 'Seo Url'), + 'name' => Yii::t('app', 'Name'), + 'meta_title' => Yii::t('app', 'Meta Title'), + 'meta_descr' => Yii::t('app', 'Meta Descr'), + 'meta_keywords' => Yii::t('app', 'Meta Keywords'), + 'h1_tag' => Yii::t('app', 'H1 Tag'), + 'tags' => Yii::t('app', 'Tags'), + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getCategory() + { + return $this->hasOne(ArticleCategory::className(), ['id' => 'category_id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getLang() + { + return $this->hasOne(Language::className(), ['language_id' => 'lang_id']); + } +} diff --git a/common/modules/blog/models/ArticleCategoryMedia.php b/common/modules/blog/models/ArticleCategoryMedia.php new file mode 100644 index 0000000..4c7c1aa --- /dev/null +++ b/common/modules/blog/models/ArticleCategoryMedia.php @@ -0,0 +1,159 @@ + 10], + [['imageFile'], 'file', 'extensions' => 'png, gif, jpg, jpeg', 'skipOnEmpty' => true, 'on' => self::SCENARIO_FULL], + [['imageFile'], 'file', 'extensions' => 'png, gif, jpg, jpeg', 'skipOnEmpty' => true, 'on' => self::SCENARIO_PREVIEW], + [['imageFile'], 'file', 'extensions' => 'png, gif, jpg, jpeg', 'skipOnEmpty' => true, 'maxFiles' => 10, 'on' => self::SCENARIO_ADDITIONAL] + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => Yii::t('app', 'ID'), + 'category_id' => Yii::t('app', 'Category ID'), + 'media_id' => Yii::t('app', 'Media ID'), + 'media_alt' => Yii::t('app', 'Media Alt'), + 'media_title' => Yii::t('app', 'Media Title'), + 'media_caption' => Yii::t('app', 'Media Caption'), + 'type' => Yii::t('app', 'Type'), + 'imageFile' => Yii::t('app', 'Image File'), + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getCategory() + { + return $this->hasOne(ArticleCategory::className(), ['id' => 'category_id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getMedia() + { + return $this->hasOne(Media::className(), ['id' => 'media_id']); + } + + public function upload($category_id) + { + $this->category_id = $category_id; + if(is_array($this->imageFile)) { + $ok = true; + foreach($this->imageFile as $image) { + $media_category = clone $this; + $media = new Media(); + $media->imageFile = $image; + $media->upload(); + $media_category->media_id = $media->id; + $ok = $media_category->save() && $ok; + unset($media_category); + } + return $ok; + } elseif(!empty($this->imageFile)) { + $media = new Media(); + $media->imageFile = $this->imageFile; + $media->upload(); + $this->media_id = $media->id; + return $this->save(); + } + } + + public function replace($category_id, $removeMedia = false) + { + $this->category_id = $category_id; + if($removeMedia) { + $category_media = ArticleCategoryMedia::find()->select('media_id')->where(['category_id' => $this->category_id, 'type' => $this->type])->column(); + $media = array(); + foreach($category_media as $media_id) { + $media[] = Media::findOne(['id' => $media_id]); + } + $media = array_unique($media); + foreach($media as $one_media) { + if($one_media instanceof Media) { + $one_media->delete(); + } + } + unset($media); + unset($category_media); + } + if(is_array($this->imageFile)) { + $ok = true; + foreach($this->imageFile as $image) { + $media_category = clone $this; + $media = new Media(); + $media->imageFile = $image; + $media->upload(); + $media_category->media_id = $media->id; + $ok = $media_category->save() && $ok; + unset($media_category); + } + return $ok; + } elseif(!empty($this->imageFile)) { + ArticleCategoryMedia::deleteAll(['category_id' => $this->category_id, 'type' => $this->type]); + $media = new Media(); + $media->imageFile = $this->imageFile; + $media->upload(); + $this->media_id = $media->id; + $this->setIsNewRecord(true); + return $this->save(); + } + } + +} diff --git a/common/modules/blog/models/ArticleLang.php b/common/modules/blog/models/ArticleLang.php new file mode 100644 index 0000000..7bc23b7 --- /dev/null +++ b/common/modules/blog/models/ArticleLang.php @@ -0,0 +1,85 @@ + Yii::t('app', 'ID'), + 'lang_id' => Yii::t('app', 'Lang ID'), + 'article_id' => Yii::t('app', 'Article ID'), + 'text' => Yii::t('app', 'Text'), + 'seo_url' => Yii::t('app', 'Seo Url'), + 'name' => Yii::t('app', 'Name'), + 'preview' => Yii::t('app', 'Preview'), + 'meta_title' => Yii::t('app', 'Meta Title'), + 'meta_descr' => Yii::t('app', 'Meta Descr'), + 'meta_keywords' => Yii::t('app', 'Meta Keywords'), + 'h1_tag' => Yii::t('app', 'H1 Tag'), + 'tags' => Yii::t('app', 'Tags'), + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getArticle() + { + return $this->hasOne(Article::className(), ['id' => 'article_id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getLang() + { + return $this->hasOne(Language::className(), ['language_id' => 'lang_id']); + } +} diff --git a/common/modules/blog/models/ArticleMedia.php b/common/modules/blog/models/ArticleMedia.php new file mode 100644 index 0000000..386f107 --- /dev/null +++ b/common/modules/blog/models/ArticleMedia.php @@ -0,0 +1,160 @@ + 10], + [['imageFile'], 'file', 'extensions' => 'png, gif, jpg, jpeg', 'skipOnEmpty' => true, 'on' => self::SCENARIO_FULL], + [['imageFile'], 'file', 'extensions' => 'png, gif, jpg, jpeg', 'skipOnEmpty' => true, 'on' => self::SCENARIO_PREVIEW], + [['imageFile'], 'file', 'extensions' => 'png, gif, jpg, jpeg', 'skipOnEmpty' => true, 'maxFiles' => 10, 'on' => self::SCENARIO_ADDITIONAL] + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => Yii::t('app', 'ID'), + 'article_id' => Yii::t('app', 'Article ID'), + 'media_id' => Yii::t('app', 'Media ID'), + 'type' => Yii::t('app', 'Type'), + 'media_alt' => Yii::t('app', 'Media Alt'), + 'media_title' => Yii::t('app', 'Media Title'), + 'media_caption' => Yii::t('app', 'Media Caption'), + 'imageFile' => Yii::t('app', 'Image File'), + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getArticle() + { + return $this->hasOne(Article::className(), ['id' => 'article_id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getMedia() + { + return $this->hasOne(Media::className(), ['id' => 'media_id']); + } + + public function upload($article_id) + { + $this->article_id = $article_id; + if(is_array($this->imageFile)) { + $ok = true; + foreach($this->imageFile as $image) { + $media_article = clone $this; + $media = new Media(); + $media->imageFile = $image; + $media->upload(); + $media_article->media_id = $media->id; + $ok = $media_article->save() && $ok; + unset($media_article); + } + return $ok; + } elseif(!empty($this->imageFile)) { + $media = new Media(); + $media->imageFile = $this->imageFile; + $media->upload(); + $this->media_id = $media->id; + return $this->save(); + } + } + + public function replace($article_id, $removeMedia = false) + { + $this->article_id = $article_id; + if($removeMedia) { + $article_media = ArticleMedia::find()->select('media_id')->where(['article_id' => $this->article_id, 'type' => $this->type])->column(); + $media = array(); + foreach($article_media as $media_id) { + $media[] = Media::findOne(['id' => $media_id]); + } + $media = array_unique($media); + foreach($media as $one_media) { + if($one_media instanceof Media) { + $one_media->delete(); + } + } + unset($media); + unset($article_media); + } + if(is_array($this->imageFile)) { + $ok = true; + foreach($this->imageFile as $image) { + $media_article = clone $this; + $media = new Media(); + $media->imageFile = $image; + $media->upload(); + $media_article->media_id = $media->id; + $ok = $media_article->save() && $ok; + unset($media_article); + } + return $ok; + } elseif(!empty($this->imageFile)) { + ArticleMedia::deleteAll(['article_id' => $this->article_id, 'type' => $this->type]); + $media = new Media(); + $media->imageFile = $this->imageFile; + $media->upload(); + $this->media_id = $media->id; + $this->setIsNewRecord(true); + return $this->save(); + } + } + +} diff --git a/common/modules/blog/models/ArticleToCategory.php b/common/modules/blog/models/ArticleToCategory.php new file mode 100644 index 0000000..a3d62d0 --- /dev/null +++ b/common/modules/blog/models/ArticleToCategory.php @@ -0,0 +1,62 @@ + Yii::t('app', 'Article ID'), + 'category_id' => Yii::t('app', 'Category ID'), + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getArticle() + { + return $this->hasOne(Article::className(), ['id' => 'article_id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getCategory() + { + return $this->hasOne(ArticleCategory::className(), ['id' => 'category_id']); + } +} diff --git a/db-migration/yarik.zip b/db-migration/yarik.zip new file mode 100644 index 0000000..df86c39 Binary files /dev/null and b/db-migration/yarik.zip differ diff --git a/frontend/web/images/upload/06021c27debe77630c03fb0e28a419fcaRUpU/original.jpg b/frontend/web/images/upload/06021c27debe77630c03fb0e28a419fcaRUpU/original.jpg new file mode 100644 index 0000000..a9c4a21 Binary files /dev/null and b/frontend/web/images/upload/06021c27debe77630c03fb0e28a419fcaRUpU/original.jpg differ diff --git a/frontend/web/images/upload/1a0cbb7d512737e6257dab6319c8760dzucy5/original.png b/frontend/web/images/upload/1a0cbb7d512737e6257dab6319c8760dzucy5/original.png new file mode 100644 index 0000000..7e36960 Binary files /dev/null and b/frontend/web/images/upload/1a0cbb7d512737e6257dab6319c8760dzucy5/original.png differ diff --git a/frontend/web/images/upload/40de6d6d4d8155e28570cc6a605c312dvaQ3X/original.png b/frontend/web/images/upload/40de6d6d4d8155e28570cc6a605c312dvaQ3X/original.png new file mode 100644 index 0000000..a41c058 Binary files /dev/null and b/frontend/web/images/upload/40de6d6d4d8155e28570cc6a605c312dvaQ3X/original.png differ diff --git a/frontend/web/images/upload/535ef2c058ba1c87101af958ecb70dd31Mdw0/original.jpg b/frontend/web/images/upload/535ef2c058ba1c87101af958ecb70dd31Mdw0/original.jpg new file mode 100644 index 0000000..6d1f32d Binary files /dev/null and b/frontend/web/images/upload/535ef2c058ba1c87101af958ecb70dd31Mdw0/original.jpg differ diff --git a/frontend/web/images/upload/5ee447f553cd4b615e0107772e72469ci_PpP/original.jpg b/frontend/web/images/upload/5ee447f553cd4b615e0107772e72469ci_PpP/original.jpg new file mode 100644 index 0000000..7601e57 Binary files /dev/null and b/frontend/web/images/upload/5ee447f553cd4b615e0107772e72469ci_PpP/original.jpg differ diff --git a/frontend/web/images/upload/68ea5e978068f52504ba9f2f10a3eca8df4wM/original.jpg b/frontend/web/images/upload/68ea5e978068f52504ba9f2f10a3eca8df4wM/original.jpg new file mode 100644 index 0000000..d6983b2 Binary files /dev/null and b/frontend/web/images/upload/68ea5e978068f52504ba9f2f10a3eca8df4wM/original.jpg differ diff --git a/frontend/web/images/upload/7c0beac302dbe743c2fec948bd232d7doP_3v/original.jpg b/frontend/web/images/upload/7c0beac302dbe743c2fec948bd232d7doP_3v/original.jpg new file mode 100644 index 0000000..ac80faa Binary files /dev/null and b/frontend/web/images/upload/7c0beac302dbe743c2fec948bd232d7doP_3v/original.jpg differ diff --git a/frontend/web/images/upload/bdaa304bee2504b65fffa5d1cb15fbf4Cdp4t/original.jpg b/frontend/web/images/upload/bdaa304bee2504b65fffa5d1cb15fbf4Cdp4t/original.jpg new file mode 100644 index 0000000..62f1627 Binary files /dev/null and b/frontend/web/images/upload/bdaa304bee2504b65fffa5d1cb15fbf4Cdp4t/original.jpg differ diff --git a/frontend/web/images/upload/da89edbbf4c7d0addb126fe4169800f8VJaw2/original.jpg b/frontend/web/images/upload/da89edbbf4c7d0addb126fe4169800f8VJaw2/original.jpg new file mode 100644 index 0000000..b1d2734 Binary files /dev/null and b/frontend/web/images/upload/da89edbbf4c7d0addb126fe4169800f8VJaw2/original.jpg differ diff --git a/frontend/web/images/upload/fe37052e2ca69e4db311946dc24eab40a5hso/original.jpg b/frontend/web/images/upload/fe37052e2ca69e4db311946dc24eab40a5hso/original.jpg new file mode 100644 index 0000000..b49b717 Binary files /dev/null and b/frontend/web/images/upload/fe37052e2ca69e4db311946dc24eab40a5hso/original.jpg differ -- libgit2 0.21.4