PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/backend/controllers/ThemeController.php

https://gitlab.com/makkooz/nikestreetbeat
PHP | 321 lines | 197 code | 48 blank | 76 comment | 22 complexity | e8d731bfac50f93e42c7b2568e01dbe3 MD5 | raw file
  1. <?php
  2. /**
  3. * @link http://www.writesdown.com/
  4. * @copyright Copyright (c) 2015 WritesDown
  5. * @license http://www.writesdown.com/license/
  6. */
  7. namespace backend\controllers;
  8. use common\models\Option;
  9. use Yii;
  10. use yii\base\DynamicModel;
  11. use yii\base\Exception;
  12. use yii\filters\AccessControl;
  13. use yii\filters\VerbFilter;
  14. use yii\helpers\ArrayHelper;
  15. use yii\helpers\FileHelper;
  16. use yii\web\Controller;
  17. use yii\web\UploadedFile;
  18. /**
  19. * ThemeController, controlling the actions for theme.
  20. *
  21. * @author Agiel K. Saputra <13nightevil@gmail.com>
  22. * @since 0.1.0
  23. */
  24. class ThemeController extends Controller
  25. {
  26. /**
  27. * @var string Path to theme directory.
  28. */
  29. private $_dir;
  30. /**
  31. * @var string Path to temporary directory of theme.
  32. */
  33. private $_tmp;
  34. /**
  35. * @var string Path to thumbnail directory of theme.
  36. */
  37. private $_thumbDir;
  38. /**
  39. * @var string Base url of theme thumbnail.
  40. */
  41. private $_thumbBaseUrl;
  42. /**
  43. * @inheritdoc
  44. */
  45. public function behaviors()
  46. {
  47. return [
  48. 'access' => [
  49. 'class' => AccessControl::className(),
  50. 'rules' => [
  51. [
  52. 'actions' => ['index', 'upload', 'detail', 'install', 'delete', 'ajax-detail'],
  53. 'allow' => true,
  54. 'roles' => ['administrator'],
  55. ],
  56. ],
  57. ],
  58. 'verbs' => [
  59. 'class' => VerbFilter::className(),
  60. 'actions' => [
  61. 'install' => ['post'],
  62. 'delete' => ['post'],
  63. ],
  64. ],
  65. ];
  66. }
  67. /**
  68. * Scan theme directory to get list of all available themes.
  69. *
  70. * @return string
  71. */
  72. public function actionIndex()
  73. {
  74. $installed = Option::get('theme');
  75. $themes[] = $this->getConfig($installed);
  76. if (!is_dir($this->_dir)) {
  77. FileHelper::createDirectory($this->_dir, 0755);
  78. }
  79. if (!is_dir($this->_thumbDir)) {
  80. FileHelper::createDirectory($this->_thumbDir, 0755);
  81. }
  82. $arrThemes = scandir($this->_dir);
  83. foreach ($arrThemes as $theme) {
  84. if (is_dir($this->_dir . $theme) && $theme !== '.' && $theme !== '..' && $theme !== $installed) {
  85. $themes[] = $this->getConfig($theme);
  86. }
  87. }
  88. return $this->render('index', [
  89. 'themes' => $themes,
  90. 'installed' => $installed,
  91. ]);
  92. }
  93. /**
  94. * Register new theme.
  95. * Theme zip uploaded to temporary directory and extracted there.
  96. * Check the theme directory and move the first directory of the extracted theme.
  97. * If registration is successful, the browser will be redirected to the 'index' page.
  98. *
  99. * @return string
  100. */
  101. public function actionUpload()
  102. {
  103. $errors = [];
  104. $model = new DynamicModel(['file']);
  105. $model->addRule(['file'], 'required')
  106. ->addRule(['file'], 'file', ['extensions' => 'zip']);
  107. if (!is_dir($this->_dir)) {
  108. FileHelper::createDirectory($this->_dir, 0755);
  109. }
  110. if (!is_dir($this->_tmp)) {
  111. FileHelper::createDirectory($this->_tmp, 0755);
  112. }
  113. if (!is_dir($this->_thumbDir)) {
  114. FileHelper::createDirectory($this->_thumbDir, 0755);
  115. }
  116. if (($model->file = UploadedFile::getInstance($model, 'file')) && $model->validate()) {
  117. $themeTempPath = $this->_tmp . $model->file->name;
  118. if (!$model->file->saveAs($themeTempPath)) {
  119. return $this->render('upload', [
  120. 'model' => $model,
  121. 'errors' => [Yii::t('writesdown', 'Failed to move uploaded file')],
  122. ]);
  123. }
  124. $zipArchive = new \ZipArchive();
  125. $zipArchive->open($themeTempPath);
  126. if (!$zipArchive->extractTo($this->_tmp)) {
  127. $zipArchive->close();
  128. FileHelper::removeDirectory($this->_tmp);
  129. return $this->render('upload', [
  130. 'model' => $model,
  131. 'errors' => [Yii::t('writesdown', 'Failed to extract file.')],
  132. ]);
  133. }
  134. $baseDir = substr($zipArchive->getNameIndex(0), 0, strpos($zipArchive->getNameIndex(0), '/'));
  135. $zipArchive->close();
  136. if (is_dir($this->_dir . $baseDir)) {
  137. FileHelper::removeDirectory($this->_tmp);
  138. $errors[] = Yii::t('writesdown', 'Theme with the same directory already exist.');
  139. } else {
  140. rename($this->_tmp . $baseDir, $this->_dir . $baseDir);
  141. FileHelper::removeDirectory($this->_tmp);
  142. if (is_file($this->_dir . $baseDir . '/screenshot.png')) {
  143. copy($this->_dir . $baseDir . '/screenshot.png', $this->_thumbDir . $baseDir . '.png');
  144. }
  145. foreach (ArrayHelper::getValue($this->getConfig($baseDir), 'upload', []) as $type) {
  146. try {
  147. Yii::createObject($type);
  148. } catch (Exception $e) {
  149. }
  150. }
  151. Yii::$app->getSession()->setFlash('success', Yii::t('writesdown', 'Theme successfully uploaded'));
  152. return $this->redirect(['index']);
  153. }
  154. }
  155. return $this->render('upload', [
  156. 'model' => $model,
  157. 'errors' => $errors,
  158. ]);
  159. }
  160. /**
  161. * Show theme detail based on theme dir then render theme detail view.
  162. *
  163. * @param string $theme
  164. *
  165. * @return string
  166. */
  167. public function actionDetail($theme)
  168. {
  169. return $this->render('detail', [
  170. 'theme' => $this->getConfig($theme),
  171. 'installed' => Option::get('theme'),
  172. ]);
  173. }
  174. /**
  175. * Install selected theme and run install and uninstall action based on config.
  176. *
  177. * @param string $theme
  178. *
  179. * @return \yii\web\Response
  180. */
  181. public function actionInstall($theme)
  182. {
  183. foreach (ArrayHelper::getValue($this->getConfig(Option::get('theme')), 'uninstall', []) as $type) {
  184. try {
  185. Yii::createObject($type);
  186. } catch (Exception $e) {
  187. }
  188. }
  189. foreach (ArrayHelper::getValue($this->getConfig($theme), 'install', []) as $type) {
  190. try {
  191. Yii::createObject($type);
  192. } catch (Exception $e) {
  193. }
  194. }
  195. if (Option::set('theme', $theme)) {
  196. Yii::$app->getSession()->setFlash('success', Yii::t('writesdown', "Theme successfully installed."));
  197. }
  198. return $this->redirect(['index']);
  199. }
  200. /**
  201. * Delete and existing theme and run action based on config.
  202. *
  203. * @param string $theme
  204. *
  205. * @return \yii\web\Response
  206. */
  207. public function actionDelete($theme)
  208. {
  209. if ($theme !== Option::get('theme')) {
  210. foreach (ArrayHelper::getValue($this->getConfig($theme), 'delete', []) as $type) {
  211. try {
  212. Yii::createObject($type);
  213. } catch (Exception $e) {
  214. }
  215. }
  216. FileHelper::removeDirectory($this->_dir . $theme);
  217. if (is_file($this->_thumbDir . $theme . '.png')) {
  218. unlink($this->_thumbDir . $theme . '.png');
  219. }
  220. }
  221. return $this->redirect(['index']);
  222. }
  223. /**
  224. * Detail selected theme via AJAX then show it on modal.
  225. *
  226. * @param string $theme
  227. *
  228. * @return string
  229. */
  230. public function actionAjaxDetail($theme)
  231. {
  232. return $this->renderPartial('_theme-detail', [
  233. 'theme' => $this->getConfig($theme),
  234. 'installed' => Option::get('theme'),
  235. ]);
  236. }
  237. /**
  238. * @inheritdoc
  239. */
  240. public function beforeAction($action)
  241. {
  242. if (parent::beforeAction($action)) {
  243. $this->_dir = Yii::getAlias('@themes/');
  244. $this->_tmp = Yii::getAlias('@common/tmp/themes/');
  245. $this->_thumbDir = Yii::getAlias('@webroot/themes/');
  246. $this->_thumbBaseUrl = Yii::getAlias('@web/themes/');
  247. return true;
  248. }
  249. return false;
  250. }
  251. /**
  252. * Get theme config based on theme directory;
  253. *
  254. * @param $theme
  255. * @return array|mixed
  256. */
  257. protected function getConfig($theme)
  258. {
  259. $config = [];
  260. $configPath = $this->_dir . $theme . '/config/main.php';
  261. if (is_file($configPath)) {
  262. $config = require($configPath);
  263. }
  264. $config['thumbnail'] = is_file($this->_thumbDir . $theme . '.png')
  265. ? $this->_thumbBaseUrl . $theme . '.png'
  266. : Yii::getAlias('@web/img/themes.png');
  267. $config['directory'] = $theme;
  268. if (!isset($config['info']['Name'])) {
  269. $config['info']['Name'] = $theme;
  270. }
  271. return $config;
  272. }
  273. }