diff --git a/README.md b/README.md index eff283e..883a1e0 100644 --- a/README.md +++ b/README.md @@ -5,18 +5,18 @@ Yii2 module for easy creating meta tags # Usage in config file: ```sh +... +'bootstrap' => ['log', 'seo'], // add seo component to application bootstrap +... 'components' => [ ... 'seo' => [ 'class' => 'shershennm\seo\Seo', 'controllerMapping' => [ - 'app\controllers' => 'app\seo\controllers', \\controllers for seo module + 'app\controllers' => 'app\seo\controllers', // controller namespace for seo module ], ], - ... - 'bootstrap' => ['log', 'seo'], - ... ] ``` seo controller example: @@ -29,21 +29,25 @@ use Yii; use shershennm\seo\SeoController; class SiteController extends SeoController -{ - public function actionIndex() - { - $this->title = 'Hello world!'; - - return [ - ['name' => 'keywords', 'value' => $this->getKeywords()], - ['name' => 'description', 'value' => 'Cool page!'], - ]; - } - - private function getKeywords() - { - return implode($this->controller->words, ', '); - } +{ + /** + * $viewParams array View Params from actionIndex in SiteController + **/ + public function actionIndex($viewParams) + { + $this->title = 'Hello world!'; + + return [ + ['name' => 'keywords', 'content' => $this->getKeywords()], // params for Html::tag('meta', '', $params) + ['name' => 'description', 'content' => 'Cool page!'], + ]; + } + + private function getKeywords() + { + // $this->controller instance of current controller + return implode($this->controller->words, ', '); + } .... ``` \ No newline at end of file diff --git a/Seo.php b/Seo.php index d00f2ca..054509f 100644 --- a/Seo.php +++ b/Seo.php @@ -3,130 +3,162 @@ namespace shershennm\seo; use Yii; + +use yii\base\ActionEvent; use yii\base\Component; +use yii\base\ViewEvent; + +use yii\web\Controller; +use yii\web\View; + use yii\helpers\Html; + use shershennm\seo\Title; /** -* -*/ + * + */ class Seo extends Component { - public - $controllerMapping, - - $titleAppend, - $titlePrepend; - - private - $_controller, - $_reflectionController; - - public function getController() - { - if ($this->_controller === null) - { - $this->_controller = Yii::$app->controller; - } - - return $this->_controller; - } - - public function getReflectionController() - { - if ($this->_reflectionController === null) - { - $this->_reflectionController = $this->buildReflectionController(); - } - - return $this->_reflectionController; - } - - - public function init() - { - parent::init(); - - if (Yii::$app->view !== null) - { - Yii::$app->view->on(yii\web\View::EVENT_BEGIN_PAGE, [$this, 'eventSetMeta']); - } - } - - public function eventSetMeta() - { - if ($this->isValidController() && $this->isSeoControllerInMapping() && $this->isSeoControllerExists()) - { - $seoController = Yii::createObject($this->buildSeoControllerClassName()); - $actionMethod = $this->controller->action->actionMethod; - - if (method_exists($seoController, $actionMethod)) - { - $seoController->controller = $this->controller; - - $meta = $seoController->$actionMethod(); - $this->addMeta($meta); - - if ($seoController->title !== null) - { - Yii::$app->view->title = $this->buildTitle($seoController->title); - } - } - } - } - - private function buildTitle($title) - { - $defaults = [ - 'defaultPrepend' => $this->titlePrepend, - 'defaultAppend' => $this->titleAppend, - ]; - - if(is_array($title)) { - $title = new Title(array_merge($title, $defaults)); - } - else - { - $title = new Title(array_merge(['title' => $title], $defaults)); - } - - return $title->buildTitle(); - } - - private function addMeta($metaArray) - { - foreach ($metaArray as $meta) { - Yii::$app->view->metaTags[] = Html::tag('meta', '', $meta); - } - } - - private function buildReflectionController() - { - return (new \ReflectionClass($this->controller)); - } - - private function isSeoControllerInMapping() - { - return isset($this->controllerMapping[$this->reflectionController->getNamespaceName()]); - } - - private function isSeoControllerExists() - { - return class_exists($this->buildSeoControllerClassName()); - } - - private function isValidController() - { - return (Yii::$app->controller !== null && Yii::$app->controller->action->className() !== 'yii\web\ErrorAction'); - } - - private function buildSeoControllerClassName() - { - return sprintf('%s\%s', $this->controllerMapping[$this->reflectionController->getNamespaceName()], $this->reflectionController->getShortName()); - } - - private function buildActionFunction() - { - return sprintf('action%s', ucfirst($this->controller->action->id)); - } + public + $controllerMapping, + + $defaultTitle, + $titleAppend, + $titlePrepend; + + private + $_reflectionController; + + public function getController() + { + return Yii::$app->controller; + } + + public function getReflectionController() + { + if ($this->_reflectionController === null) + { + $this->_reflectionController = $this->buildReflectionController(); + } + + return $this->_reflectionController; + } + + public function init() + { + $this->initEventBranches(); + + parent::init(); + } + + private function initEventBranches() + { + ActionEvent::on(Controller::className(), Controller::EVENT_BEFORE_ACTION, [$this, 'eventControllerBeforeAction']); + } + + public function eventControllerBeforeAction($event) + { + ActionEvent::off(Controller::className(), Controller::EVENT_BEFORE_ACTION, [$this, 'eventControllerBeforeAction']); + + $event->sender->view->on(View::EVENT_BEFORE_RENDER, [$this, 'eventViewBeforeRender']); + } + + public function eventViewBeforeRender($event) + { + $event->sender->off(View::EVENT_BEFORE_RENDER, [$this, 'eventViewBeforeRender']); + + $this->setMeta($event); + } + + public function setMeta($viewEvent) + { + $set = false; + + if ($this->isValidController() && $this->isSeoControllerInMapping() && $this->isSeoControllerExists()) + { + $set = $this->executeSeoControllerAction($viewEvent); + } + + if ($set === false) + { + $this->addTitle($viewEvent->sender); + } + } + + private function executeSeoControllerAction($viewEvent) + { + $seoController = Yii::createObject($this->buildSeoControllerClassName()); + $actionMethod = $this->controller->action->actionMethod; + + if (method_exists($seoController, $actionMethod)) + { + $seoController->controller = $this->controller; + + $meta = $seoController->$actionMethod($viewEvent->params); + + $this->addMeta($viewEvent->sender, $meta); + $this->addTitle($viewEvent->sender, $seoController->title); + + return true; + } + + return false; + } + + private function buildTitle($title) + { + $defaults = [ + 'defaultTitle' => $this->defaultTitle, + 'defaultPrepend' => $this->titlePrepend, + 'defaultAppend' => $this->titleAppend, + ]; + + if(is_array($title)) { + $title = new Title(array_merge($title, $defaults)); + } + else + { + $title = new Title(array_merge(['title' => $title], $defaults)); + } + + return $title->buildTitle(); + } + + public function addMeta($view, $metaArray) + { + foreach ($metaArray as $meta) { + $view->metaTags[] = Html::tag('meta', '', $meta); + } + } + + public function addTitle($view, $title = null) + { + $view->title = $this->buildTitle($title); + } + + private function buildReflectionController() + { + return (new \ReflectionClass($this->controller)); + } + + private function isSeoControllerInMapping() + { + return isset($this->controllerMapping[$this->reflectionController->getNamespaceName()]); + } + + private function isSeoControllerExists() + { + return class_exists($this->buildSeoControllerClassName()); + } + + private function isValidController() + { + return (Yii::$app->controller !== null && Yii::$app->controller->action->className() !== 'yii\web\ErrorAction'); + } + + private function buildSeoControllerClassName() + { + return sprintf('%s\%s', $this->controllerMapping[$this->reflectionController->getNamespaceName()], $this->reflectionController->getShortName()); + } } \ No newline at end of file diff --git a/SeoController.php b/SeoController.php index a6cf70d..c6aca05 100644 --- a/SeoController.php +++ b/SeoController.php @@ -7,7 +7,13 @@ abstract class SeoController extends Object { - public - $controller, - $title; + /** + * @var $title string Page