PageRenderTime 25ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/rainlab/builder/classes/ControllerModel.php

https://gitlab.com/gideonmarked/newlifetrainingcenter-v2
PHP | 394 lines | 297 code | 91 blank | 6 comment | 48 complexity | fb68024a340844e5dbf53f54bc454acd MD5 | raw file
  1. <?php namespace RainLab\Builder\Classes;
  2. use ApplicationException;
  3. use Symfony\Component\Yaml\Dumper as YamlDumper;
  4. use SystemException;
  5. use DirectoryIterator;
  6. use Yaml;
  7. use Exception;
  8. use Lang;
  9. use File;
  10. /**
  11. * Represents and manages plugin controllers.
  12. *
  13. * @package rainlab\builder
  14. * @author Alexey Bobkov, Samuel Georges
  15. */
  16. class ControllerModel extends BaseModel
  17. {
  18. public $controller;
  19. public $behaviors = [];
  20. public $baseModelClassName;
  21. public $permissions = [];
  22. public $menuItem;
  23. protected static $fillable = [
  24. 'controller',
  25. 'behaviors',
  26. 'baseModelClassName',
  27. 'permissions',
  28. 'menuItem'
  29. ];
  30. protected $validationRules = [
  31. 'controller' => ['regex:/^[A-Z]+[a-zA-Z0-9_]+$/']
  32. ];
  33. public function load($controller)
  34. {
  35. if (!$this->validateFileName($controller)) {
  36. throw new SystemException('Invalid controller file name: '.$language);
  37. }
  38. $this->controller = $this->trimExtension($controller);
  39. $this->loadControllerBehaviors();
  40. $this->exists = true;
  41. }
  42. public function save()
  43. {
  44. if ($this->isNewModel()) {
  45. $this->generateController();
  46. }
  47. else {
  48. $this->saveController();
  49. }
  50. }
  51. public function fill(array $attributes)
  52. {
  53. parent::fill($attributes);
  54. if (!$this->isNewModel() && is_array($this->behaviors)) {
  55. foreach ($this->behaviors as $class=>&$configuration) {
  56. if (is_scalar($configuration)) {
  57. $configuration = json_decode($configuration, true);
  58. }
  59. }
  60. }
  61. }
  62. public static function listPluginControllers($pluginCodeObj)
  63. {
  64. $controllersDirectoryPath = $pluginCodeObj->toPluginDirectoryPath().'/controllers';
  65. $controllersDirectoryPath = File::symbolizePath($controllersDirectoryPath);
  66. if (!File::isDirectory($controllersDirectoryPath)) {
  67. return [];
  68. }
  69. $result = [];
  70. foreach (new DirectoryIterator($controllersDirectoryPath) as $fileInfo) {
  71. if ($fileInfo->isDir()) {
  72. continue;
  73. }
  74. if ($fileInfo->getExtension() !== 'php') {
  75. continue;
  76. }
  77. $result[] = $fileInfo->getBasename('.php');
  78. }
  79. return $result;
  80. }
  81. public function getBaseModelClassNameOptions($keyValue = null)
  82. {
  83. $models = ModelModel::listPluginModels($this->getPluginCodeObj());
  84. $result = [];
  85. foreach ($models as $model) {
  86. $result[$model->className] = $model->className;
  87. }
  88. return $result;
  89. }
  90. public function getBehaviorsOptions()
  91. {
  92. $library = ControllerBehaviorLibrary::instance();
  93. $behaviors = $library->listBehaviors();
  94. $result = [];
  95. foreach ($behaviors as $behaviorClass=>$behaviorInfo) {
  96. $result[$behaviorClass] = [
  97. $behaviorInfo['name'],
  98. $behaviorInfo['description']
  99. ];
  100. }
  101. return $result;
  102. }
  103. public function getPermissionsOptions()
  104. {
  105. $model = new PermissionsModel();
  106. $model->loadPlugin($this->getPluginCodeObj()->toCode());
  107. $result = [];
  108. foreach ($model->permissions as $permissionInfo) {
  109. if (!isset($permissionInfo['label']) || !isset($permissionInfo['permission'])) {
  110. continue;
  111. }
  112. $result[$permissionInfo['permission']] = Lang::get($permissionInfo['label']);
  113. }
  114. return $result;
  115. }
  116. public function getMenuItemOptions()
  117. {
  118. $model = new MenusModel();
  119. $model->loadPlugin($this->getPluginCodeObj()->toCode());
  120. $result = [];
  121. foreach ($model->menus as $itemInfo) {
  122. if (!isset($itemInfo['label']) || !isset($itemInfo['code'])) {
  123. continue;
  124. }
  125. $itemCode = $itemInfo['code'];
  126. $result[$itemCode] = Lang::get($itemInfo['label']);
  127. if (!isset($itemInfo['sideMenu'])) {
  128. continue;
  129. }
  130. foreach ($itemInfo['sideMenu'] as $itemInfo) {
  131. if (!isset($itemInfo['label']) || !isset($itemInfo['code'])) {
  132. continue;
  133. }
  134. $subItemCode = $itemInfo['code'];
  135. $result[$itemCode.'||'.$subItemCode] = str_repeat('&nbsp;', 4).Lang::get($itemInfo['label']);
  136. }
  137. }
  138. return $result;
  139. }
  140. public function getControllerFilePath($controllerFilesDirectory = false)
  141. {
  142. $pluginCodeObj = $this->getPluginCodeObj();
  143. $controllersDirectoryPath = File::symbolizePath($pluginCodeObj->toPluginDirectoryPath().'/controllers');
  144. if (!$controllerFilesDirectory) {
  145. return $controllersDirectoryPath.'/'.$this->controller.'.php';
  146. }
  147. return $controllersDirectoryPath.'/'.strtolower($this->controller);
  148. }
  149. public static function getPluginRegistryData($pluginCode, $subtype)
  150. {
  151. $pluginCodeObj = new PluginCode($pluginCode);
  152. $urlBase = $pluginCodeObj->toUrl().'/';
  153. $controllers = self::listPluginControllers($pluginCodeObj);
  154. $result = [];
  155. foreach ($controllers as $controler) {
  156. $controllerPath = strtolower(basename($controler));
  157. $url = $urlBase.$controllerPath;
  158. $result[$url] = $url;
  159. }
  160. return $result;
  161. }
  162. protected function saveController()
  163. {
  164. $this->validate();
  165. $controllerPath = $this->getControllerFilePath();
  166. if (!File::isFile($controllerPath)) {
  167. throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_controller_not_found'));
  168. }
  169. if (!is_array($this->behaviors)) {
  170. throw new SystemException('The behaviors data should be an array.');
  171. }
  172. $fileContents = File::get($controllerPath);
  173. $parser = new ControllerFileParser($fileContents);
  174. $behaviors = $parser->listBehaviors();
  175. if (!$behaviors) {
  176. throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_controller_has_no_behaviors'));
  177. }
  178. $library = ControllerBehaviorLibrary::instance();
  179. foreach ($behaviors as $behaviorClass) {
  180. $behaviorInfo = $library->getBehaviorInfo($behaviorClass);
  181. if (!$behaviorInfo) {
  182. continue;
  183. }
  184. $propertyName = $behaviorInfo['configPropertyName'];
  185. $propertyValue = $parser->getStringPropertyValue($propertyName);
  186. if (!strlen($propertyValue)) {
  187. continue;
  188. }
  189. if (array_key_exists($behaviorClass, $this->behaviors)) {
  190. $this->saveBehaviorConfiguration($propertyValue, $this->behaviors[$behaviorClass], $behaviorClass);
  191. }
  192. }
  193. }
  194. protected function generateController()
  195. {
  196. $this->validationMessages = [
  197. 'controller.regex' => Lang::get('rainlab.builder::lang.controller.error_controller_name_invalid')
  198. ];
  199. $this->validationRules['controller'][] = 'required';
  200. $this->validate();
  201. $generator = new ControllerGenerator($this);
  202. $generator->generate();
  203. }
  204. protected function loadControllerBehaviors()
  205. {
  206. $filePath = $this->getControllerFilePath();
  207. if (!File::isFile($filePath)) {
  208. throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_controller_not_found'));
  209. }
  210. $fileContents = File::get($filePath);
  211. $parser = new ControllerFileParser($fileContents);
  212. $behaviors = $parser->listBehaviors();
  213. if (!$behaviors) {
  214. throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_controller_has_no_behaviors'));
  215. }
  216. $library = ControllerBehaviorLibrary::instance();
  217. $this->behaviors = [];
  218. foreach ($behaviors as $behaviorClass) {
  219. $behaviorInfo = $library->getBehaviorInfo($behaviorClass);
  220. if (!$behaviorInfo) {
  221. continue;
  222. }
  223. $propertyName = $behaviorInfo['configPropertyName'];
  224. $propertyValue = $parser->getStringPropertyValue($propertyName);
  225. if (!strlen($propertyValue)) {
  226. continue;
  227. }
  228. $configuration = $this->loadBehaviorConfiguration($propertyValue, $behaviorClass);
  229. if ($configuration === false) {
  230. continue;
  231. }
  232. $this->behaviors[$behaviorClass] = $configuration;
  233. }
  234. }
  235. protected function loadBehaviorConfiguration($fileName, $behaviorClass)
  236. {
  237. if (!preg_match('/^[a-z0-9\.\-_]+$/i', $fileName)) {
  238. return false;
  239. }
  240. $extension = pathinfo($fileName, PATHINFO_EXTENSION);
  241. if (strlen($extension) && $extension != 'yaml') {
  242. return false;
  243. }
  244. $controllerPath = $this->getControllerFilePath(true);
  245. $filePath = $controllerPath.'/'.$fileName;
  246. if (!File::isFile($filePath)) {
  247. return false;
  248. }
  249. try {
  250. return Yaml::parse(File::get($filePath));
  251. }
  252. catch (Exception $ex) {
  253. throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_invalid_yaml_configuration', ['file'=>$fileName]));
  254. }
  255. }
  256. protected function saveBehaviorConfiguration($fileName, $configuration, $behaviorClass)
  257. {
  258. if (!preg_match('/^[a-z0-9\.\-_]+$/i', $fileName)) {
  259. throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_invalid_config_file_name', ['file'=>$fileName, 'class'=>$behaviorClass]));
  260. }
  261. $extension = pathinfo($fileName, PATHINFO_EXTENSION);
  262. if (strlen($extension) && $extension != 'yaml') {
  263. throw new ApplicationException(Lang::get('rainlab.builder::lang.controller.error_file_not_yaml', ['file'=>$fileName, 'class'=>$behaviorClass]));
  264. }
  265. $controllerPath = $this->getControllerFilePath(true);
  266. $filePath = $controllerPath.'/'.$fileName;
  267. $fileDirectory = dirname($filePath);
  268. if (!File::isDirectory($fileDirectory)) {
  269. if (!File::makeDirectory($fileDirectory, 0777, true, true)) {
  270. throw new ApplicationException(Lang::get('rainlab.builder::lang.common.error_make_dir', ['name'=>$fileDirectory]));
  271. }
  272. }
  273. $dumper = new YamlDumper();
  274. if ($configuration !== null) {
  275. $yamlData = $dumper->dump($configuration, 20, 0, false, true);
  276. }
  277. else {
  278. $yamlData = '';
  279. }
  280. if (@File::put($filePath, $yamlData) === false) {
  281. throw new ApplicationException(Lang::get('rainlab.builder::lang.yaml.save_error', ['name'=>$filePath]));
  282. }
  283. @File::chmod($filePath);
  284. }
  285. protected function trimExtension($fileName)
  286. {
  287. if (substr($fileName, -4) == '.php') {
  288. return substr($fileName, 0, -4);
  289. }
  290. return $fileName;
  291. }
  292. protected function validateFileName($fileName)
  293. {
  294. if (!preg_match('/^[a-z0-9\.\-_]+$/i', $fileName)) {
  295. return false;
  296. }
  297. $extension = pathinfo($fileName, PATHINFO_EXTENSION);
  298. if (strlen($extension) && $extension != 'php') {
  299. return false;
  300. }
  301. return true;
  302. }
  303. }