Commit aee73024e7bc8ae82b15390c309258d4247ad7c8

Authored by Yarik
1 parent e950ba39

Artbox great prepairings

backend/config/main.php
1 <?php 1 <?php
2 use artbox\core\components\SeoUrlManager; 2 use artbox\core\components\SeoUrlManager;
  3 + use artbox\core\components\Sitemap;
3 use artbox\core\models\Page; 4 use artbox\core\models\Page;
4 - use common\components\Sitemap;  
5 5
6 $params = array_merge( 6 $params = array_merge(
7 require( __DIR__ . '/../../common/config/params.php' ), 7 require( __DIR__ . '/../../common/config/params.php' ),
@@ -18,9 +18,9 @@ @@ -18,9 +18,9 @@
18 'controllerNamespace' => 'backend\controllers', 18 'controllerNamespace' => 'backend\controllers',
19 'bootstrap' => [ 'log' ], 19 'bootstrap' => [ 'log' ],
20 'controllerMap' => [ 20 'controllerMap' => [
21 - 'profile' => 'artbox\core\controllers\ProfileController',  
22 - 'page' => 'artbox\core\controllers\PageController',  
23 - 'alias' => 'artbox\core\controllers\AliasController', 21 + 'profile' => 'artbox\core\controllers\ProfileController',
  22 + 'page' => 'artbox\core\controllers\PageController',
  23 + 'alias' => 'artbox\core\controllers\AliasController',
24 'seo' => 'artbox\core\controllers\SeoController', 24 'seo' => 'artbox\core\controllers\SeoController',
25 'feedback' => 'artbox\core\controllers\FeedbackController', 25 'feedback' => 'artbox\core\controllers\FeedbackController',
26 'weblog-article' => 'artbox\weblog\controllers\ArticleController', 26 'weblog-article' => 'artbox\weblog\controllers\ArticleController',
@@ -35,16 +35,17 @@ @@ -35,16 +35,17 @@
35 'variant-option-complementary' => 'artbox\catalog\controllers\VariantOptionComplController', 35 'variant-option-complementary' => 'artbox\catalog\controllers\VariantOptionComplController',
36 'variant-option-exclusion' => 'artbox\catalog\controllers\VariantOptionExclController', 36 'variant-option-exclusion' => 'artbox\catalog\controllers\VariantOptionExclController',
37 'product-option-complementary' => 'artbox\catalog\controllers\ProductOptionComplController', 37 'product-option-complementary' => 'artbox\catalog\controllers\ProductOptionComplController',
38 - 'product-option-exclusion' => 'artbox\catalog\controllers\ProductOptionExclController',  
39 - 'import' => 'artbox\catalog\controllers\ImportController',  
40 - 'blog-article' => 'artbox\weblog\controllers\ArticleController',  
41 - 'blog-category' => 'artbox\weblog\controllers\CategoryController',  
42 - 'blog-tag' => 'artbox\weblog\controllers\TagController',  
43 - 'order' => 'artbox\order\controllers\OrderController',  
44 - 'order-product' => 'artbox\order\controllers\OrderProductController',  
45 - 'label' => 'artbox\order\controllers\LabelController',  
46 - 'delivery' => 'artbox\order\controllers\DeliveryController',  
47 - 'payment' => 'artbox\order\controllers\PaymentController', 38 + 'product-option-exclusion' => 'artbox\catalog\controllers\ProductOptionExclController',
  39 + 'import' => 'artbox\catalog\controllers\ImportController',
  40 + 'blog-article' => 'artbox\weblog\controllers\ArticleController',
  41 + 'blog-category' => 'artbox\weblog\controllers\CategoryController',
  42 + 'blog-tag' => 'artbox\weblog\controllers\TagController',
  43 + 'order' => 'artbox\order\controllers\OrderController',
  44 + 'order-product' => 'artbox\order\controllers\OrderProductController',
  45 + 'label' => 'artbox\order\controllers\LabelController',
  46 + 'delivery' => 'artbox\order\controllers\DeliveryController',
  47 + 'payment' => 'artbox\order\controllers\PaymentController',
  48 + 'sitemap' => 'artbox\core\controllers\SitemapController',
48 ], 49 ],
49 'components' => [ 50 'components' => [
50 'assetManager' => [ 51 'assetManager' => [
backend/controllers/SitemapController.php deleted
1 -<?php  
2 - namespace backend\controllers;  
3 -  
4 - use common\components\Sitemap;  
5 - use common\models\SitemapDynamic;  
6 - use common\models\SitemapStatic;  
7 - use yii\bootstrap\ActiveForm;  
8 - use yii\bootstrap\Html;  
9 - use yii\filters\AccessControl;  
10 - use yii\helpers\Json;  
11 - use yii\web\Controller;  
12 -  
13 - /**  
14 - * Class SitemapController  
15 - */  
16 - class SitemapController extends Controller  
17 - {  
18 - /**  
19 - * @inheritdoc  
20 - */  
21 - public function behaviors()  
22 - {  
23 - return [  
24 - 'access' => [  
25 - 'class' => AccessControl::className(),  
26 - 'rules' => [  
27 - [  
28 - 'actions' => [  
29 - 'login',  
30 - 'error',  
31 - ],  
32 - 'allow' => true,  
33 - ],  
34 - [  
35 - 'allow' => true,  
36 - 'roles' => [ '@' ],  
37 - ],  
38 - ],  
39 - ],  
40 - ];  
41 - }  
42 -  
43 - /**  
44 - * Action to configure sitemap of the website  
45 - *  
46 - * @return string  
47 - */  
48 - public function actionIndex()  
49 - {  
50 - return $this->render('index');  
51 - }  
52 -  
53 - /**  
54 - * Action to configure sitemap of the website  
55 - *  
56 - * @return string  
57 - */  
58 - public function actionUpdate()  
59 - {  
60 - /**  
61 - * @var Sitemap $sitemap  
62 - */  
63 - $request = \Yii::$app->request;  
64 - // ***** Generate SitemapDynamic models for every entity in Sitemap component  
65 - $sitemap = \Yii::$app->get('sitemap');  
66 - $entities = $sitemap->entities;  
67 - /**  
68 - * @var SitemapDynamic[] $entity_models  
69 - */  
70 - $entity_models = [];  
71 - foreach ($entities as $entity) {  
72 - $entity_model = new SitemapDynamic();  
73 - $entity_model->entity = $entity[ 'class' ];  
74 - $entity_model->status = SitemapDynamic::STATUS_DISABLED;  
75 - $entity_models[] = $entity_model;  
76 - }  
77 - // ***** <<< End  
78 - if ($request->isPost) {  
79 - $success = false;  
80 - // ***** Create SitemapStatic models from POST and delete existing  
81 - $models = [];  
82 - $index = 1;  
83 - foreach ($request->post('SitemapStatic') as $item) {  
84 - $model = new SitemapStatic();  
85 - if ($model->load($item, '') && $model->validate()) {  
86 - $model->id = $index++;  
87 - $models[] = $model;  
88 - }  
89 - }  
90 - if (!empty( $models )) {  
91 - $old = SitemapStatic::find()  
92 - ->all();  
93 - foreach ($old as $item) {  
94 - $item->delete();  
95 - }  
96 - foreach ($models as $model) {  
97 - $model->save(false);  
98 - $success = true;  
99 - }  
100 - }  
101 - // ***** <<< End  
102 - // ***** Create SitemapDynamic models from POST and delete existing  
103 -  
104 - /**  
105 - * @var SitemapDynamic[] $old_entity_models  
106 - */  
107 - $old_entity_models = SitemapDynamic::find()  
108 - ->all();  
109 - foreach ($old_entity_models as $old_entity_model) {  
110 - $old_entity_model->delete();  
111 - }  
112 - $index = 1;  
113 - $entity_models = [];  
114 - foreach ($request->post('SitemapDynamic') as $item) {  
115 - $entity = new SitemapDynamic();  
116 - if ($entity->load($item, '') && $entity->validate()) {  
117 - $entity->id = $index++;  
118 - $entity->save(false);  
119 - $entity_models[] = $entity;  
120 - $success = true;  
121 - }  
122 - }  
123 - if ($success) {  
124 - if ($request->post('action', '') == 'generate') {  
125 - if ($sitemap->generateXML()) {  
126 - \Yii::$app->session->setFlash(  
127 - 'success',  
128 - \Yii::t(  
129 - 'core',  
130 - 'Карта сайта сгенерированна в ' . \Yii::getAlias(  
131 - $sitemap->path . '.'  
132 - )  
133 - )  
134 - );  
135 - }  
136 - }  
137 - return $this->redirect([ 'index' ]);  
138 - }  
139 - // ***** <<< End  
140 - } else {  
141 - // ***** Find existing SitemapStatic models  
142 - $models = SitemapStatic::find()  
143 - ->all();  
144 - if (empty( $models )) {  
145 - $models = [ new SitemapStatic() ];  
146 - }  
147 - // ***** <<< End  
148 - // ***** Fill SitemapDynamic models from Sitemap component with existing models  
149 - /**  
150 - * @var SitemapDynamic[] $old_entity_models  
151 - */  
152 - $old_entity_models = SitemapDynamic::find()  
153 - ->indexBy('entity')  
154 - ->all();  
155 - foreach ($entity_models as $index => $entity_model) {  
156 - if (isset( $old_entity_models[ $entity_model->entity ] )) {  
157 - $entity_model->status = $old_entity_models[ $entity_model->entity ]->status;  
158 - $entity_model->priority = $old_entity_models[ $entity_model->entity ]->priority;  
159 - $entity_model->frequency = $old_entity_models[ $entity_model->entity ]->frequency;  
160 - }  
161 - }  
162 - // ***** <<< End  
163 - }  
164 - return $this->render(  
165 - 'update',  
166 - [  
167 - 'models' => $models,  
168 - 'entity_models' => $entity_models,  
169 - ]  
170 - );  
171 - }  
172 -  
173 - /**  
174 - * Create activeField for static sitemap  
175 - *  
176 - * @return string  
177 - */  
178 - public function actionCreateStatic()  
179 - {  
180 - $content = '';  
181 - $request = \Yii::$app->request;  
182 - $formId = $request->get('formId');  
183 - $count = $request->get('count');  
184 - if (empty( $formId ) || empty( $count )) {  
185 - return $this->renderContent($content);  
186 - }  
187 - $model = new SitemapStatic();  
188 - $form = new ActiveForm();  
189 - $content .= $form->field(  
190 - $model,  
191 - "[$count]url",  
192 - [  
193 - 'options' => [  
194 - 'class' => 'form-group col-xs-5 col-sm-6',  
195 - ],  
196 - ]  
197 - )  
198 - ->textInput()  
199 - ->render();  
200 - $content .= $form->field(  
201 - $model,  
202 - "[$count]frequency",  
203 - [  
204 - 'options' => [  
205 - 'class' => 'form-group col-xs-3 col-sm-3',  
206 - ],  
207 - ]  
208 - )  
209 - ->dropDownList(  
210 - [  
211 - 'always' => 'always',  
212 - 'hourly' => 'hourly',  
213 - 'daily' => 'daily',  
214 - 'weekly' => 'weekly',  
215 - 'monthly' => 'monthly',  
216 - 'yearly' => 'yearly',  
217 - 'never' => 'never',  
218 - ]  
219 - )  
220 - ->render();  
221 - $content .= $form->field(  
222 - $model,  
223 - "[$count]priority",  
224 - [  
225 - 'options' => [  
226 - 'class' => 'form-group col-xs-3 col-sm-2',  
227 - ],  
228 - ]  
229 - )  
230 - ->textInput()  
231 - ->render();  
232 - $content .= Html::icon(  
233 - 'minus',  
234 - [  
235 - 'class' => 'col-xs-1 field-group-remove',  
236 - 'onclick' => 'sitemap_remove(this)',  
237 - ]  
238 - );  
239 - foreach ($form->attributes as $index => $attribute) {  
240 - $content .= Html::script("$('#w0').yiiActiveForm('add', " . Json::htmlEncode($attribute) . ");");  
241 - }  
242 - $content = Html::tag(  
243 - 'div',  
244 - $content,  
245 - [  
246 - 'class' => 'row field-group',  
247 - ]  
248 - );  
249 - $this->layout = false;  
250 - return $this->renderContent($content);  
251 - }  
252 -  
253 - /**  
254 - * Generate sitemap XML to Sitemap::$path  
255 - *  
256 - * @return bool  
257 - */  
258 - public function actionGenerate()  
259 - {  
260 - $response = \Yii::$app->response;  
261 - $response->format = $response::FORMAT_JSON;  
262 - /**  
263 - * @var Sitemap $sitemap  
264 - */  
265 - $sitemap = \Yii::$app->get('sitemap');  
266 - return $sitemap->generateXML();  
267 - }  
268 - }  
269 -  
270 \ No newline at end of file 0 \ No newline at end of file
common/components/Sitemap.php deleted
1 -<?php  
2 - namespace common\components;  
3 -  
4 - use common\models\SitemapDynamic;  
5 - use common\models\SitemapStatic;  
6 - use yii\base\Object;  
7 - use yii\db\ActiveRecord;  
8 - use yii\helpers\Html;  
9 - use yii\web\UrlManager;  
10 -  
11 - class Sitemap extends Object  
12 - {  
13 - public $entities = [];  
14 - public $path = '@frontend/web/sitemap.xml';  
15 - public $url = 'sitemap.xml';  
16 -  
17 - /**  
18 - * Get absolute url to sitemap.xml  
19 - *  
20 - * @return string  
21 - */  
22 - public function getUrl(): string  
23 - {  
24 - /**  
25 - * @var UrlManager $urlManager  
26 - */  
27 - $urlManager = \Yii::$app->get('urlManagerFrontend');  
28 - return $urlManager->createAbsoluteUrl('/' . $this->url);  
29 - }  
30 -  
31 - /**  
32 - * Check whether sitemap.xml exist  
33 - *  
34 - * @return bool  
35 - */  
36 - public function checkFileExist(): bool  
37 - {  
38 - return file_exists(\Yii::getAlias($this->path));  
39 - }  
40 - /**  
41 - * Generate sitemap XML in $path  
42 - *  
43 - * @return bool  
44 - */  
45 - public function generateXML(): bool  
46 - {  
47 - return $this->saveXML($this->generateOneShot());  
48 - }  
49 -  
50 - /**  
51 - * Save generated xml to $path file  
52 - *  
53 - * @param string $xml  
54 - *  
55 - * @return bool  
56 - */  
57 - protected function saveXML(string $xml): bool  
58 - {  
59 - $realpath = \Yii::getAlias($this->path);  
60 - if (file_put_contents($realpath, $xml)) {  
61 - return true;  
62 - } else {  
63 - return false;  
64 - }  
65 - }  
66 -  
67 - /**  
68 - * Generate xml from configs  
69 - *  
70 - * @return string  
71 - */  
72 - public function generateOneShot(): string  
73 - {  
74 - /**  
75 - * @var UrlManager $urlManager  
76 - */  
77 - $urlManager = \Yii::$app->get('urlManagerFrontend');  
78 - $content = '<?xml version="1.0" encoding="UTF-8"?>';  
79 - $content .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';  
80 - /**  
81 - * @var SitemapStatic[] $static  
82 - */  
83 - // ***** Begin generating static pages  
84 - $static = SitemapStatic::find()  
85 - ->all();  
86 - foreach ($static as $item) {  
87 - $content .= Html::tag(  
88 - 'url',  
89 - Html::tag('loc', $item->url) . Html::tag('lastmod', date('Y-m-d')) . Html::tag(  
90 - 'changefreq',  
91 - $item->frequency  
92 - ) . Html::tag('priority', $item->priority)  
93 - );  
94 - }  
95 - // ***** <<< End  
96 - /**  
97 - * @var SitemapDynamic $dynamic  
98 - */  
99 - $dynamic = SitemapDynamic::find()  
100 - ->indexBy('entity')  
101 - ->where([ 'status' => 1 ])  
102 - ->all();  
103 - $entities = $this->entities;  
104 - foreach ($entities as $entity) {  
105 - /**  
106 - * @var string $class  
107 - */  
108 - $class = $entity[ 'class' ];  
109 - /**  
110 - * @var ActiveRecord $classInstance  
111 - */  
112 - $classInstance = new $class();  
113 - if (is_subclass_of($classInstance, ActiveRecord::className())) {  
114 - if (!empty( $dynamic[ $class ] )) {  
115 - /**  
116 - * @var SitemapDynamic $model  
117 - */  
118 - $model = $dynamic[ $class ];  
119 - $query = $classInstance::find();  
120 - if (isset( $entity[ 'conditions' ] )) {  
121 - foreach ($entity[ 'conditions' ] as $condition) {  
122 - $query->where($condition);  
123 - }  
124 - }  
125 - $result = $query->all();  
126 - foreach ($result as $record) {  
127 - $content .= Html::tag(  
128 - 'url',  
129 - Html::tag(  
130 - 'loc',  
131 - $urlManager->createAbsoluteUrl(  
132 - [  
133 - $entity[ 'url' ],  
134 - 'id' => $record->getAttribute('id'),  
135 - ]  
136 - )  
137 - ) . Html::tag('lastmod', date('Y-m-d')) . Html::tag(  
138 - 'changefreq',  
139 - $model->frequency  
140 - ) . Html::tag('priority', $model->priority)  
141 - );  
142 - }  
143 - }  
144 - }  
145 - }  
146 - $content .= '</urlset>';  
147 - return $content;  
148 - }  
149 - }  
150 \ No newline at end of file 0 \ No newline at end of file
common/models/LoginForm.php deleted
1 -<?php  
2 - namespace common\models;  
3 -  
4 - use artbox\order\models\Customer;  
5 - use Yii;  
6 - use yii\base\Model;  
7 -  
8 - /**  
9 - * Login form  
10 - */  
11 - class LoginForm extends Model  
12 - {  
13 - public $username;  
14 - public $password;  
15 - public $rememberMe = true;  
16 - public $returnUrl;  
17 -  
18 - private $_user;  
19 -  
20 - /**  
21 - * @inheritdoc  
22 - */  
23 - public function rules()  
24 - {  
25 - return [  
26 - // username and password are both required  
27 - [  
28 - [  
29 - 'username',  
30 - 'password',  
31 - ],  
32 - 'required',  
33 - ],  
34 - [  
35 - [  
36 - 'returnUrl',  
37 - ],  
38 - 'string',  
39 - ],  
40 - // rememberMe must be a boolean value  
41 - [  
42 - 'rememberMe',  
43 - 'boolean',  
44 - ],  
45 - // password is validated by validatePassword()  
46 - [  
47 - 'password',  
48 - 'validatePassword',  
49 - ],  
50 - ];  
51 - }  
52 -  
53 - /**  
54 - * Validates the password.  
55 - * This method serves as the inline validation for password.  
56 - *  
57 - * @param string $attribute the attribute currently being validated  
58 - * @param array $params the additional name-value pairs given in the rule  
59 - */  
60 - public function validatePassword($attribute, $params)  
61 - {  
62 - if (!$this->hasErrors()) {  
63 - $user = $this->getUser();  
64 - if (!$user || !$user->validatePassword($this->password)) {  
65 - $this->addError($attribute, 'Incorrect username or password.');  
66 - }  
67 - }  
68 - }  
69 -  
70 - /**  
71 - * Logs in a user using the provided username and password.  
72 - *  
73 - * @return bool whether the user is logged in successfully  
74 - */  
75 - public function login()  
76 - {  
77 - if ($this->validate()) {  
78 - return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);  
79 - } else {  
80 - return false;  
81 - }  
82 - }  
83 -  
84 - /**  
85 - * Finds user by [[username]]  
86 - *  
87 - * @return Customer|null  
88 - */  
89 - protected function getUser()  
90 - {  
91 - if ($this->_user === null) {  
92 - $this->_user = Customer::findByUsername($this->username);  
93 - }  
94 -  
95 - return $this->_user;  
96 - }  
97 -  
98 - public function attributeLabels()  
99 - {  
100 - return [  
101 - 'username' => Yii::t('app', 'Логин'),  
102 - 'password' => Yii::t('app', 'Пароль'),  
103 - 'rememberMe' => Yii::t('app', 'Запомнить'),  
104 - ];  
105 - }  
106 - }  
common/models/PasswordResetRequestForm.php deleted
1 -<?php  
2 -  
3 - namespace common\models;  
4 -  
5 - use artbox\order\models\Customer;  
6 - use Yii;  
7 - use yii\base\Model;  
8 -  
9 - /**  
10 - * Password reset request form  
11 - */  
12 - class PasswordResetRequestForm extends Model  
13 - {  
14 - public $email;  
15 - /**  
16 - * @inheritdoc  
17 - */  
18 - public function rules()  
19 - {  
20 - return [  
21 - [  
22 - 'email',  
23 - 'trim',  
24 - ],  
25 - [  
26 - 'email',  
27 - 'required',  
28 - ],  
29 - [  
30 - 'email',  
31 - 'email',  
32 - ],  
33 - [  
34 - 'email',  
35 - 'exist',  
36 - 'targetClass' => '\artbox\order\models\Customer',  
37 - 'filter' => [ 'status' => Customer::STATUS_ACTIVE ],  
38 - 'message' => 'There is no user with this email address.',  
39 - ],  
40 - ];  
41 - }  
42 - /**  
43 - * Sends an email with a link, for resetting the password.  
44 - *  
45 - * @return bool whether the email was send  
46 - */  
47 - public function sendEmail()  
48 - {  
49 - /* @var $user Customer */  
50 - $user = Customer::findOne(  
51 - [  
52 - 'status' => Customer::STATUS_ACTIVE,  
53 - 'email' => $this->email,  
54 - ]  
55 - );  
56 - if (!$user) {  
57 - return false;  
58 - }  
59 -  
60 - if (!Customer::isPasswordResetTokenValid($user->password_reset_token)) {  
61 - $user->generatePasswordResetToken();  
62 - if (!$user->save()) {  
63 - return false;  
64 - }  
65 - }  
66 - return Yii::$app->mailer->compose(  
67 - [  
68 - 'html' => 'passwordResetToken-html',  
69 - 'text' => 'passwordResetToken-text',  
70 - ],  
71 - [ 'user' => $user ]  
72 - )  
73 - ->setFrom([ Yii::$app->params[ 'supportEmail' ] => Yii::$app->name . ' robot' ])  
74 - ->setTo($this->email)  
75 - ->setSubject('Password reset for ' . Yii::$app->name)  
76 - ->send();  
77 - }  
78 - }  
79 \ No newline at end of file 0 \ No newline at end of file
common/models/ResetPasswordForm.php deleted
1 -<?php  
2 -  
3 - namespace common\models;  
4 -  
5 - use artbox\order\models\Customer;  
6 - use yii\base\Model;  
7 - use yii\base\InvalidParamException;  
8 -  
9 - /**  
10 - * Password reset form  
11 - */  
12 - class ResetPasswordForm extends Model  
13 - {  
14 - public $password;  
15 -  
16 - /**  
17 - * @var \artbox\order\models\Customer  
18 - */  
19 - private $_user;  
20 -  
21 - /**  
22 - * Creates a form model given a token.  
23 - *  
24 - * @param string $token  
25 - * @param array $config name-value pairs that will be used to initialize the object properties  
26 - *  
27 - * @throws \yii\base\InvalidParamException if token is empty or not valid  
28 - */  
29 - public function __construct($token, $config = [])  
30 - {  
31 - if (empty($token) || !is_string($token)) {  
32 - throw new InvalidParamException('Password reset token cannot be blank.');  
33 - }  
34 - $this->_user = Customer::findByPasswordResetToken($token);  
35 - if (!$this->_user) {  
36 - throw new InvalidParamException('Wrong password reset token.');  
37 - }  
38 - parent::__construct($config);  
39 - }  
40 -  
41 - /**  
42 - * @inheritdoc  
43 - */  
44 - public function rules()  
45 - {  
46 - return [  
47 - [  
48 - 'password',  
49 - 'required',  
50 - ],  
51 - [  
52 - 'password',  
53 - 'string',  
54 - 'min' => 6,  
55 - ],  
56 - ];  
57 - }  
58 -  
59 - /**  
60 - * Resets password.  
61 - *  
62 - * @return bool if password was reset.  
63 - */  
64 - public function resetPassword()  
65 - {  
66 - $user = $this->_user;  
67 - $user->setPassword($this->password);  
68 - $user->removePasswordResetToken();  
69 -  
70 - return $user->save(false);  
71 - }  
72 - }  
73 \ No newline at end of file 0 \ No newline at end of file
common/models/SignupForm.php deleted
1 -<?php  
2 -  
3 - namespace common\models;  
4 -  
5 - use artbox\order\models\Customer;  
6 - use yii\base\Model;  
7 -  
8 - /**  
9 - * Signup form  
10 - */  
11 - class SignupForm extends Model  
12 - {  
13 - public $username;  
14 - public $email;  
15 - public $password;  
16 -  
17 - /**  
18 - * @inheritdoc  
19 - */  
20 - public function rules()  
21 - {  
22 - return [  
23 - [  
24 - 'username',  
25 - 'trim',  
26 - ],  
27 - [  
28 - 'username',  
29 - 'required',  
30 - ],  
31 - [  
32 - 'username',  
33 - 'unique',  
34 - 'targetClass' => '\artbox\order\models\Customer',  
35 - 'message' => 'This username has already been taken.',  
36 - ],  
37 - [  
38 - 'username',  
39 - 'string',  
40 - 'min' => 2,  
41 - 'max' => 255,  
42 - ],  
43 -  
44 - [  
45 - 'email',  
46 - 'trim',  
47 - ],  
48 - [  
49 - 'email',  
50 - 'required',  
51 - ],  
52 - [  
53 - 'email',  
54 - 'email',  
55 - ],  
56 - [  
57 - 'email',  
58 - 'string',  
59 - 'max' => 255,  
60 - ],  
61 - [  
62 - 'email',  
63 - 'unique',  
64 - 'targetClass' => '\artbox\order\models\Customer',  
65 - 'message' => 'This email address has already been taken.',  
66 - ],  
67 -  
68 - [  
69 - 'password',  
70 - 'required',  
71 - ],  
72 - [  
73 - 'password',  
74 - 'string',  
75 - 'min' => 6,  
76 - ],  
77 - ];  
78 - }  
79 -  
80 - /**  
81 - * Signs user up.  
82 - *  
83 - * @return \artbox\order\models\Customer|null the saved model or null if saving fails  
84 - */  
85 - public function signup()  
86 - {  
87 - if (!$this->validate()) {  
88 - return null;  
89 - }  
90 -  
91 - $user = new Customer();  
92 - $user->username = $this->username;  
93 - $user->email = $this->email;  
94 - $user->setPassword($this->password);  
95 - $user->generateAuthKey();  
96 -  
97 - return $user->save() ? $user : null;  
98 - }  
99 - }  
100 \ No newline at end of file 0 \ No newline at end of file
common/models/SitemapDynamic.php deleted
1 -<?php  
2 - namespace common\models;  
3 -  
4 - use Yii;  
5 - use yii\helpers\ArrayHelper;  
6 - use yii2tech\filedb\ActiveRecord;  
7 -  
8 - /**  
9 - * Class SitemapDynamic  
10 - *  
11 - * @property int $id  
12 - * @property string $entity  
13 - * @property bool $status  
14 - * @property float $priority  
15 - * @property string $frequency  
16 - */  
17 - class SitemapDynamic extends ActiveRecord  
18 - {  
19 -  
20 - const STATUS_ENABLED = 1;  
21 - const STATUS_DISABLED = 0;  
22 -  
23 - /**  
24 - * @inheritdoc  
25 - */  
26 - public static function getDb()  
27 - {  
28 - return \Yii::$app->get('sitemapdb');  
29 - }  
30 -  
31 - /**  
32 - * @inheritdoc  
33 - */  
34 - public function attributes()  
35 - {  
36 - return [  
37 - 'id',  
38 - 'entity',  
39 - 'status',  
40 - 'priority',  
41 - 'frequency',  
42 - ];  
43 - }  
44 -  
45 - /**  
46 - * @inheritdoc  
47 - */  
48 - public static function primaryKey()  
49 - {  
50 - return [ 'id' ];  
51 - }  
52 -  
53 - /**  
54 - * @inheritdoc  
55 - */  
56 - public function rules()  
57 - {  
58 - return [  
59 - [  
60 - [  
61 - 'entity',  
62 - 'status',  
63 - 'priority',  
64 - 'frequency',  
65 - ],  
66 - 'required',  
67 - ],  
68 - [  
69 - [  
70 - 'status',  
71 - ],  
72 - 'boolean',  
73 - ],  
74 - [  
75 - [  
76 - 'entity',  
77 - 'frequency',  
78 - ],  
79 - 'string',  
80 - ],  
81 - [  
82 - [  
83 - 'priority',  
84 - ],  
85 - 'double',  
86 - 'min' => 0,  
87 - 'max' => 1,  
88 - ],  
89 - ];  
90 - }  
91 -  
92 - /**  
93 - * @inheritdoc  
94 - */  
95 - public function attributeLabels()  
96 - {  
97 - return [  
98 - 'id' => Yii::t('core', 'ID'),  
99 - 'entity' => Yii::t('core', 'Model'),  
100 - 'status' => Yii::t('core', 'Status'),  
101 - 'priority' => Yii::t('core', 'Priority'),  
102 - 'frequency' => Yii::t('core', 'Frequency'),  
103 - ];  
104 - }  
105 -  
106 - /**  
107 - * Find maximum ID value from SitemapStatic models  
108 - */  
109 - public static function max(): int  
110 - {  
111 - $models = self::find()  
112 - ->all();  
113 - $array = ArrayHelper::getColumn($models, self::primaryKey()[ 0 ], false);  
114 - if (empty( $array )) {  
115 - return 0;  
116 - } else {  
117 - return max($array);  
118 - }  
119 - }  
120 - }  
121 \ No newline at end of file 0 \ No newline at end of file
common/models/SitemapStatic.php deleted
1 -<?php  
2 - namespace common\models;  
3 -  
4 - use Yii;  
5 - use yii\helpers\ArrayHelper;  
6 - use yii2tech\filedb\ActiveRecord;  
7 -  
8 - /**  
9 - * Class SitemapStatic  
10 - *  
11 - * @property int $id  
12 - * @property string $url  
13 - * @property float $priority  
14 - * @property string $frequency  
15 - */  
16 - class SitemapStatic extends ActiveRecord  
17 - {  
18 - /**  
19 - * @inheritdoc  
20 - */  
21 - public static function getDb()  
22 - {  
23 - return \Yii::$app->get('sitemapdb');  
24 - }  
25 -  
26 - /**  
27 - * @inheritdoc  
28 - */  
29 - public function attributes()  
30 - {  
31 - return [  
32 - 'id',  
33 - 'url',  
34 - 'priority',  
35 - 'frequency',  
36 - ];  
37 - }  
38 -  
39 - /**  
40 - * @inheritdoc  
41 - */  
42 - public static function primaryKey()  
43 - {  
44 - return [ 'id' ];  
45 - }  
46 -  
47 - /**  
48 - * @inheritdoc  
49 - */  
50 - public function rules()  
51 - {  
52 - return [  
53 - [  
54 - [  
55 - 'url',  
56 - 'priority',  
57 - ],  
58 - 'required',  
59 - ],  
60 - [  
61 - [  
62 - 'priority',  
63 - ],  
64 - 'double',  
65 - 'min' => 0,  
66 - 'max' => 1,  
67 - ],  
68 - [  
69 - [  
70 - 'url',  
71 - 'frequency',  
72 - ],  
73 - 'string',  
74 - ],  
75 - ];  
76 - }  
77 -  
78 - /**  
79 - * @inheritdoc  
80 - */  
81 - public function attributeLabels()  
82 - {  
83 - return [  
84 - 'id' => Yii::t('core', 'ID'),  
85 - 'url' => Yii::t('core', 'Url'),  
86 - 'priority' => Yii::t('core', 'Priority'),  
87 - 'frequency' => Yii::t('core', 'Frequency'),  
88 - ];  
89 - }  
90 -  
91 - /**  
92 - * Find maximum ID value from SitemapStatic models  
93 - */  
94 - public static function max(): int  
95 - {  
96 - $models = self::find()  
97 - ->all();  
98 - $array = ArrayHelper::getColumn($models, self::primaryKey()[ 0 ], false);  
99 - if (empty( $array )) {  
100 - return 0;  
101 - } else {  
102 - return max($array);  
103 - }  
104 - }  
105 - }  
106 \ No newline at end of file 0 \ No newline at end of file
console/controllers/CheckController.php
@@ -2,9 +2,7 @@ @@ -2,9 +2,7 @@
2 namespace console\controllers; 2 namespace console\controllers;
3 3
4 use yii\console\Controller; 4 use yii\console\Controller;
5 - use yii\db\Connection;  
6 use yii\db\Exception; 5 use yii\db\Exception;
7 - use yii\helpers\ArrayHelper;  
8 6
9 /** 7 /**
10 * Class CheckController 8 * Class CheckController
frontend/assets/AppAsset.php
@@ -14,7 +14,6 @@ @@ -14,7 +14,6 @@
14 public $css = [ 14 public $css = [
15 'css/animate.css', 15 'css/animate.css',
16 'css/style.css', 16 'css/style.css',
17 - // 'css/style.default.css', // -  
18 'css/owl.carousel.css', 17 'css/owl.carousel.css',
19 'css/owl.theme.css', 18 'css/owl.theme.css',
20 '//fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,500,700,800', 19 '//fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,500,700,800',
frontend/controllers/AccountController.php
@@ -8,8 +8,8 @@ @@ -8,8 +8,8 @@
8 use artbox\order\models\Wishlist; 8 use artbox\order\models\Wishlist;
9 use yii\data\ActiveDataProvider; 9 use yii\data\ActiveDataProvider;
10 use yii\db\ActiveQuery; 10 use yii\db\ActiveQuery;
  11 + use yii\filters\AccessControl;
11 use yii\web\Controller; 12 use yii\web\Controller;
12 - use yii\web\ForbiddenHttpException;  
13 use yii\web\NotFoundHttpException; 13 use yii\web\NotFoundHttpException;
14 use yii\web\Response; 14 use yii\web\Response;
15 15
@@ -20,9 +20,35 @@ @@ -20,9 +20,35 @@
20 */ 20 */
21 class AccountController extends Controller 21 class AccountController extends Controller
22 { 22 {
  23 + /**
  24 + * @inheritdoc
  25 + */
  26 + public function behaviors()
  27 + {
  28 + return [
  29 + 'access' => [
  30 + 'class' => AccessControl::className(),
  31 + 'rules' => [
  32 + [
  33 + 'allow' => true,
  34 + 'roles' => [ '@' ],
  35 + ],
  36 + ],
  37 + ],
  38 + ];
  39 + }
  40 +
  41 + /**
  42 + * Account main page with orders
  43 + *
  44 + * @return string
  45 + */
23 public function actionIndex() 46 public function actionIndex()
24 { 47 {
25 - $user = Customer::findOne(\Yii::$app->user->identity->getId()); 48 + /**
  49 + * @var Customer $user
  50 + */
  51 + $user = \Yii::$app->user->identity;
26 52
27 $orders = $user->getOrders() 53 $orders = $user->getOrders()
28 ->with( 54 ->with(
@@ -46,12 +72,24 @@ @@ -46,12 +72,24 @@
46 ); 72 );
47 } 73 }
48 74
  75 + /**
  76 + * Account detail order page
  77 + *
  78 + * @param $id
  79 + *
  80 + * @return string
  81 + * @throws \yii\web\NotFoundHttpException
  82 + */
49 public function actionOrder($id) 83 public function actionOrder($id)
50 { 84 {
51 /** 85 /**
  86 + * @var Customer $user
  87 + */
  88 + $user = \Yii::$app->user->identity;
  89 + /**
52 * @var Order $order 90 * @var Order $order
53 */ 91 */
54 - $order = Order::find() 92 + $order = $user->getOrders()
55 ->with('orderProducts.variant.product.lang') 93 ->with('orderProducts.variant.product.lang')
56 ->where( 94 ->where(
57 [ 95 [
@@ -62,8 +100,6 @@ @@ -62,8 +100,6 @@
62 100
63 if (empty($order)) { 101 if (empty($order)) {
64 throw new NotFoundHttpException(\Yii::t('app', 'Order not found')); 102 throw new NotFoundHttpException(\Yii::t('app', 'Order not found'));
65 - } elseif ($order->user_id !== \Yii::$app->user->identity->getId()) {  
66 - throw new ForbiddenHttpException();  
67 } 103 }
68 104
69 return $this->render( 105 return $this->render(
@@ -74,6 +110,11 @@ @@ -74,6 +110,11 @@
74 ); 110 );
75 } 111 }
76 112
  113 + /**
  114 + * Acount info page
  115 + *
  116 + * @return string
  117 + */
77 public function actionAccount() 118 public function actionAccount()
78 { 119 {
79 $user = \Yii::$app->user->identity; 120 $user = \Yii::$app->user->identity;
@@ -86,6 +127,11 @@ @@ -86,6 +127,11 @@
86 ); 127 );
87 } 128 }
88 129
  130 + /**
  131 + * Account wishlist page
  132 + *
  133 + * @return string
  134 + */
89 public function actionWishlist() 135 public function actionWishlist()
90 { 136 {
91 /** 137 /**
@@ -114,7 +160,7 @@ @@ -114,7 +160,7 @@
114 ], 160 ],
115 ] 161 ]
116 ); 162 );
117 - 163 +
118 return $this->render( 164 return $this->render(
119 'wishlist', 165 'wishlist',
120 [ 166 [
@@ -122,7 +168,12 @@ @@ -122,7 +168,12 @@
122 ] 168 ]
123 ); 169 );
124 } 170 }
125 - 171 +
  172 + /**
  173 + * Account change password action
  174 + *
  175 + * @return string|\yii\web\Response
  176 + */
126 public function actionChangePassword() 177 public function actionChangePassword()
127 { 178 {
128 /** 179 /**
@@ -165,6 +216,11 @@ @@ -165,6 +216,11 @@
165 216
166 } 217 }
167 218
  219 + /**
  220 + * Account change data action
  221 + *
  222 + * @return string|\yii\web\Response
  223 + */
168 public function actionChangeData() 224 public function actionChangeData()
169 { 225 {
170 /** 226 /**
@@ -188,6 +244,11 @@ @@ -188,6 +244,11 @@
188 ); 244 );
189 } 245 }
190 246
  247 + /**
  248 + * Account delete from wishlist action
  249 + *
  250 + * @return array
  251 + */
191 public function actionWishlistDelete() 252 public function actionWishlistDelete()
192 { 253 {
193 \Yii::$app->response->format = Response::FORMAT_JSON; 254 \Yii::$app->response->format = Response::FORMAT_JSON;
@@ -201,21 +262,22 @@ @@ -201,21 +262,22 @@
201 ->andWhere( 262 ->andWhere(
202 [ 263 [
203 'variant_id' => \Yii::$app->request->post('variant'), 264 'variant_id' => \Yii::$app->request->post('variant'),
204 - 265 +
205 ] 266 ]
206 ) 267 )
207 ->one(); 268 ->one();
208 if (!empty($model) && $model->delete()) { 269 if (!empty($model) && $model->delete()) {
209 return [ 270 return [
210 'success' => true, 271 'success' => true,
211 - 'message' => 'Товар удален из избранного', 272 + 'message' => \Yii::t('app', 'Товар удален из избранного'),
212 ]; 273 ];
213 } 274 }
214 - 275 +
215 return [ 276 return [
216 'success' => false, 277 'success' => false,
217 - 'message' => 'Ошибка', 278 + 'message' => \Yii::t('app', 'Ошибка'),
218 ]; 279 ];
219 } 280 }
  281 + return [];
220 } 282 }
221 } 283 }
222 \ No newline at end of file 284 \ No newline at end of file
frontend/controllers/PageController.php
@@ -43,7 +43,13 @@ @@ -43,7 +43,13 @@
43 ] 43 ]
44 ); 44 );
45 } 45 }
46 - 46 +
  47 + /**
  48 + * @param $id
  49 + *
  50 + * @return \artbox\core\models\Page
  51 + * @throws \yii\web\NotFoundHttpException
  52 + */
47 protected function findModel($id) 53 protected function findModel($id)
48 { 54 {
49 /** 55 /**
@@ -60,11 +66,11 @@ @@ -60,11 +66,11 @@
60 66
61 if (!empty( $model )) { 67 if (!empty( $model )) {
62 if ($model->lang->alias_id !== Yii::$app->seo->aliasId) { 68 if ($model->lang->alias_id !== Yii::$app->seo->aliasId) {
63 - throw new NotFoundHttpException('Wrong language'); 69 + throw new NotFoundHttpException(\Yii::t('app', 'Wrong language'));
64 } 70 }
65 return $model; 71 return $model;
66 } else { 72 } else {
67 - throw new NotFoundHttpException('Model not found'); 73 + throw new NotFoundHttpException(\Yii::t('app', 'Model not found'));
68 } 74 }
69 } 75 }
70 } 76 }
71 \ No newline at end of file 77 \ No newline at end of file
frontend/controllers/ProductController.php
@@ -83,14 +83,19 @@ @@ -83,14 +83,19 @@
83 ->one(); 83 ->one();
84 if (!empty($model)) { 84 if (!empty($model)) {
85 if ($model->lang->alias_id !== $seo->aliasId) { 85 if ($model->lang->alias_id !== $seo->aliasId) {
86 - throw new NotFoundHttpException('Wrong language'); 86 + throw new NotFoundHttpException(\Yii::t('app', 'Wrong language'));
87 } 87 }
88 return $model; 88 return $model;
89 } else { 89 } else {
90 - throw new NotFoundHttpException('Model not found'); 90 + throw new NotFoundHttpException(\Yii::t('app', 'Model not found'));
91 } 91 }
92 } 92 }
93 93
  94 + /**
  95 + * Remove product from wishlist
  96 + *
  97 + * @return array
  98 + */
94 public function actionWishlistRm() 99 public function actionWishlistRm()
95 { 100 {
96 \Yii::$app->response->format = Response::FORMAT_JSON; 101 \Yii::$app->response->format = Response::FORMAT_JSON;
@@ -113,7 +118,7 @@ @@ -113,7 +118,7 @@
113 'button' => Html::button( 118 'button' => Html::button(
114 Html::tag('i', '', [ 'class' => 'fa fa-heart-o' ]), 119 Html::tag('i', '', [ 'class' => 'fa fa-heart-o' ]),
115 [ 120 [
116 - 'title' => 'Добавить в избранное', 121 + 'title' => \Yii::t('app', 'Добавить в избранное'),
117 'data' => [ 122 'data' => [
118 'toggle' => 'tooltip', 123 'toggle' => 'tooltip',
119 'placement' => 'top', 124 'placement' => 'top',
@@ -125,7 +130,7 @@ @@ -125,7 +130,7 @@
125 'class' => 'wishlist-add btn btn-success pull-right', 130 'class' => 'wishlist-add btn btn-success pull-right',
126 ] 131 ]
127 ), 132 ),
128 - 'message' => 'Товар убран из избранного', 133 + 'message' => \Yii::t('app', 'Товар убран из избранного'),
129 ]; 134 ];
130 } 135 }
131 136
@@ -133,7 +138,7 @@ @@ -133,7 +138,7 @@
133 'button' => Html::button( 138 'button' => Html::button(
134 Html::tag('i', '', [ 'class' => 'fa fa-heart' ]), 139 Html::tag('i', '', [ 'class' => 'fa fa-heart' ]),
135 [ 140 [
136 - 'title' => 'Убрать из избранного', 141 + 'title' => \Yii::t('app', 'Убрать из избранного'),
137 'data' => [ 142 'data' => [
138 'toggle' => 'tooltip', 143 'toggle' => 'tooltip',
139 'placement' => 'top', 144 'placement' => 'top',
@@ -145,11 +150,17 @@ @@ -145,11 +150,17 @@
145 'class' => 'wishlist-rm btn btn-success pull-right', 150 'class' => 'wishlist-rm btn btn-success pull-right',
146 ] 151 ]
147 ), 152 ),
148 - 'message' => 'Товар не найден', 153 + 'message' => \Yii::t('app', 'Товар не найден'),
149 ]; 154 ];
150 } 155 }
  156 + return [];
151 } 157 }
152 158
  159 + /**
  160 + * Add product to wishlist
  161 + *
  162 + * @return array
  163 + */
153 public function actionWishlistAdd() 164 public function actionWishlistAdd()
154 { 165 {
155 \Yii::$app->response->format = Response::FORMAT_JSON; 166 \Yii::$app->response->format = Response::FORMAT_JSON;
@@ -164,7 +175,7 @@ @@ -164,7 +175,7 @@
164 'button' => Html::button( 175 'button' => Html::button(
165 Html::tag('i', '', [ 'class' => 'fa fa-heart' ]), 176 Html::tag('i', '', [ 'class' => 'fa fa-heart' ]),
166 [ 177 [
167 - 'title' => 'Убрать из избранного', 178 + 'title' => \Yii::t('app', 'Убрать из избранного'),
168 'data' => [ 179 'data' => [
169 'toggle' => 'tooltip', 180 'toggle' => 'tooltip',
170 'placement' => 'top', 181 'placement' => 'top',
@@ -184,7 +195,7 @@ @@ -184,7 +195,7 @@
184 'button' => Html::button( 195 'button' => Html::button(
185 Html::tag('i', '', [ 'class' => 'fa fa-heart-o' ]), 196 Html::tag('i', '', [ 'class' => 'fa fa-heart-o' ]),
186 [ 197 [
187 - 'title' => 'Добавить в избранное', 198 + 'title' => \Yii::t('app', 'Добавить в избранное'),
188 'data' => [ 199 'data' => [
189 'toggle' => 'tooltip', 200 'toggle' => 'tooltip',
190 'placement' => 'top', 201 'placement' => 'top',
@@ -196,8 +207,9 @@ @@ -196,8 +207,9 @@
196 'class' => 'wishlist-add btn btn-success pull-right', 207 'class' => 'wishlist-add btn btn-success pull-right',
197 ] 208 ]
198 ), 209 ),
199 - 'message' => 'Товар добавить не вышло', 210 + 'message' => \Yii::t('app', 'Товар добавить не вышло'),
200 ]; 211 ];
201 } 212 }
  213 + return [];
202 } 214 }
203 } 215 }
204 \ No newline at end of file 216 \ No newline at end of file
frontend/controllers/SiteController.php
@@ -7,12 +7,12 @@ @@ -7,12 +7,12 @@
7 use artbox\catalog\models\Product; 7 use artbox\catalog\models\Product;
8 use artbox\core\models\DummyAlias; 8 use artbox\core\models\DummyAlias;
9 use artbox\core\models\Feedback; 9 use artbox\core\models\Feedback;
  10 + use artbox\order\models\LoginForm;
  11 + use artbox\order\models\PasswordResetRequestForm;
  12 + use artbox\order\models\ResetPasswordForm;
  13 + use artbox\order\models\SignupForm;
10 use artbox\weblog\models\Article; 14 use artbox\weblog\models\Article;
11 - use common\models\LoginForm;  
12 - use common\models\PasswordResetRequestForm;  
13 - use common\models\ResetPasswordForm;  
14 use common\models\Settings; 15 use common\models\Settings;
15 - use common\models\SignupForm;  
16 use Yii; 16 use Yii;
17 use yii\base\InvalidParamException; 17 use yii\base\InvalidParamException;
18 use yii\bootstrap\Html; 18 use yii\bootstrap\Html;
frontend/views/layouts/main.php
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 use artbox\core\models\Image; 11 use artbox\core\models\Image;
12 use artbox\core\models\Page; 12 use artbox\core\models\Page;
13 use artbox\core\models\User; 13 use artbox\core\models\User;
14 - use common\models\LoginForm; 14 + use artbox\order\models\LoginForm;
15 use common\models\Newsletter; 15 use common\models\Newsletter;
16 use common\models\SearchForm; 16 use common\models\SearchForm;
17 use common\models\Settings; 17 use common\models\Settings;
frontend/web/css/perfect-scrollbar.min.css 100644 → 100755
frontend/web/js/perfect-scrollbar.min.js 100644 → 100755
frontend/web/sitemap.xml
1 -<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +<?xml version="1.0" encoding="UTF-8"?>
  3 +<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  4 + <url>
  5 + <loc>artbox.dev</loc>
  6 + <lastmod>2017-05-29</lastmod>
  7 + <changefreq>always</changefreq>
  8 + <priority>1</priority>
  9 + </url>
  10 + <url>
  11 + <loc>http://www.artbox.dev/ru/o-nas</loc>
  12 + <lastmod>2017-05-29</lastmod>
  13 + <changefreq>always</changefreq>
  14 + <priority>1</priority>
  15 + </url>
  16 + <url>
  17 + <loc>http://www.artbox.dev/ru/dostavka-i-oplata</loc>
  18 + <lastmod>2017-05-29</lastmod>
  19 + <changefreq>always</changefreq>
  20 + <priority>1</priority>
  21 + </url>
  22 +</urlset>
3 \ No newline at end of file 23 \ No newline at end of file