PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/clients/controller/backend/NodeBuilderGUI/NodeBuilderGUI.php

https://gitlab.com/vanthanhhoh/devlovebook
PHP | 326 lines | 317 code | 6 blank | 3 comment | 67 complexity | eb10e22d832147f85058f3148d1cfba6 MD5 | raw file
  1. <?php
  2. if( !defined('VNP_SYSTEM') && !defined('VNP_APPLICATION') && !defined('ADMIN_AREA') ) die('Access denied!');
  3. Access::RequirePermission(Boot::ADMIN_SESSION);
  4. Boot::Library('NodeBuilder');
  5. define('CONTROLLER_BASE_URL', Router::Generate('Controller',array('controller'=> 'NodeBuilderGUI')));
  6. define('NODE_UTILITY_BASE_URL', Router::Generate('Controller',array('controller'=> 'NodeUtility')));
  7. class NodeBuilderGUI extends Controller {
  8. public $NodeBuilder;
  9. private $NodeTypes = array();
  10. private $NodeType = '';
  11. private $NodeField = '';
  12. private $MergedProfilesFileName = '';
  13. private $NodeProfilePath = '';
  14. private $SubAction = '';
  15. public function Construct() {
  16. NodeBuilder::$NodeBuilderCachePath = CACHE_PATH . 'NodeBuilder' . DIRECTORY_SEPARATOR;
  17. $this->NodeProfilePath = DATA_PATH . 'NodeBuilder' . DIRECTORY_SEPARATOR;
  18. $this->MergedProfilesFilePath =
  19. NodeBuilder::$NodeBuilderCachePath . md5('VNP_MERGED_PROFILE_1906') . '_merge' . NodeBuilder::CACHE_FILE_EXTENSION;
  20. $this->NodeBuilder = new NodeBuilder();
  21. if(!empty($this->Registry['Params'])) {
  22. if(count($this->Registry['Params']) == 1 && isset($this->Registry['Params'][ROUTER_EXTRA_KEY])) $this->NodeType = $this->Registry['Params'][ROUTER_EXTRA_KEY];
  23. elseif((count($this->Registry['Params']) == 1 && !isset($this->Registry['Params'][ROUTER_EXTRA_KEY])) || count($this->Registry['Params']) > 1 ) {
  24. if(isset($this->Registry['Params'][ROUTER_EXTRA_KEY])) $this->NodeField = $this->Registry['Params'][ROUTER_EXTRA_KEY];
  25. $this->NodeType = array_keys($this->Registry['Params']);
  26. $this->NodeType = $this->NodeType[0];
  27. $this->SubAction = $this->Registry['Params'][$this->NodeType];
  28. }
  29. $this->LoadNodeTypeProfiles('default_' . $this->NodeType . '.xml');
  30. }
  31. }
  32. protected function LoadNodeTypeProfiles($NodeTypeFile = '', $Reload = false) {
  33. $XmlPath = $this->NodeProfilePath . $NodeTypeFile;
  34. if($NodeTypeFile != '' || !file_exists($XmlPath))
  35. $this->NodeBuilder->LoadXmlNodeFile($XmlPath, $Reload);
  36. else trigger_error('Node profile doesn\'t exists: ' . $NodeTypeFile, E_USER_ERROR);
  37. }
  38. protected function MergeProfiles() {
  39. $Profiles = glob(NodeBuilder::$NodeBuilderCachePath . '*' . NodeBuilder::CACHE_FILE_EXTENSION);
  40. $_Temp = array('NodeTypes' => array(), 'RequiredNodeTypes' => array(), 'NodeTypeMissed' => array());
  41. foreach($Profiles as $Profile) {
  42. $_CP = unserialize(File::GetContent($Profile));
  43. $_Temp['NodeTypes'] = array_merge($_Temp['NodeTypes'], $_CP['NodeTypes']);
  44. $_Temp['RequiredNodeTypes'] = array_merge($_Temp['RequiredNodeTypes'], $_CP['RequiredNodeTypes']);
  45. $_Temp['NodeTypeMissed'] = array_merge($_Temp['NodeTypeMissed'], $_CP['NodeTypeMissed']);
  46. }
  47. File::Create($this->MergedProfilesFilePath, serialize($_Temp));
  48. }
  49. protected function RebuildProfileCache() {
  50. $PrepareProfiles = glob($this->NodeProfilePath . 'default_*.xml');
  51. foreach($PrepareProfiles as $Profile) {
  52. $this->NodeBuilder->ResetNodeBuilder();
  53. $this->LoadNodeTypeProfiles(basename($Profile), true);
  54. }
  55. $this->MergeProfiles();
  56. $NodeTypes = $this->GetAllNodeTypes();
  57. $MapperContent1 = $MapperContent2 = array();
  58. foreach($NodeTypes['NodeTypes'] as $Name => $NodeType) {
  59. $MapperContent1[$Name] = array('title' => $NodeType['NodeTypeInfo']['title'],
  60. 'split' => $NodeType['NodeTypeInfo']['split'],
  61. 'code' => $NodeType['NodeTypeInfo']['code']);
  62. $MapperContent2[$NodeType['NodeTypeInfo']['code']] = array('controller' => $Name,
  63. 'title' => $NodeType['NodeTypeInfo']['title'],
  64. 'split' => $NodeType['NodeTypeInfo']['split']);
  65. }
  66. $MapperFile = APPLICATION_PATH . 'node_mapper.php';
  67. $MapperContent = '<?php if(!defined(\'VNP_APPLICATION\')) die(\'Stop here\');' . PHP_EOL;
  68. $MapperContent .= '$NodeProfile = ' . var_export($MapperContent1, true) . ';' . PHP_EOL;
  69. $MapperContent .= '$NodeMapper = ' . var_export($MapperContent2, true) . PHP_EOL;
  70. $MapperContent .= '?>';
  71. FILE::Create($MapperFile, $MapperContent);
  72. }
  73. public function Main() {
  74. $this->UseCssComponents('Tables,Glyphicons,Buttons');
  75. if(Input::Post('RescanNodeTypes') == 1 || !file_exists($this->MergedProfilesFilePath))
  76. $this->RebuildProfileCache();
  77. $NodeTypes = $this->GetAllNodeTypes();
  78. $v = $this->View('NodeTypeFromXml')
  79. ->Assign('StructureUrl', Router::GenerateThisRoute())
  80. ->Assign('NodeTypes', $NodeTypes['NodeTypes'])
  81. ->Output();
  82. $this->Render($v);
  83. }
  84. private function GetAllNodeTypes() {
  85. if(!file_exists($this->MergedProfilesFilePath)) $this->MergeProfiles();
  86. return unserialize(File::GetContent($this->MergedProfilesFilePath));
  87. }
  88. public function Structure() {
  89. $this->UseCssComponents('Tables,Glyphicons,Buttons,Labels,InputGroups');
  90. if($this->NodeType != '') {
  91. if(!empty($this->SubAction)) {
  92. if($this->SubAction == 'EditField') {
  93. Helper::PageInfo('Edit field : ' . $this->NodeField . ' <span class="label label-primary">Node type ' . $this->NodeType . '</span>');
  94. Helper::FeaturedPanel('Drop this field',BASE_DIR . 'NodeBuilderGUI/Structure/' . $this->NodeType . '/DropField/' . $this->NodeField . '/','remove');
  95. $NodeField = $this->DetectPostEditField($this->NodeField);
  96. $this->UseCssComponents('Forms,InputGroups');
  97. $v = $this->View('EditField')
  98. ->Assign(array(
  99. 'NodeTypeName' => $this->NodeType,
  100. 'FieldTypes' => $this->NodeBuilder->FieldTypes,
  101. 'DBFieldTypes' => $this->NodeBuilder->DB_FieldTypes,
  102. 'DBCollations' => $this->NodeBuilder->DB_Collations,
  103. 'NodeField' => array_merge($this->NodeBuilder->NodeTypes[$this->NodeType]['NodeFields'][$this->NodeField],$NodeField),
  104. 'NodeTypes' => $this->GetAllNodeTypes()
  105. ))
  106. ->Output();
  107. $this->Render($v);
  108. Theme::UseJquery();
  109. Theme::JqueryUI('sortable');
  110. Theme::JsFooter('NodeBuilderGUI', $this->ControllerAddress(__FILE__) . 'js/node_builder.js');
  111. }
  112. elseif($this->SubAction == 'AddField') {
  113. Helper::PageInfo('Add field <span class="label label-primary">Node type ' . $this->NodeType . '</span>');
  114. $this->UseCssComponents('Forms,InputGroups');
  115. $NodeField = $this->DetectPostAddField();
  116. $v = $this->View('EditField')
  117. ->Assign(array(
  118. 'NodeTypeName' => $this->NodeType,
  119. 'FieldTypes' => $this->NodeBuilder->FieldTypes,
  120. 'DBFieldTypes' => $this->NodeBuilder->DB_FieldTypes,
  121. 'DBCollations' => $this->NodeBuilder->DB_Collations,
  122. 'NodeField' => array_merge($this->NodeBuilder->DefaultFieldAttributes,$NodeField),
  123. 'NodeTypes' => $this->GetAllNodeTypes()
  124. ))
  125. ->Output();
  126. $this->Render($v);
  127. Theme::UseJquery();
  128. Theme::JqueryUI('sortable');
  129. Theme::JsFooter('JsBaseFunctions', APPLICATION_DATA_DIR . 'static/js/base.js');
  130. Theme::JsFooter('NodeBuilderGUI', $this->ControllerAddress(__FILE__) . 'js/node_builder.js');
  131. }
  132. elseif($this->SubAction == 'DropField') {
  133. $this->DetectPostDropField($this->NodeField);
  134. $config = array('action' => Router::GenerateThisRoute(),
  135. 'tokens' => array(array('name' => 'NodeFieldName', 'value' => $this->NodeField))
  136. );
  137. $v = Access::Confirm('Confirm drop this field: ' . $this->NodeField, $config);
  138. $this->Render($v);
  139. }
  140. }
  141. else {
  142. //Theme::JqueryUI('sortable');
  143. //Theme::JsFooter('node_struct', APPLICATION_DATA_DIR . 'static/js/node_struct.js');
  144. Helper::PageInfo('Node type ' . $this->NodeType);
  145. Helper::FeaturedPanel( array(
  146. array( 'text' => 'Add field',
  147. 'url' => Router::GenerateThisRoute() . '/AddField',
  148. 'class' => 'plus'),
  149. array( 'text' => 'Rebuild',
  150. 'url' => CONTROLLER_BASE_URL . '/Rebuild/' . $this->NodeType . '/',
  151. 'class' => 'share-alt'),
  152. array( 'text' => 'Reload',
  153. 'url' => Router::GenerateThisRoute() . '/Reload',
  154. 'class' => 'refresh')
  155. )
  156. );
  157. $v = $this->View('Structure')
  158. ->Assign(array(
  159. 'NodeTypeName' => $this->NodeType,
  160. 'FieldAction' => Router::GenerateThisRoute(),
  161. 'NodeType' => $this->NodeBuilder->NodeTypes[$this->NodeType]
  162. ))
  163. ->Output();
  164. $this->Render($v);
  165. }
  166. }
  167. }
  168. public function Rebuild() {
  169. $this->UseCssComponents('Tables,Glyphicons,Buttons,Labels,InputGroups');
  170. if($this->NodeType != '') {
  171. $this->DetectPostRebuildNodeType($this->NodeType);
  172. $config = array('action' => Router::GenerateThisRoute(),
  173. 'tokens' => array(array('name' => 'NodeType', 'value' => $this->NodeType))
  174. );
  175. $v = Access::Confirm('Confirm rebuild this node type: ' . $this->NodeType, $config);
  176. $this->Render($v);
  177. }
  178. }
  179. private function DetectPostEditField($NodeFieldName) {
  180. if(Input::Post('edit_field') == 1 && Input::Post('field_name') == $NodeFieldName) {
  181. $FieldData = Input::Post('Field');
  182. if($FieldData['type'] == 'multi_value' || $FieldData['type'] == 'single_value') {
  183. $ValueCollections = array();
  184. if(!is_array($FieldData['value'])) $FieldData['value'] = array($FieldData['value']);
  185. $FieldData['value'] = array_filter($FieldData['value']);
  186. if(!empty($FieldData['value']))
  187. foreach($FieldData['value'] as $v)
  188. $ValueCollections[] = $FieldData['options'][$v]['value'];
  189. $FieldData['value'] = implode(',',$ValueCollections);
  190. unset($ValueCollections);
  191. }
  192. $this->NodeBuilder->NodeTypes[$this->NodeType]['NodeFields'][$NodeFieldName] = $FieldData;
  193. $this->NodeBuilder->RebuildProfile();
  194. $this->LoadNodeTypeProfiles('default_' . $this->NodeType . '.xml', true);
  195. $this->MergeProfiles();
  196. return $FieldData;
  197. }
  198. return array();
  199. }
  200. private function DetectPostAddField() {
  201. if(Input::Post('edit_field') == 1) {
  202. $FieldData = Input::Post('Field');
  203. if($FieldData['type'] == 'multi_value' || $FieldData['type'] == 'single_value') {
  204. $ValueCollections = array();
  205. if(!is_array($FieldData['value'])) $FieldData['value'] = array($FieldData['value']);
  206. foreach($FieldData['value'] as $v)
  207. $ValueCollections[] = $FieldData['options'][$v]['value'];
  208. $FieldData['value'] = implode(',',$ValueCollections);
  209. unset($ValueCollections);
  210. }
  211. $this->NodeBuilder->NodeTypes[$this->NodeType]['NodeFields'][$FieldData['name']] = $FieldData;
  212. $this->NodeBuilder->RebuildProfile();
  213. $this->LoadNodeTypeProfiles('default_' . $this->NodeType . '.xml', true);
  214. $this->MergeProfiles();
  215. return $FieldData;
  216. }
  217. return array();
  218. }
  219. private function DetectPostDropField($NodeFieldName) {
  220. if(Input::Post('NodeFieldName') == $NodeFieldName && Access::CheckToken()) {
  221. unset($this->NodeBuilder->NodeTypes[$this->NodeType]['NodeFields'][$NodeFieldName]);
  222. $this->NodeBuilder->RebuildProfile();
  223. Helper::Notify('success', 'Successful drop field ' . $NodeFieldName);
  224. header('REFRESH: 2; url=' . Router::Generate( 'ControllerParams',
  225. array( 'controller' => get_class($this),
  226. 'action' => 'Structure',
  227. 'params' => $this->NodeType
  228. )
  229. ));
  230. }
  231. }
  232. private function DetectPostRebuildNodeType($NodeTypeName) {
  233. if(Input::Post('NodeType') == $NodeTypeName && Access::CheckToken()) {
  234. $db_config = $this->NodeBuilder->NodeTypes[$this->NodeType]['NodeTypeInfo']['db_config'];
  235. $CreateTableResult = $this->NodeBuilder->CreateBaseNodeTable($this->NodeType, $db_config);
  236. $CurrentNodeDB = new NodeBuilder();
  237. $OnlyAdd = false;
  238. if(!file_exists($this->NodeProfilePath . 'current_' . $this->NodeType . '.xml')) {
  239. $_C = File::GetContent($this->NodeProfilePath . 'default_' . $this->NodeType . '.xml');
  240. File::Create($this->NodeProfilePath . 'current_' . $this->NodeType . '.xml', $_C);
  241. $OnlyAdd = true;
  242. }
  243. $CurrentNodeDB->LoadXmlNodeFile($this->NodeProfilePath . 'current_' . $this->NodeType . '.xml');
  244. $ProfileFields = $this->NodeBuilder->NodeTypes[$this->NodeType]['NodeFields'];
  245. $WorkingFields = $CurrentNodeDB->NodeTypes[$this->NodeType]['NodeFields'];
  246. $RemoveFields = array_diff_key($WorkingFields,$ProfileFields);
  247. $AddFields = array_diff_key($ProfileFields,$WorkingFields);
  248. $SkipFields = array_diff_key($WorkingFields,$RemoveFields);
  249. $__Tables = DB::CustomQuery('SHOW TABLES LIKE \'' . $this->NodeType . '\_%\'');
  250. if(!empty($RemoveFields)) {
  251. $DropSql = array();
  252. foreach($RemoveFields as $FieldKey => $Field) $DropSql[] = $FieldKey;
  253. while($__Table = $__Tables->fetch_row()) {
  254. $__TableID = str_replace($this->NodeType . '_', '', $__Table[0]);
  255. if(is_numeric($__TableID))
  256. $this->NodeBuilder->DropFields($this->NodeType . '_' . $__TableID, $DropSql);
  257. }
  258. $this->NodeBuilder->DropFields($this->NodeType, $DropSql);
  259. }
  260. if($OnlyAdd) $AddFields = $ProfileFields;
  261. if(!empty($AddFields)) {
  262. while($__Table = $__Tables->fetch_row()) {
  263. $__TableID = str_replace($this->NodeType . '_', '', $__Table[0]);
  264. if(is_numeric($__TableID))
  265. $this->NodeBuilder->AddFields($this->NodeType . '_' . $__TableID, $AddFields);
  266. }
  267. $this->NodeBuilder->AddFields($this->NodeType, $AddFields);
  268. }
  269. if(!empty($SkipFields)) {
  270. $ModifyFields = array();
  271. foreach($SkipFields as $FKey => $Field) {
  272. if($ProfileFields[$FKey] != $Field)
  273. $ModifyFields[] = array('original' => $Field,
  274. 'modified' => $ProfileFields[$FKey]
  275. );
  276. }
  277. if(sizeof($ModifyFields) > 0) {
  278. while($__Table = $__Tables->fetch_row()) {
  279. $__TableID = str_replace($this->NodeType . '_', '', $__Table[0]);
  280. if(is_numeric($__TableID))
  281. $this->NodeBuilder->ModifyFields($this->NodeType . '_' . $__TableID, $ModifyFields);
  282. }
  283. $this->NodeBuilder->ModifyFields($this->NodeType, $ModifyFields);
  284. }
  285. }
  286. $CurrentNodeDB->NodeTypes[$this->NodeType] = $this->NodeBuilder->NodeTypes[$this->NodeType];
  287. $CurrentNodeDB->RebuildProfile();
  288. $CacheFiles = glob(CACHE_PATH . 'form' . DIRECTORY_SEPARATOR . '*' . $this->NodeType . '.php');
  289. array_map('unlink', $CacheFiles);
  290. NodeBuilder::DeleteCache();
  291. //$this->RebuildProfileCache();
  292. $this->MergeProfiles();
  293. }
  294. }
  295. public function XmlFiles() {
  296. $NodeTypeXmlFiles = glob(DATA_PATH . 'NodeBuilder' . DIRECTORY_SEPARATOR . 'default_*.xml');
  297. $x = $this->View('XmlFiles');
  298. $x->Assign('XmlFiles', $NodeTypeXmlFiles);
  299. $x->Output();
  300. }
  301. public function NodeFieldExtraAttribute() {
  302. $FieldType = Input::Post('FieldType');
  303. if(in_array($FieldType, array('single_value', 'multi_value'))) $tpl = 'ExtraOptionsField';
  304. elseif($FieldType == 'referer' || $FieldType == 'list') $tpl = 'ExtraRefererField';
  305. $this->Render($this->View($tpl)
  306. ->Assign('FieldType', $FieldType)
  307. ->Output(false));
  308. die();
  309. }
  310. public function ListNodeTypes() {
  311. $NodeTypeXmlFiles = glob(DATA_PATH . 'NodeBuilder' . DIRECTORY_SEPARATOR . 'default_*.xml');
  312. $NodeTypes = array();
  313. foreach($NodeTypeXmlFiles as $XmlFile) {
  314. n($XmlFile);
  315. }
  316. }
  317. private function ListAllNodeTypeFiles() {
  318. }
  319. }
  320. ?>