TYPE_NOTAGS, # Meta Title 'mkeywords' => TYPE_NOTAGS, # Meta Keywords 'mdescription' => TYPE_NOTAGS, # Meta Description 'breadcrumb' => TYPE_NOTAGS, # Breadcrumb 'titleh1' => TYPE_NOTAGS, # Title H1 'seotext' => TYPE_STR, # Seotext ]; public function init() { parent::init(); if ($this->controller->landingPagesEnabled()) { # Добавляем доп. поля посадочных страниц $extraFields = $this->controller->landingPagesFields(); if (!empty($extraFields)) { foreach ($extraFields as $k => $v) { if (is_string($k) && !isset($this->langLandingPages[$k])) { $this->langLandingPages[$k] = (!empty($v['type']) && $v['type'] == 'wy' ? TYPE_STR : TYPE_NOTAGS); } } } } } # -------------------------------------------------------------------- # Посадочные страницы /** * Landing page model * @param int|null $id * @param array $columns * @param array $with * @param string|null $lang * @return \bff\modules\seo\models\LandingPage | \bff\db\illuminate\Model |array */ public function landingpage($id = null, $columns = ['*'], array $with = array(), $lang = null) { $model = $this->model('LandingPage'); if (! empty($id)) { return $model->one($id, $columns, $with, $lang); } return $model; } /** * Список страниц (admin) * @param array $filter фильтр списка страниц * @param bool $countOnly только подсчет кол-ва страниц * @param string $limit * @param string $orderBy * @return mixed */ public function landingpagesListing(array $filter, $countOnly = false, $limit = '', $orderBy = '') { $filter = $this->prepareFilter($filter, 'LP'); if ($countOnly) { return $this->db->one_data('SELECT COUNT(LP.id) FROM ' . static::TABLE_LANDING_PAGES . ' LP ' . $filter['where'], $filter['bind']); } if (empty($orderBy)) { $orderBy = 'LP.id DESC'; } return $this->db->select('SELECT LP.id, LP.landing_uri, LP.original_uri, LP.title, LP.enabled, LP.joined FROM ' . static::TABLE_LANDING_PAGES . ' LP ' . $filter['where'] . ' ORDER BY ' . $orderBy . $limit, $filter['bind']); } /** * Список страниц (frontend) * @param array $filter фильтр списка страниц * @param bool $countOnly только подсчет кол-ва страниц * @param string $limit * @param string $orderBy * @return mixed */ public function landingpagesList(array $filter = array(), $countOnly = false, $limit = '', $orderBy = '') { if (! $countOnly) { $filter[':lang'] = $this->db->langAnd(false, 'LP', 'LPL'); } $filter = $this->prepareFilter($filter, 'LP'); if ($countOnly) { return $this->db->one_data('SELECT COUNT(LP.id) FROM ' . static::TABLE_LANDING_PAGES . ' LP ' . $filter['where'], $filter['bind']); } $data = $this->db->select('SELECT LP.id FROM ' . static::TABLE_LANDING_PAGES . ' LP, ' . static::TABLE_LANDING_PAGES_LANG . ' LPL ' . $filter['where'] . ' ' . ( ! empty($orderBy) ? ' ORDER BY ' . $orderBy : '') . ' ' . $limit, $filter['bind']); if (empty($data)) { return []; } return $data; } /** * Формирование данных о посадочных страницах для файла Sitemap.xml * @param bool $callback * @param string $priority приоритетность url * @param array $opts доп. параметры * @return array|callable [['l'=>'url страницы','m'=>'дата последних изменений'],...] */ public function landingpagesSitemapXmlData($callback = true, $priority = '', array $opts = []) { if ($callback) { return function ($count = false, callable $callback = null) use ($priority) { if ($count) { return $this->db->one_data('SELECT COUNT(*) FROM ' . static::TABLE_LANDING_PAGES . ' WHERE enabled = 1'); } else { $languageKey = $this->locale->getDefaultLanguage(); $alt = $this->controller->sitemapXMLAltLangs(static::SITEMAP_LANG_ALL); $this->db->select_iterator( ' SELECT landing_uri AS l, DATE_FORMAT(modified, :format) as m FROM ' . static::TABLE_LANDING_PAGES . ' WHERE enabled = 1 ORDER BY modified DESC', array(':format' => '%Y-%m-%d'), function (&$row) use ($languageKey, &$callback, $priority) { $row['m'] = ''; if ( ! (mb_stripos($row['l'], 'http:') === 0 || mb_stripos($row['l'], 'https:') === 0 || mb_stripos($row['l'], '//') === 0) ) { if (! empty($alt)) { $row['alt'] = []; foreach ($alt as $l) { $row['alt'][$l] = Url::to($row['l'], ['lang' => $l]); } } $row['l'] = Url::to($row['l'], ['lang' => $languageKey]); } if (! empty($priority)) { $row['p'] = $priority; } $callback($row); } ); } return false; }; } $data = $this->db->select('SELECT landing_uri AS l, DATE_FORMAT(modified, :format) as m FROM ' . static::TABLE_LANDING_PAGES . ' WHERE enabled = 1 ORDER BY modified DESC', [ ':format' => '%Y-%m-%d', ]); if (!empty($data)) { $languageKey = $this->locale->getDefaultLanguage(); foreach ($data as &$v) { $v['m'] = ''; $v['l'] = Url::to($v['l'], ['lang' => $languageKey]); if (! empty($priority)) { $v['p'] = $priority; } } unset($v); return $data; } else { return array(); } } /** * Получение данных страницы * @param int $landingpageID ID страницы * @param bool $edit при редактировании * @return array */ public function landingpageData($landingpageID, $edit = false) { if ($edit) { $data = $this->db->one_array( 'SELECT LP.* FROM ' . static::TABLE_LANDING_PAGES . ' LP WHERE LP.id = :id', array(':id' => $landingpageID) ); if (! empty($data)) { $this->db->langSelect($landingpageID, $data, $this->langLandingPages, static::TABLE_LANDING_PAGES_LANG); } } return $data ?? []; } /** * Получение данных страницы по URI * @param string $landingUri URI посадочной страницы * @param bool $enabledOnly только включенные * @return array|bool */ public function landingpageDataByURI($landingUri, $enabledOnly = true) { if (empty($landingUri)) { return false; } $data = $this->db->one_array( 'SELECT P.*, PL.* FROM ' . static::TABLE_LANDING_PAGES . ' P, ' . static::TABLE_LANDING_PAGES_LANG . ' PL WHERE P.landing_uri = :uri' . ($enabledOnly ? ' AND P.enabled = 1' : '') . $this->db->langAnd(true, 'P', 'PL'), array(':uri' => $landingUri) ); if (empty($data)) { return false; } return $data; } /** * Поиск подходящей посадочной страницы на основе вариантов URI текущего запроса * @param array $requestVariations варианты URI текущего запроса * @param bool $enabledOnly только включенные * @return array|bool */ public function landingpageDataByRequest(array $requestVariations, $enabledOnly = true) { if (empty($requestVariations)) { return false; } $uriFilter = array(); $i = 1; foreach ($requestVariations as $v) { $uriFilter[':from' . $i++] = $v; } $data = $this->db->select( 'SELECT P.*, PL.* FROM ' . static::TABLE_LANDING_PAGES . ' P, ' . static::TABLE_LANDING_PAGES_LANG . ' PL WHERE P.landing_uri IN (' . join(', ', array_keys($uriFilter)) . ')' . ($enabledOnly ? ' AND P.enabled = 1' : '') . $this->db->langAnd(true, 'P', 'PL') . ' LIMIT 10', $uriFilter ); if (empty($data)) { return false; } # Сортируем по приоритету if (sizeof($data) > 1) { $sort = array(); foreach ($data as $k => &$v) { $sort[$k] = $v['priority'] = array_search($v['landing_uri'], $requestVariations, true); if (!isset($v['is_relative'])) { $v['is_relative'] = 1; } if (!isset($v['joined'])) { $v['joined'] = 0; } } unset($v); array_multisort($sort, SORT_ASC, $data); } return reset($data); } /** * Сохранение страницы * @param int $landingpageID ID страницы * @param array $data данные страницы * @return bool|int */ public function landingpageSave($landingpageID, array $data) { if (empty($data)) { return false; } $data['modified'] = $this->db->now(); # Дата изменения if ($landingpageID > 0) { $res = $this->db->update(static::TABLE_LANDING_PAGES, array_diff_key($data, $this->langLandingPages), array('id' => $landingpageID)); $this->db->langUpdate($landingpageID, $data, $this->langLandingPages, static::TABLE_LANDING_PAGES_LANG); return ! empty($res); } else { $data['created'] = $this->db->now(); # Дата создания $data['user_id'] = User::id(); # Пользователь $data['user_ip'] = $this->request->remoteAddress(true); # IP адрес $landingpageID = $this->db->insert(static::TABLE_LANDING_PAGES, array_diff_key($data, $this->langLandingPages)); if ($landingpageID > 0) { $this->db->langInsert($landingpageID, $data, $this->langLandingPages, static::TABLE_LANDING_PAGES_LANG); } return $landingpageID; } } /** * Переключатели страницы * @param int $landingpageID ID страницы * @param string $field переключаемое поле * @return mixed|void @see toggleInt */ public function landingpageToggle($landingpageID, $field) { switch ($field) { case 'enabled': { # Включен return $this->toggleInt(static::TABLE_LANDING_PAGES, $landingpageID, $field, 'id'); } } } /** * Удаление страницы * @param int $landingpageID ID страницы * @return bool */ public function landingpageDelete($landingpageID) { if (empty($landingpageID)) { return false; } $res = $this->db->delete(static::TABLE_LANDING_PAGES, ['id' => $landingpageID]); if (! empty($res)) { $this->db->delete(static::TABLE_LANDING_PAGES_LANG, ['id' => $landingpageID]); return true; } return false; } # -------------------------------------------------------------------- # Редиректы /** * Redirect model * @param int|null $id * @param array $columns * @param array $with * @return \bff\modules\seo\models\LandingPage | \bff\db\illuminate\Model |array */ public function redirect($id = null, $columns = ['*'], array $with = array()) { $model = $this->model('Redirect'); if (! empty($id)) { return $model->one($id, $columns, $with); } return $model; } /** * Список редиректов (admin) * @param array $filter фильтр списка * @param bool $countOnly только подсчет кол-ва * @param string $limit * @param string $orderBy * @return mixed */ public function redirectsListing(array $filter, $countOnly = false, $limit = '', $orderBy = '') { $filter = $this->prepareFilter($filter, 'R'); if ($countOnly) { return $this->db->one_data('SELECT COUNT(R.id) FROM ' . static::TABLE_REDIRECTS . ' R ' . $filter['where'], $filter['bind']); } return $this->db->select('SELECT R.* FROM ' . static::TABLE_REDIRECTS . ' R ' . $filter['where'] . ( ! empty($orderBy) ? ' ORDER BY ' . $orderBy : '') . $limit, $filter['bind']); } /** * Получение данных о редиректах по подстроке запроса * @param array $uri варианты URI текущего запроса * @param bool $enabledOnly только включенные * @return array */ public function redirectsByRequest(array $uri, $enabledOnly = true) { if (empty($uri)) { return []; } $fromFilter = []; $i = 1; foreach ($uri as $v) { $fromFilter[':from' . $i++] = $v; } $data = $this->db->select('SELECT R.id, R.from_uri, R.to_uri, R.status, R.add_extra, R.add_query, R.is_relative FROM ' . static::TABLE_REDIRECTS . ' R WHERE R.from_uri IN (' . join(', ', array_keys($fromFilter)) . ')' . ($enabledOnly ? ' AND R.enabled = 1' : '') . ' LIMIT 10', $fromFilter); if (empty($data)) { return []; } # Сортируем по приоритету if (sizeof($data) > 1) { $sort = []; foreach ($data as $k => &$v) { $sort[$k] = $v['priority'] = array_search($v['from_uri'], $uri, true); } unset($v); array_multisort($sort, SORT_ASC, $data); } return reset($data); } /** * Получение данных о редиректе * @param int $redirectID $redirectID редиректа * @return array */ public function redirectData($redirectID) { return $this->db->one_array( 'SELECT R.* FROM ' . static::TABLE_REDIRECTS . ' R WHERE R.id = :id', [':id' => $redirectID] ); } /** * Сохранение редиректа * @param int $redirectID ID редиректа * @param array $data данные * @return bool|int */ public function redirectSave($redirectID, array $data) { if (empty($data)) { return false; } $data['modified'] = $this->db->now(); # Дата изменения if ($redirectID > 0) { $res = $this->db->update(static::TABLE_REDIRECTS, $data, ['id' => $redirectID]); return ! empty($res); } else { $data['created'] = $this->db->now(); # Дата создания $data['user_id'] = $data['user_id'] ?? User::id(); # Пользователь $data['user_ip'] = $data['user_ip'] ?? $this->request->remoteAddress(true); # IP адрес $redirectID = $this->db->insert(static::TABLE_REDIRECTS, $data); return $redirectID; } } /** * Переключатели редиректа * @param int $redirectID ID редиректа * @param string $field переключаемое поле * @return mixed|void @see toggleInt */ public function redirectToggle($redirectID, $field) { switch ($field) { case 'enabled': { # Включен return $this->toggleInt(static::TABLE_REDIRECTS, $redirectID, $field, 'id'); } } } /** * Удаление редиректа * @param int $redirectID ID редиректа * @return bool */ public function redirectDelete($redirectID) { if (empty($redirectID)) { return false; } $res = $this->db->delete(static::TABLE_REDIRECTS, ['id' => $redirectID]); if (! empty($res)) { return true; } return false; } public function getLocaleTables() { return [ static::TABLE_LANDING_PAGES => ['type' => 'table', 'fields' => $this->langLandingPages, 'title' => _t('seo', 'Landing Pages')], ]; } }