diff --git a/common/modules/blog/controllers/PostController.php b/common/modules/blog/controllers/PostController.php index 3f9f9b7..64bd745 100644 --- a/common/modules/blog/controllers/PostController.php +++ b/common/modules/blog/controllers/PostController.php @@ -2,14 +2,21 @@ namespace common\modules\blog\controllers; +use common\modules\blog\entities\BlogPost; use common\modules\blog\forms\BlogCommentForm; +use common\modules\blog\forms\BlogPostForm; +use common\modules\blog\helpers\BlogPostHelper; use common\modules\blog\repositories\read\BlogCategoryReadRepository; use common\modules\blog\repositories\read\BlogPostReadRepository; use common\modules\blog\repositories\read\BlogTagReadRepository; use common\modules\blog\services\BlogCommentService; +use core\entities\Meta; use frontend\components\FrontendController; use Yii; +use yii\base\Security; use yii\data\ActiveDataProvider; +use yii\helpers\FileHelper; +use yii\helpers\Json; use yii\web\NotFoundHttpException; use yii\filters\AccessControl; @@ -43,10 +50,10 @@ class PostController extends FrontendController { return [ 'access' => [ - 'class' => AccessControl::className(), + 'class' => AccessControl::class, 'rules' => [ [ - 'actions' => ['index', 'category', 'tag', 'post'], + 'actions' => ['index', 'category', 'tag', 'post', 'preview'], 'allow' => true, //'roles' => ['Blog'], ], @@ -159,4 +166,64 @@ class PostController extends FrontendController 'model' => $form, ]); } + + public function beforeAction($action) + { + // ...set `$this->enableCsrfValidation` here based on some conditions... + // call parent method that will check CSRF if such property is true. + if ($action->id === 'preview') { + # code... + $this->enableCsrfValidation = false; + } + return parent::beforeAction($action); + } + + public function actionPreview() + { + Yii::$app->controller->enableCsrfValidation = false; + $form = new BlogPostForm(); + if ($form->load(Yii::$app->request->post()) && $form->validate()) { + $post = new BlogPost(); + $post->id = -1; + $post->title = $form->title; + $post->description = $form->description; + $post->content = $form->content; + $post->category_id = $form->category_id; + $post->created_at = time(); + $post->updated_at = time(); + $post->published_at = time(); + + $meta = new Meta($form->meta->title, $form->meta->description, $form->meta->keywords); + $post->meta = $meta; + $post->meta_json = Json::encode([ + 'title' => $form->meta->title, + 'description' => $form->meta->description, + 'keywords' => $form->meta->keywords, + ]); + $post->video = $form->video; + $post->slug = $form->slug; + + if ($form->image) { + $post->setImage($form->image); + } + else if ($form->video) { + $src = 'https://i.ytimg.com/vi/' . BlogPostHelper::parseYoutubeUrl($post->video) . '/maxresdefault.jpg'; + $filename = (new Security())->generateRandomString(15) . '.jpg'; + copy($src, \Yii::getAlias(BlogPost::FILE_ORIGINAL_PATH . '/' . $post->id . '.jpg')); + //copy($src, \Yii::getAlias(BlogPost::FILE_ORIGINAL_PATH . '/' . $filename)); + $post->image = $filename; + } + + $path = $post->getUploadedFilePath('image'); + FileHelper::createDirectory(pathinfo($path, PATHINFO_DIRNAME), 0775, true); + $post->image->saveAs($path); + + $post->image = $post->getImageFileUrl('image'); + + return $this->render('post', [ + 'post' => $post, + ]); + } + return ''; + } } \ No newline at end of file diff --git a/common/modules/blog/controllers/manage/PostController.php b/common/modules/blog/controllers/manage/PostController.php index 9136068..9aeb403 100644 --- a/common/modules/blog/controllers/manage/PostController.php +++ b/common/modules/blog/controllers/manage/PostController.php @@ -28,7 +28,7 @@ class PostController extends Controller { return [ 'access' => [ - 'class' => AccessControl::className(), + 'class' => AccessControl::class, 'rules' => [ [ 'allow' => true, @@ -41,7 +41,7 @@ class PostController extends Controller ], ], 'verbs' => [ - 'class' => VerbFilter::className(), + 'class' => VerbFilter::class, 'actions' => [ 'delete' => ['POST'], 'activate' => ['POST'], diff --git a/common/modules/blog/entities/BlogPost.php b/common/modules/blog/entities/BlogPost.php index ba28bd6..e957a7d 100644 --- a/common/modules/blog/entities/BlogPost.php +++ b/common/modules/blog/entities/BlogPost.php @@ -273,22 +273,22 @@ class BlogPost extends ActiveRecord public function getBlogComments(): ActiveQuery { - return $this->hasMany(BlogComment::className(), ['post_id' => 'id']); + return $this->hasMany(BlogComment::class, ['post_id' => 'id']); } public function getBlogTagAssignments(): ActiveQuery { - return $this->hasMany(BlogTagAssignment::className(), ['post_id' => 'id']); + return $this->hasMany(BlogTagAssignment::class, ['post_id' => 'id']); } public function getTags(): ActiveQuery { - return $this->hasMany(BlogTag::className(), ['id' => 'tag_id'])->viaTable('blog_tag_assignments', ['post_id' => 'id']); + return $this->hasMany(BlogTag::class, ['id' => 'tag_id'])->viaTable('blog_tag_assignments', ['post_id' => 'id']); } public function getCategory(): ActiveQuery { - return $this->hasOne(BlogCategory::className(), ['id' => 'category_id']); + return $this->hasOne(BlogCategory::class, ['id' => 'category_id']); } ###################################### @@ -296,15 +296,15 @@ class BlogPost extends ActiveRecord public function behaviors(): array { return [ - TimestampBehavior::className(), - MetaBehavior::className(), + TimestampBehavior::class, + MetaBehavior::class, [ - 'class' => SaveRelationsBehavior::className(), + 'class' => SaveRelationsBehavior::class, 'relations' => ['blogTagAssignments', 'blogComments'], ], [ // todo Image Sizes to settings or theme settings - 'class' => ImageUploadBehavior::className(), + 'class' => ImageUploadBehavior::class, 'attribute' => 'image', 'createThumbsOnRequest' => true, //'filePath' => $this::FILE_ORIGINAL_PATH . '/[[id]].[[extension]]', @@ -313,7 +313,7 @@ class BlogPost extends ActiveRecord 'thumbPath' => '@staticRoot/cache/posts/[[profile]]_[[id]].[[extension]]', 'thumbUrl' => '@static/cache/posts/[[profile]]_[[id]].[[extension]]', 'thumbs' => [ - 'blog_list' => ['width' => 750, 'height' => 300], + 'blog_list' => ['width' => 750, 'height' => 300, 'resizeUp' => true], 'blog_post' => ['width' => 900, 'height' => 300], 'admin' => ['width' => 60, 'height' => 60], diff --git a/common/modules/blog/messages/ru/blog.php b/common/modules/blog/messages/ru/blog.php index f40d671..00a7abc 100644 --- a/common/modules/blog/messages/ru/blog.php +++ b/common/modules/blog/messages/ru/blog.php @@ -54,6 +54,7 @@ return [ 'User' => 'Пользователь', 'Post' => 'Статья', 'YouTube URL' => 'Ссылка YouTube', + 'Video URL' => 'Ссылка на видео (YouTube, Vimeo)', 'Add Image' => 'Новое изображение', 'Video' => 'Видео', 'If a video link is specified, the image will be used as a preview image' => 'Если указана ссылка на видео, то изображение будет рассматриваться как картинка для предварительного просмотра', diff --git a/common/modules/blog/services/BlogPostManageService.php b/common/modules/blog/services/BlogPostManageService.php index a2ba4ff..e67edcd 100644 --- a/common/modules/blog/services/BlogPostManageService.php +++ b/common/modules/blog/services/BlogPostManageService.php @@ -10,6 +10,7 @@ use common\modules\blog\repositories\BlogCategoryRepository; use common\modules\blog\repositories\BlogRepository; use common\modules\blog\repositories\BlogTagRepository; use core\entities\Meta; +use core\helpers\VideoHelper; use core\services\TransactionManager; use yii\base\Security; use yii\helpers\Inflector; @@ -53,16 +54,6 @@ class BlogPostManageService ) ); - if ($form->image) { - $post->setImage($form->image); - } - else if ($form->video) { - $src = 'https://i.ytimg.com/vi/' . BlogPostHelper::parseYoutubeUrl($post->video) . '/maxresdefault.jpg'; - $filename = (new Security())->generateRandomString(15) . '.jpg'; - copy($src, \Yii::getAlias(BlogPost::FILE_ORIGINAL_PATH . '/' . $post->id . '.jpg')); - $post->image = $filename; - } - $this->transaction->wrap(function () use ($post, $form) { if (is_array($form->tags->new_tags) && !empty($form->tags->new_tags)) { @@ -75,6 +66,23 @@ class BlogPostManageService } } $this->posts->save($post); + + if ($form->image) { + $post->setImage($form->image); + } + else if ($form->video) { + $src = VideoHelper::getThumb($form->video); + //$src = 'https://i.ytimg.com/vi/' . BlogPostHelper::parseYoutubeUrl($post->video) . '/maxresdefault.jpg'; + $filename = (new Security())->generateRandomString(15) . '.jpg'; + copy($src, \Yii::getAlias(BlogPost::FILE_ORIGINAL_PATH . '/' . $post->id . '.jpg')); + $post->image = $filename; + } + + if ($form->status == BlogPost::STATUS_ACTIVE) { + $post->activate(); + } + + $this->posts->save($post); }); return $post; @@ -106,7 +114,8 @@ class BlogPostManageService } elseif ($form->video && (!$post->image || $form->reset_image)) { $post->cleanFiles(); - $src = 'https://i.ytimg.com/vi/' . BlogPostHelper::parseYoutubeUrl($post->video) . '/maxresdefault.jpg'; + $src = VideoHelper::getThumb($form->video); + //$src = 'https://i.ytimg.com/vi/' . BlogPostHelper::parseYoutubeUrl($post->video) . '/maxresdefault.jpg'; $filename = (new Security())->generateRandomString(15) . '.jpg'; copy($src, \Yii::getAlias(BlogPost::FILE_ORIGINAL_PATH . '/' . $post->id . '.jpg')); $post->image = $filename; diff --git a/common/modules/blog/urls/BlogMainUrlRule.php b/common/modules/blog/urls/BlogMainUrlRule.php index 67a7acf..c5157d2 100644 --- a/common/modules/blog/urls/BlogMainUrlRule.php +++ b/common/modules/blog/urls/BlogMainUrlRule.php @@ -4,7 +4,6 @@ namespace common\modules\blog\urls; use common\modules\blog\repositories\read\BlogPostReadRepository; use yii\base\BaseObject; -use yii\base\InvalidParamException; use yii\caching\Cache; use yii\caching\TagDependency; use yii\web\UrlNormalizerRedirectException; @@ -66,7 +65,8 @@ class BlogMainUrlRule extends BaseObject implements UrlRuleInterface }, null, new TagDependency(['tags' => ['blog']])); if (!$url) { - throw new InvalidParamException('Undefined id.'); + return '#'; + //throw new InvalidArgumentException('Undefined id.'); } $url = $this->prefix . '/' . $url; diff --git a/common/modules/blog/views/manage/post/_form.php b/common/modules/blog/views/manage/post/_form.php index d7b3a61..c5988f0 100644 --- a/common/modules/blog/views/manage/post/_form.php +++ b/common/modules/blog/views/manage/post/_form.php @@ -132,7 +132,7 @@ $this->registerJs($js2);
- field($model, 'video')->textInput()->label(Yii::t('blog', 'YouTube URL'))->hint(Yii::t('blog', 'If a video link is specified, the image will be used as a preview image')) ?> + field($model, 'video')->textInput()->label(Yii::t('blog', 'Video URL'))->hint(Yii::t('blog', 'If a video link is specified, the image will be used as a preview image')) ?>
@@ -158,7 +158,13 @@ $this->registerJs($js2);
- + 'btn btn-info', + 'value'=>'preview', + 'name'=>'submit_preview', + 'formaction' => Url::to(Yii::$app->params['frontendHostInfo'] . '/blog/post/preview'), + 'formtarget' => '_blank', + ]) ?>
field($model, 'status')->radioList(BlogPostHelper::statusList()) ?>
diff --git a/common/modules/blog/views/manage/post/view.php b/common/modules/blog/views/manage/post/view.php index c1fb1f3..38ecebf 100644 --- a/common/modules/blog/views/manage/post/view.php +++ b/common/modules/blog/views/manage/post/view.php @@ -76,7 +76,11 @@ $this->params['breadcrumbs'][] = $title;
- video) . '/maxresdefault.jpg', [ + + video), [ 'width' => 300, 'class' => 'thumbnail', ]) ?> @@ -88,7 +92,10 @@ $this->params['breadcrumbs'][] = $title;
- + $post->video, + 'style' => '', + ]) ?>
diff --git a/core/helpers/VideoHelper.php b/core/helpers/VideoHelper.php new file mode 100644 index 0000000..010b2b8 --- /dev/null +++ b/core/helpers/VideoHelper.php @@ -0,0 +1,86 @@ +thumbnail_large; + break; + } + return $src; + } + + public static function parseVimeoUrl($url) + { + $urls = parse_url($url); + // https://vimeo.com/274720181 + if($urls['host'] == 'vimeo.com'){ + $id = ltrim($urls['path'],'/'); + } + // https://player.vimeo.com/video/274720181 + else { + $parts = explode('/',$urls['path']); + $id = end($parts); + } + + return $id; + } + + public static function parseYoutubeUrl($url) + { + $urls = parse_url($url); + //url is http://youtu.be/xxxx + if($urls['host'] == 'youtu.be'){ + $id = ltrim($urls['path'],'/'); + } + //url is http://www.youtube.com/embed/xxxx + else if(strpos($urls['path'],'embed') == 1){ + $parts = explode('/',$urls['path']); + $id = end($parts); + } + //url is xxxx only + else if(strpos($url,'/')===false){ + $id = $url; + } + //http://www.youtube.com/watch?feature=player_embedded&v=m-t4pcO99gI + //url is http://www.youtube.com/watch?v=xxxx + else{ + parse_str($urls['query']); + /* @var $v */ + $id = $v; + if(!empty($feature)){ + $id = end(explode('v=',$urls['query'])); + } + } + return $id; + } + +} \ No newline at end of file diff --git a/core/widgets/VideoWidget.php b/core/widgets/VideoWidget.php new file mode 100644 index 0000000..504a723 --- /dev/null +++ b/core/widgets/VideoWidget.php @@ -0,0 +1,35 @@ +src)) { + case 'youtube': + $id = VideoHelper::parseYoutubeUrl($this->src); + $player = ''; + break; + case 'vimeo': + $id = VideoHelper::parseVimeoUrl($this->src); + $player = ''; + break; + } + return $player; + } +} \ No newline at end of file diff --git a/frontend/web/themes/start/layouts/main.php b/frontend/web/themes/start/layouts/main.php index 4ee8d47..f55d798 100644 --- a/frontend/web/themes/start/layouts/main.php +++ b/frontend/web/themes/start/layouts/main.php @@ -3,6 +3,8 @@ * @var $this \yii\web\View */ +use yii\helpers\Html; + \frontend\web\themes\start\layouts\code\assets\AppAsset::register($this); rmrevin\yii\fontawesome\cdn\AssetBundle::register($this); ?> @@ -12,13 +14,12 @@ rmrevin\yii\fontawesome\cdn\AssetBundle::register($this); - + - - - - Modern Business - Start Bootstrap Template + + <?= Html::encode($this->title) ?> + head() ?> @@ -27,12 +28,17 @@ rmrevin\yii\fontawesome\cdn\AssetBundle::register($this);