Browse Source

Favicon generator

master
Egorka 6 years ago
parent
commit
8019e95384
  1. 30
      backend/controllers/settings/ListController.php
  2. 6
      backend/messages/ru/main.php
  3. 10
      backend/views/auth/login.php
  4. 3
      backend/views/layouts/main-login.php
  5. 3
      backend/views/layouts/main.php
  6. 34
      backend/views/settings/list/favicon.php
  7. 7
      backend/views/settings/list/index.php
  8. 39
      core/components/TestForm.php
  9. 134
      core/components/favicon/FaviconGenerator.php
  10. 19
      core/components/favicon/browserconfig.php
  11. 48
      core/components/favicon/manifest.php
  12. 37
      core/forms/FaviconForm.php
  13. 7
      core/services/SettingsService.php
  14. 77
      core/widgets/FaviconWidget.php
  15. 5
      frontend/web/themes/start/layouts/main.php

30
backend/controllers/settings/ListController.php

@ -7,7 +7,9 @@
namespace backend\controllers\settings; namespace backend\controllers\settings;
use backend\forms\SettingsSearch; use backend\forms\SettingsSearch;
use core\component\favicon\FaviconGenerator;
use core\entities\Settings; use core\entities\Settings;
use core\forms\FaviconForm;
use core\forms\SettingsForm; use core\forms\SettingsForm;
use core\services\SettingsService; use core\services\SettingsService;
use yii\filters\AccessControl; use yii\filters\AccessControl;
@ -16,6 +18,7 @@ use yii\web\Controller;
use backend\components\ToggleAction; use backend\components\ToggleAction;
use Yii; use Yii;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
use yii\web\UploadedFile;
class ListController extends Controller class ListController extends Controller
{ {
@ -40,7 +43,7 @@ class ListController extends Controller
'class' => AccessControl::class, 'class' => AccessControl::class,
'rules' => [ 'rules' => [
[ [
'actions' => ['create', 'view', 'index', 'update', 'delete', 'toggle'], 'actions' => ['create', 'view', 'index', 'update', 'delete', 'toggle', 'favicon'],
'allow' => true, 'allow' => true,
'roles' => ['SettingsManagement'], 'roles' => ['SettingsManagement'],
], ],
@ -146,6 +149,31 @@ class ListController extends Controller
return $this->redirect(['index']); return $this->redirect(['index']);
} }
public function actionFavicon()
{
$form = new FaviconForm();
if ($form->load(Yii::$app->request->post())) {
$form->image = UploadedFile::getInstance($form, 'image');
if ($form->image && $form->validate()) {
if (!file_exists(Yii::getAlias('@staticRoot') . '/images/origin/favicon')) {
mkdir(Yii::getAlias('@staticRoot') . '/images/origin/favicon', 0777, true);
}
$form->image->saveAs(Yii::getAlias('@staticRoot') . '/images/origin/favicon/favicon.png');
$this->_service->newFavicon();
Yii::$app->session->setFlash('success', Yii::t('main', 'Favicon generation complete'));
return $this->redirect(['settings/list/index']);
}
}
return $this->render(
'favicon',
[
'model' => $form,
]
);
}
protected function findModel($section, $key) protected function findModel($section, $key)
{ {
if (($model = Settings::find()->andWhere(['section' => $section])->andWhere(['key' => $key])->one()) !== null) { if (($model = Settings::find()->andWhere(['section' => $section])->andWhere(['key' => $key])->one()) !== null) {

6
backend/messages/ru/main.php

@ -5,6 +5,7 @@ return [
'Description' => 'Описание', 'Description' => 'Описание',
'Keywords' => 'Ключевые слова', 'Keywords' => 'Ключевые слова',
'Sign out' => 'Выход', 'Sign out' => 'Выход',
'Sign in' => 'Вход',
'Profile' => 'Профиль', 'Profile' => 'Профиль',
'Error' => 'Ошибка', 'Error' => 'Ошибка',
'Return to back or login page please.' => 'Вернитесь назад или авторизуйтесь снова.', 'Return to back or login page please.' => 'Вернитесь назад или авторизуйтесь снова.',
@ -41,4 +42,9 @@ return [
'Interface Language' => 'Язык интерфейса', 'Interface Language' => 'Язык интерфейса',
'design' => 'Оформление', 'design' => 'Оформление',
'site' => 'Сайт', 'site' => 'Сайт',
'Change Favicon' => 'Изменить иконку сайта',
'Set Favicon' => 'Новая иконка сайта',
'Image' => 'Изображение',
'Only png files allowed. Minimum size: 200x200. Form: square' => 'Разрешены только png файлы минимального размера 200х200. Форма: квадрат',
'Favicon generation complete' => 'Иконка для сайта обновлена',
]; ];

10
backend/views/auth/login.php

@ -7,7 +7,7 @@ use yii\bootstrap\ActiveForm;
/* @var $form yii\bootstrap\ActiveForm */ /* @var $form yii\bootstrap\ActiveForm */
/* @var $model \core\forms\auth\LoginForm */ /* @var $model \core\forms\auth\LoginForm */
$this->title = 'Sign In'; $this->title = Yii::t('main', 'Sign in');
$fieldOptions1 = [ $fieldOptions1 = [
'options' => ['class' => 'form-group has-feedback'], 'options' => ['class' => 'form-group has-feedback'],
@ -22,10 +22,14 @@ $fieldOptions2 = [
<div class="login-box"> <div class="login-box">
<div class="login-logo"> <div class="login-logo">
<a href="#"><b>Zertex</b>CMS</a> <?php if (file_exists(Yii::getAlias('@static/images/cache/favicon/favicon-96x96.png'))) : ?>
<img style="filter: drop-shadow(0px 0px 5px rgba(0, 0, 0, 0.2));" src="<?= Yii::getAlias('@static/images/cache/favicon/favicon-96x96.png') ?>" alt="Zertex CMS">
<br>
<?php endif; ?>
<a style="filter: drop-shadow(0px 0px 5px rgba(0, 0, 0, 0.2));" href="#"><b>Zertex</b>CMS</a>
</div> </div>
<!-- /.login-logo --> <!-- /.login-logo -->
<div class="login-box-body"> <div class="login-box-body" style="filter: drop-shadow(0px 0px 5px rgba(0, 0, 0, 0.2));">
<p class="login-box-msg"><?= Yii::t('main', 'Sign in to start your session') ?></p> <p class="login-box-msg"><?= Yii::t('main', 'Sign in to start your session') ?></p>
<?= Alert::widget() ?> <?= Alert::widget() ?>

3
backend/views/layouts/main-login.php

@ -1,5 +1,5 @@
<?php <?php
use backend\assets\AppAsset;
use yii\helpers\Html; use yii\helpers\Html;
/* @var $this \yii\web\View */ /* @var $this \yii\web\View */
@ -16,6 +16,7 @@ dmstr\web\AdminLteAsset::register($this);
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<?= Html::csrfMetaTags() ?> <?= Html::csrfMetaTags() ?>
<title><?= Html::encode($this->title) ?></title> <title><?= Html::encode($this->title) ?></title>
<?= \core\widgets\FaviconWidget::widget() ?>
<?php $this->head() ?> <?php $this->head() ?>
</head> </head>
<body class="login-page"> <body class="login-page">

3
backend/views/layouts/main.php

@ -1,4 +1,5 @@
<?php <?php
use yii\helpers\Html; use yii\helpers\Html;
/* @var $this \yii\web\View */ /* @var $this \yii\web\View */
@ -15,7 +16,6 @@ if (Yii::$app->controller->action->id === 'login') {
['content' => $content] ['content' => $content]
); );
} else { } else {
if (class_exists('backend\assets\AppAsset')) { if (class_exists('backend\assets\AppAsset')) {
backend\assets\AppAsset::register($this); backend\assets\AppAsset::register($this);
} else { } else {
@ -34,6 +34,7 @@ if (Yii::$app->controller->action->id === 'login') {
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<?= Html::csrfMetaTags() ?> <?= Html::csrfMetaTags() ?>
<title><?= Html::encode($this->title) ?></title> <title><?= Html::encode($this->title) ?></title>
<?= \core\widgets\FaviconWidget::widget() ?>
<?php $this->head() ?> <?php $this->head() ?>
</head> </head>
<body class="hold-transition skin-blue sidebar-mini"> <body class="hold-transition skin-blue sidebar-mini">

34
backend/views/settings/list/favicon.php

@ -0,0 +1,34 @@
<?php
use core\forms\FaviconForm;
use kartik\form\ActiveForm;
use yii\helpers\Html;
/**
* @var yii\web\View $this
* @var FaviconForm $model
*/
$this->title = Yii::t('main', 'Set Favicon');
$this->params['breadcrumbs'][] = ['label' => Yii::t('main', 'Settings'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="favicon-create">
<div class="box box-default">
<div class="box-body">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'image')->fileInput(['accept' => 'image/png']) ?>
<div class="form-group">
<?= Html::submitButton(Yii::t('buttons', 'Save'), ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

7
backend/views/settings/list/index.php

@ -26,6 +26,13 @@ $this->params['breadcrumbs'][] = $this->title;
['create'], ['create'],
['class' => 'btn btn-success'] ['class' => 'btn btn-success']
) ?> ) ?>
<?=
Html::a(
Yii::t('main', 'Change Favicon'),
['favicon'],
['class' => 'btn btn-default']
) ?>
</p> </p>
<div class="row"> <div class="row">

39
core/components/TestForm.php

@ -1,39 +0,0 @@
<?php
/**
* Created by Error202
* Date: 24.08.2018
*/
namespace core\components;
class TestForm extends LanguageDynamicModel
{
public $name;
public $content;
public $number;
public function rules() {
return array_merge(
parent::rules(),
[
[['name', 'content'], 'required'],
['name', 'string', 'max' => 50],
['content', 'string'],
['number', 'integer'],
]
);
}
public function attributeLabels() {
return array_merge(
parent::attributeLabels(),
[
'name' => \Yii::t('main', 'Name'),
'content' => \Yii::t('main', 'Key'),
'number' => \Yii::t('main', 'Value'),
]
);
}
}

134
core/components/favicon/FaviconGenerator.php

@ -0,0 +1,134 @@
<?php
/**
* Created by Error202
* Date: 03.10.2017
*/
namespace core\components\favicon;
use Yii;
use yii\imagine\Image;
use yii\web\View;
class FaviconGenerator
{
public $originPath;
public $cachePath;
public function __construct()
{
$this->originPath = Yii::getAlias('@staticRoot') . '/images/origin/favicon';
$this->cachePath = Yii::getAlias('@staticRoot') . '/images/cache/favicon';
}
public function generateIcons()
{
if (!file_exists($this->originPath)) {
mkdir($this->originPath, 0777, true);
}
if (!file_exists($this->cachePath)) {
mkdir($this->cachePath, 0777, true);
}
if (file_exists($this->originPath . '/favicon.png')) {
$this->generateFavicons();
$this->generateAndroid();
$this->generateApple();
$this->generateMicrosoft();
$this->generateManifestJson();
$this->generateBrowserConfigXml();
}
}
protected function generateFavicons()
{
foreach ([16, 32, 96, 194] as $s) {
$filename = sprintf('favicon-%sx%s.png', $s, $s);
Image::thumbnail($this->originPath . '/favicon.png', $s, $s)
->save($this->cachePath . '/' . $filename);
}
}
protected function generateAndroid()
{
foreach ([36, 48, 72, 96, 144, 192] as $s) {
$filename = sprintf('android-chrome-%sx%s.png', $s, $s);
Image::thumbnail($this->originPath . '/favicon.png', $s, $s)
->save($this->cachePath . '/' . $filename);
}
}
protected function generateApple()
{
foreach ([57, 60, 72, 76, 114, 120, 144, 152, 180] as $s) {
$filename = sprintf('apple-touch-icon-%sx%s.png', $s, $s);
Image::thumbnail($this->originPath . '/favicon.png', $s, $s)
->save($this->cachePath . '/' . $filename);
if ($s == 180) {
$filename = sprintf('apple-touch-icon.png', $s, $s);
Image::thumbnail($this->originPath . '/favicon.png', $s, $s)
->save($this->cachePath . '/' . $filename);
}
}
}
protected function generateMicrosoft()
{
foreach ([70, 150, 270, 310] as $s) {
$filename = sprintf('mstile-%sx%s.png', $s, $s);
Image::thumbnail($this->originPath . '/favicon.png', $s, $s)
->save($this->cachePath . '/' . $filename);
}
}
protected function generateManifestJson()
{
$cacheUrl = Yii::getAlias('@static') . '/images/cache';
// frontend
file_put_contents(
Yii::getAlias('@frontend/web') . '/' . 'manifest.json',
(new View())->render('@core/components/favicon/manifest.php', [
'appName' => isset(Yii::$app->params['settings']['site']['name']) ? Yii::$app->params['settings']['site']['name'] : Yii::$app->name,
'iconPath' => $cacheUrl . '/favicon'
])
);
// backend
file_put_contents(
Yii::getAlias('@backend/web') . '/' . 'manifest.json',
(new View())->render('@core/components/favicon/manifest.php', [
'appName' => isset(Yii::$app->params['settings']['site']['name']) ? Yii::$app->params['settings']['site']['name'] : Yii::$app->name,
'iconPath' => $cacheUrl . '/favicon'
])
);
}
protected function generateBrowserConfigXml()
{
$cacheUrl = Yii::getAlias('@static') . '/images/cache';
// frontend
file_put_contents(
Yii::getAlias('@frontend/web') . '/' . 'browserconfig.xml',
(new View())->render('@core/components/favicon/browserconfig.php', [
'iconPath' => $cacheUrl . '/favicon'
])
);
// backend
file_put_contents(
Yii::getAlias('@backend/web') . '/' . 'browserconfig.xml',
(new View())->render('@core/components/favicon/browserconfig.php', [
'iconPath' => $cacheUrl . '/favicon'
])
);
}
}

19
core/components/favicon/browserconfig.php

@ -0,0 +1,19 @@
<?php
/**
* @var $this \yii\web\View
* @var $iconPath string
*/
?>
<?= '<?xml version="1.0" encoding="utf-8"?>' ?>
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="<?= $iconPath ?>/mstile-70x70.png"/>
<square150x150logo src="<?= $iconPath ?>/mstile-150x150.png"/>
<square310x310logo src="<?= $iconPath ?>/mstile-310x310.png"/>
<wide310x150logo src="<?= $iconPath ?>/mstile-310x150.png"/>
<TileColor>#ffffff</TileColor>
</tile>
</msapplication>
</browserconfig>

48
core/components/favicon/manifest.php

@ -0,0 +1,48 @@
<?php
/**
* @var $this \yii\web\View
* @var $appName string
* @var $iconPath string
*/
?>
{
"name": "<?= $appName ?>",
"icons": [
{
"src": "<?= $iconPath ?>/android-chrome-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "<?= $iconPath ?>/android-chrome-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "<?= $iconPath ?>/android-chrome-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "<?= $iconPath ?>/android-chrome-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "<?= $iconPath ?>/android-chrome-144x144.png",
"sizes": "144x144",
"type": "image\/png",
"density": "3.0"
},
{
"src": "<?= $iconPath ?>/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image\/png",
"density": "4.0"
}
]
}

37
core/forms/FaviconForm.php

@ -0,0 +1,37 @@
<?php
/**
* Created by Error202
* Date: 11.09.2018
*/
namespace core\forms;
use yii\base\Model;
use Yii;
class FaviconForm extends Model
{
public $image;
public function rules()
{
return [
['image', 'required'],
[['image'], 'image', 'extensions' => 'png', 'minWidth' => 200, 'minHeight' => 200],
];
}
public function attributeLabels()
{
return [
'image' => Yii::t('main', 'Image'),
];
}
public function attributeHints()
{
return [
'image' => Yii::t('main', 'Only png files allowed. Minimum size: 200x200. Form: square'),
];
}
}

7
core/services/SettingsService.php

@ -2,6 +2,7 @@
namespace core\services; namespace core\services;
use core\components\favicon\FaviconGenerator;
use core\entities\Settings; use core\entities\Settings;
use core\forms\SettingsForm; use core\forms\SettingsForm;
use core\repositories\SettingsRepository; use core\repositories\SettingsRepository;
@ -47,4 +48,10 @@ class SettingsService
$settings = $this->_repository->get($section, $key); $settings = $this->_repository->get($section, $key);
$this->_repository->remove($settings); $this->_repository->remove($settings);
} }
public function newFavicon(): void
{
$fg = new FaviconGenerator();
$fg->generateIcons();
}
} }

77
core/widgets/FaviconWidget.php

@ -0,0 +1,77 @@
<?php
/**
* Created by Error202
* Date: 03.10.2017
*/
namespace core\widgets;
use yii\base\Widget;
use yii\helpers\Url;
use Yii;
class FaviconWidget extends Widget
{
public $iconsPath;
public $iconsUrl;
public function run()
{
/** @var \yii\web\View $View */
$View = \Yii::$app->get('view');
$this->iconsPath = Yii::getAlias('@staticRoot') . '/images/cache/favicon';
$this->iconsUrl = Yii::getAlias('@static') . '/images/cache/favicon';
foreach ([16, 32, 96, 194] as $s) {
$filename = sprintf('favicon-%sx%s.png', $s, $s);
$filepath = $this->iconsPath . '/' . $filename;
if (!empty($filepath) && file_exists($filepath)) {
$View->registerLinkTag([
'rel' => 'icon',
'type' => 'image/png',
'href' => Url::to(sprintf('%s/%s', $this->iconsUrl, $filename)),
'sizes' => sprintf('%sx%s', $s, $s),
], basename($filepath));
}
}
$filepath = $this->iconsPath . '/' . 'android-chrome-192x192.png';
if (!empty($filepath) && file_exists($filepath)) {
$View->registerLinkTag([
'rel' => 'icon',
'type' => 'image/png',
'href' => Url::to(sprintf('%s/android-chrome-192x192.png', $this->iconsUrl)),
'sizes' => sprintf('%sx%s', 192, 192),
], basename($filepath));
}
foreach ([57, 60, 72, 76, 114, 120, 144, 152, 180] as $s) {
$filename = sprintf('apple-touch-icon-%sx%s.png', $s, $s);
$filepath = $this->iconsPath . '/' . $filename;
if (!empty($filepath) && file_exists($filepath)) {
$View->registerLinkTag([
'rel' => 'apple-touch-icon',
'type' => 'image/png',
'href' => Url::to(sprintf('%s/%s', $this->iconsUrl, $filename)),
'sizes' => sprintf('%sx%s', $s, $s),
], basename($filepath));
}
}
$filepath = $this->iconsPath . 'mstile-144x144.png';
if (!empty($filepath) && file_exists($filepath)) {
$View->registerMetaTag([
'name' => 'msapplication-TileImage',
'content' => Url::to(sprintf('%s/mstile-144x144.png', $this->iconsUrl)),
], basename($filepath));
}
$filepath = Yii::getAlias('@webroot') . '/' . 'manifest.json';
if (!empty($filepath) && file_exists($filepath)) {
$View->registerLinkTag([
'rel' => 'manifest',
'href' => Url::to(sprintf('%s/manifest.json', Yii::getAlias('@web'))),
], basename($filepath));
}
}
}

5
frontend/web/themes/start/layouts/main.php

@ -19,6 +19,7 @@ rmrevin\yii\fontawesome\cdn\AssetBundle::register($this);
<meta name="author" content="Egor Oldenburger"> <meta name="author" content="Egor Oldenburger">
<title><?= Html::encode($this->title) ?></title> <title><?= Html::encode($this->title) ?></title>
<?= \core\widgets\FaviconWidget::widget() ?>
<?= Html::csrfMetaTags() ?> <?= Html::csrfMetaTags() ?>
<?php $this->head() ?> <?php $this->head() ?>
</head> </head>
@ -29,7 +30,9 @@ rmrevin\yii\fontawesome\cdn\AssetBundle::register($this);
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-dark fixed-top"> <nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container"> <div class="container">
<?= Html::a('Start Bootstrap', ['/site/index'], ['class' => 'navbar-brand']) ?> <?= Html::a('Start Bootstrap', ['/site/index'], ['class' => 'navbar-brand']) ?>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse"
data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>

Loading…
Cancel
Save