PageRenderTime 51ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Standard/Controller/Model.php

https://github.com/18thstreetmike/sodapop_for_codaserver
PHP | 655 lines | 631 code | 17 blank | 7 comment | 162 complexity | 6ee7a637ceeda3e4ebfd50dd2743a8d6 MD5 | raw file
  1. <?php
  2. /**
  3. * Description of indexController
  4. *
  5. * @author michaelarace
  6. */
  7. class Standard_Controller_Model extends Sodapop_Controller {
  8. protected $model;
  9. protected $modelClassname = '';
  10. protected $listSelectClause = '';
  11. protected $listFromClause = '';
  12. protected $joinedTables = array();
  13. protected $selectedColumns = array();
  14. public function __call($name, $arguments) {
  15. if (substr($name, -6) == 'Action') {
  16. $actionName = substr($name, 0, strlen($name) - 6);
  17. if ($this->model instanceof Sodapop_Database_Form_Abstract) {
  18. } else {
  19. if ($this->user->hasTablePermission(strtolower(Sodapop_Inflector::camelCapsToUnderscores($this->modelClassname, false)), strtoupper($actionName))) {
  20. $this->viewAction($actionName);
  21. } else {
  22. $this->viewAction();
  23. }
  24. }
  25. }
  26. }
  27. public function preDispatch() {
  28. $modelClassname = str_replace('Controller','', get_class($this));
  29. $this->modelClassname = $modelClassname;
  30. $this->model = new $modelClassname();
  31. $this->listFromClause = strtolower(Sodapop_Inflector::camelCapsToUnderscores($modelClassname, false)).' AS '.$this->createAlias($modelClassname).' ';
  32. if ($this->model instanceof Sodapop_Database_Form_Abstract) {
  33. $this->listFromClause .= ' INNER JOIN '.$this->model->getStatusTableName().' AS model_statuses ON model_statuses.id = '.$this->createAlias($modelClassname).'.status_id ';
  34. $this->joinedTables[] = 'model_statuses';
  35. }
  36. $this->view->stylesheets = array('/styles/style.css');
  37. $this->view->javascripts = array('/scripts/standard.js', '/scripts/jquery-1.4.1.min.js');
  38. $this->view->currentTab = strtolower(substr($modelClassname, 0, 1)).substr($modelClassname, 1);
  39. }
  40. public function indexAction() {
  41. $this->listAction();
  42. }
  43. public function listAction() {
  44. $this->viewPath = 'model/list';
  45. $navigationItem = $this->application->getNavigationItem(strtolower(substr($this->modelClassname, 0, 1)).substr($this->modelClassname, 1));
  46. $this->view->tabTitle = $navigationItem['label'];
  47. if (isset($navigationItem['description'])) {
  48. $this->view->tabDescription = $navigationItem['description'];
  49. } else {
  50. $this->view->tabDescription = '';
  51. }
  52. $filterVars = $this->processListFilterRequest();
  53. $this->view->listState = $this->buildListState($filterVars);
  54. $this->view->filter = $this->buildFilter($filterVars);
  55. $grid = $this->buildGrid($filterVars, $this->model);
  56. $this->view->grid = $grid;
  57. $this->view->data = $this->getData($grid, $filterVars, $this->model);
  58. $this->view->actions = $this->getInitialActions();
  59. }
  60. public function viewAction($actionName = 'View') {
  61. $this->viewPath = 'model/view';
  62. $id = (isset($this->request->variables['id']) ? $this->request->id : (count($this->request->numeric) > 0 && isset($this->request->numeric[0]) ? $this->request->numeric[0] : null));
  63. $filterVars = $this->processListFilterRequest();
  64. $modelClassname = $this->modelClassname;
  65. if (!is_null($id)) {
  66. $model = new $modelClassname($id);
  67. } else {
  68. $model = new $modelClassname();
  69. }
  70. $this->view->actionName = ucwords($actionName);
  71. $this->view->entityName = ucwords(str_replace('_', ' ', Sodapop_Inflector::camelCapsToUnderscores($modelClassname)));
  72. $this->view->controller = $this->modelClassname;
  73. if ($this->request->isPost()) {
  74. try {
  75. $this->processPost($actionName, &$model);
  76. $id = $model->id;
  77. $this->view->successMessage = 'Your information was saved!';
  78. } catch (Sodapop_Database_Exception $e) {
  79. if (count($e->getErrors()) == 1) {
  80. $this->view->errorMessage = $e->getMessage();
  81. } else {
  82. $this->view->errorMessage = 'The following errors have occurred:';
  83. $this->view->errors = $e->getErrors();
  84. }
  85. }
  86. }
  87. $this->view->id = $id;
  88. $form = $this->getModelForm(&$model);
  89. $this->view->form = $form;
  90. $actions = $this->getNextActions($model);
  91. $this->view->renderedForm = $this->renderForm($form, '', count($actions) == 0);
  92. $this->view->actions = $actions;
  93. }
  94. protected function processListFilterRequest(){
  95. $retval = array('numPerPage' => (isset($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($this->model), false)]) && isset($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($this->model), false)]['list_num_per_page']) ? $this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($this->model), false)]['list_num_per_page'] : 10), 'filters' => array(), 'startIndex' => 0, 'orderBy' => (isset($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($this->model), false)]) && isset($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($this->model), false)]['list_order_by']) ? $this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($this->model), false)]['list_order_by'] : 'id'), 'orderDirection' => 'ASC');
  96. foreach($this->request->variables() as $key => $value) {
  97. if (substr($key, 0, 7) == 'filter_') {
  98. $keyName = substr($key, 7);
  99. if ($keyName == 'numPerPage') {
  100. $retval['numPerPage'] = $value;
  101. } else if ($keyName == 'orderBy') {
  102. $retval['orderBy'] = $value;
  103. } else if ($keyName == 'orderDirection') {
  104. $retval['orderDirection'] = $value;
  105. } else if ($keyName == 'startIndex') {
  106. $retval['startIndex'] = $value;
  107. } else {
  108. $retval['filters'][$keyName] = $value;
  109. }
  110. }
  111. }
  112. return $retval;
  113. }
  114. protected function buildListState($filterVars) {
  115. $retval = array();
  116. $retval['sort'] = '&filter_startIndex=0&filter_numPerPage='.$filterVars['numPerPage'];
  117. $retval['nextPage'] = '&filter_startIndex='.($filterVars['startIndex'] + $filterVars['numPerPage']).'&filter_numPerPage='.$filterVars['numPerPage'].'&filter_orderBy='.$filterVars['orderBy'].'&filter_orderDirection='.$filterVars['orderDirection'];
  118. $retval['prevPage'] = '&filter_startIndex='.($filterVars['startIndex'] - $filterVars['numPerPage']).'&filter_numPerPage='.$filterVars['numPerPage'].'&filter_orderBy='.$filterVars['orderBy'].'&filter_orderDirection='.$filterVars['orderDirection'];
  119. $retval['viewItem'] = '?filter_startIndex='.($filterVars['startIndex'] - $filterVars['numPerPage']).'&filter_numPerPage='.$filterVars['numPerPage'].'&filter_orderBy='.$filterVars['orderBy'].'&filter_orderDirection='.$filterVars['orderDirection'];
  120. foreach($filterVars['filters'] as $key => $filter) {
  121. $retval['sort'] .= '&filter_'.$key.'='.urlencode($filter);
  122. $retval['nextPage'] .= '&filter_'.$key.'='.urlencode($filter);
  123. $retval['prevPage'] .= '&filter_'.$key.'='.urlencode($filter);
  124. $retval['viewItem'] .= '&filter_'.$key.'='.urlencode($filter);
  125. }
  126. $retval['filter'] = '';
  127. foreach($filterVars as $key => $filter) {
  128. if ($key != 'filters') {
  129. $retval['filter'] .= '<input type="hidden" name="filter_'.$key.'" value="'.htmlentities($filter).'" />';
  130. }
  131. }
  132. return $retval;
  133. }
  134. protected function buildFilter($filterVars) {
  135. $retval = array('filters' => array(), 'buttonLabel' => (isset($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($this->model), false)]) && isset($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($this->model), false)]['list_filter_label']) ? $this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($this->model), false)]['list_filter_label'] : 'Update') );
  136. if (isset($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($this->model), false)]) && isset($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($this->model), false)]['list_filters'])) {
  137. // grab it from the models file
  138. foreach ($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($this->model), false)]['list_filters'] as $filter) {
  139. if (isset($filter['type']) && $filter['type'] == 'search') {
  140. $retval['filters'][] = array('label' => 'Search', 'id'=> 'search', 'input' => 'text', 'default' => (isset($filterVars['filters']['search']) ? $filterVars['filters']['search'] : ''));
  141. } else if (isset($filter['type']) && $filter['type'] == 'num_per_page') {
  142. $retval['filters'][] = array('label' => '# Per Page', 'id'=> 'numPerPage', 'input' => 'select', 'options' => array('10' => '10', '20' => '20', '50' => '50', '100' => '100'), 'default' => $filterVars['numPerPage']);
  143. } else if (isset($filter['field']) && $filter['field'] == 'status' && $this->model instanceof Sodapop_Database_Form_Abstract) {
  144. $options = array();
  145. if ($filter['include_all']) {
  146. $options[''] = 'All';
  147. }
  148. foreach ($this->model->getFormStatuses() as $statusId => $status) {
  149. $options[$statusId] = $status['display_adjective'];
  150. }
  151. $retval['filters'][] = array('label' => 'Status', 'id' => 'statusId', 'input' => 'select', 'options' => $options, 'default' => (isset($filterVars['filters']['statusId']) ? $filterVars['filters']['statusId'] : ''));
  152. } else {
  153. if (isset($filter['field'])) {
  154. $fieldDef = $this->model->getFieldDefinition(Sodapop_Inflector::underscoresToCamelCaps($filter['field']));
  155. if ($fieldDef) {
  156. if ($fieldDef['type_name'] == 'REFERENCE' && (!$filter['type'] || $filter['type'] == 'select') && $filter['select_field'] && ($this->user->hasTablePermission($fieldDef['ref_table_name'], 'SELECT') || $this->user->hasFormPermission($fieldDef['ref_table_name'], false, 'VIEW'))) {
  157. $options = array();
  158. if ($filter['include_all']) {
  159. $options[''] = 'All';
  160. }
  161. $result = $this->user->connection->runQuery("SELECT id, ".$filter['select_field']." FROM ".$fieldDef['ref_table_name']." ORDER BY ".$filter['select_field']." ASC");
  162. foreach ($result['data'] as $row) {
  163. $options[$row[0]] = $row[1];
  164. }
  165. $retval['filters'][] = array('label' => $fieldDef['display_name'], 'id' => Sodapop_Inflector::underscoresToCamelCaps($filter['field']), 'input' => 'select', 'options' => $options, 'default' => ($filterVars['filters'][Sodapop_Inflector::underscoresToCamelCaps($filter['field'])] ? $filterVars['filters'][Sodapop_Inflector::underscoresToCamelCaps($filter['field'])] : ''));
  166. } else {
  167. $retval['filters'][] = array('label' => $fieldDef['display_name'], 'id' => Sodapop_Inflector::underscoresToCamelCaps($filter['field']), 'input' => 'text', 'default' => ($filterVars['filters'][Sodapop_Inflector::underscoresToCamelCaps($filter['field'])] ? $filterVars['filters'][Sodapop_Inflector::underscoresToCamelCaps($filter['field'])] : ''));
  168. }
  169. }
  170. }
  171. }
  172. }
  173. } else {
  174. $fieldDefs = $this->model->getFieldDefinitions();
  175. foreach($fieldDefs as $fieldDef) {
  176. if ($fieldDef['type_name'] == 'REFERENCE' && ($this->user->hasTablePermission($fieldDef['ref_table_name'], 'SELECT') || $this->user->hasFormPermission($fieldDef['ref_table_name'], false, 'VIEW'))) {
  177. $options = array();
  178. $options[''] = 'All';
  179. $result = $this->user->connection->runQuery("SELECT * FROM ".strtolower($fieldDef['ref_table_name'])." ORDER BY id ASC");
  180. for ($i = 0; $i < count($result['columns']); $i++) {
  181. if ($result['columns'][$i]['columnname'] == 'id') {
  182. break;
  183. }
  184. }
  185. foreach ($result['data'] as $row) {
  186. $options[$row[$i]] = $row[($i == 0 ? 1 : 0)];
  187. }
  188. $retval['filters'][] = array('label' => $fieldDef['display_name'], 'id' => Sodapop_Inflector::underscoresToCamelCaps(strtolower(isset($fieldDef['field_name']) ? $fieldDef['field_name'] : $fieldDef['column_name']), true, false), 'input' => 'select', 'options' => $options, 'default' => (isset($filterVars['filters'][Sodapop_Inflector::underscoresToCamelCaps(strtolower(isset($fieldDef['field_name']) ? $fieldDef['field_name'] : $fieldDef['column_name']), true, false)]) ? $filterVars['filters'][Sodapop_Inflector::underscoresToCamelCaps(strtolower(isset($fieldDef['field_name']) ? $fieldDef['field_name'] : $fieldDef['column_name']), true, false)] : ''));
  189. }
  190. }
  191. $retval['filters'][] = array('label' => 'Search', 'id'=> 'search', 'input' => 'text', 'default' => (isset($filterVars['filters']['search']) ? $filterVars['filters']['search'] : ''));
  192. $retval['filters'][] = array('label' => '# Per Page', 'id'=> 'numPerPage', 'input' => 'select', 'options' => array('10' => '10', '20' => '20', '50' => '50', '100' => '100'), 'default' => $filterVars['numPerPage']);
  193. }
  194. return $retval;
  195. }
  196. protected function buildGrid($filterVars, $model) {
  197. $retval = array('headings' =>array());
  198. if (isset($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($model), false)]) && isset($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($model), false)]['list_fields'])) {
  199. $retval['headings'] = $this->processModelList($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($model), false)]['list_fields'], $filterVars, $model);
  200. } else {
  201. $modelList = array(array('name' => 'id', 'link' => '/'.get_class($model).'/view/:id'));
  202. $fields = $model->getFieldDefinitions();
  203. foreach ($fields as $field) {
  204. if (((isset($field['column_name']) && strtolower($field['column_name']) != 'id') || (isset($field['field_name']) && strtolower($field['field_name']) != 'id')) && strtolower($field['type_name']) != 'reference') {
  205. $modelList[] = array('name' => isset($field['column_name']) ? strtolower($field['column_name']) : strtolower($field['field_name']));
  206. }
  207. }
  208. if ($model instanceof Sodapop_Database_Form_Abstract) {
  209. $modelList[] = array('name' => 'status');
  210. }
  211. $retval['headings'] = $this->processModelList($modelList, $filterVars, $model);
  212. }
  213. return $retval;
  214. }
  215. protected function processModelList($modelList, $filterVars, $model) {
  216. $retval = array();
  217. foreach ($modelList as $listField) {
  218. $heading = array('id' => $listField['name']);
  219. if ($model instanceof Sodapop_Database_Form_Abstract && strtolower($listField['name']) == 'status') {
  220. $heading['label'] = (isset($listField['label']) ? $listField['label'] : 'Status');
  221. if (!array_key_exists('model_statuses.adj_display_name', $this->selectedColumns)) {
  222. $this->listSelectClause .= ($this->listSelectClause == '' ? ' ' : ', ').'model_statuses.adj_display_name AS '.$this->createAlias(get_class($model)).'_status';
  223. $this->selectedColumns['model_statuses.adj_display_name'] = 'STRING';
  224. }
  225. $heading['sortField'] = $this->createAlias(get_class($model)).'_status';
  226. } else {
  227. $fieldDefinition = $model->getFieldDefinition(Sodapop_Inflector::underscoresToCamelCaps($listField['name'], true, false));
  228. if (!is_null($fieldDefinition)) {
  229. $heading['label'] = (isset($listField['label']) ? $listField['label'] : $fieldDefinition['display_name']);
  230. $heading['printExpression'] = array(array('type' => 'field', 'field' => $this->createAlias(get_class($model)).'_'.$listField['name']));
  231. $heading['sortField'] = $this->createAlias(get_class($model)).'_'.$listField['name'];
  232. if (!array_key_exists($this->createAlias(get_class($model)).'.'.$listField['name'], $this->selectedColumns)) {
  233. $this->listSelectClause .= ($this->listSelectClause == '' ? ' ' : ', ').$this->createAlias(get_class($model)).'.'.$listField['name'].' AS '.$this->createAlias(get_class($model)).'_'.$listField['name'];
  234. $this->selectedColumns[$this->createAlias(get_class($model)).'.'.$listField['name']] = $fieldDefinition['type_name'];
  235. }
  236. } else {
  237. $heading['label'] = (isset($listField['label']) ? $listField['label'] : 'Column '.(count($retval) + 1));
  238. if (isset($listField['concat'])) {
  239. $heading['printExpression'] = array();
  240. $concatParts = explode('+', $listField['concat']);
  241. foreach ($concatParts as $concatPart) {
  242. $concatPart = trim($concatPart);
  243. if (substr($concatPart, 0, 1) == "'" && substr($concatPart, strlen($concatPart) - 2, 1) == "'") {
  244. $heading['printExpression'][] = array('type' => 'text', 'text' => substr($concatPart,1, strlen($concatPart) - 2));
  245. } else {
  246. $moreParts = explode('.', $concatPart);
  247. $partDefinition = $model->getFieldDefinition(Sodapop_Inflector::underscoresToCamelCaps($moreParts[0], true, false));
  248. if (!is_null($partDefinition)) {
  249. if (!isset($moreParts[1]) || $partDefinition['type_name'] != 'REFERENCE') {
  250. $columnName = trim($moreParts[0]);
  251. if (!array_key_exists($this->createAlias(get_class($model)).'.'.$columnName, $this->selectedColumns)) {
  252. $this->listSelectClause .= ($this->listSelectClause == '' ? ' ' : ', ').$this->createAlias(get_class($model)).'.'.$columnName.' AS '.$this->createAlias(get_class($model)).'_'.$columnName;
  253. $this->selectedColumns[$this->createAlias(get_class($model)).'.'.$columnName] = $partDefinition['type_name'];
  254. }
  255. $heading['printExpression'][] = array('type' => 'field', 'field' => Sodapop_Inflector::camelCapsToUnderscores(get_class($model), true).'_'.$columnName);
  256. if (!isset($heading['sortField'])) {
  257. $heading['sortField'] = $this->createAlias(get_class($model)).'_'.$columnName;
  258. }
  259. } else {
  260. $childTableClassname = Sodapop_Inflector::underscoresToCamelCaps(strtolower($partDefinition['ref_table_name']), false);
  261. $childObject = new $childTableClassname();
  262. $childPartsDefinition = $childObject->getFieldDefinition(Sodapop_Inflector::underscoresToCamelCaps($moreParts[1], true, false));
  263. if (!is_null($childPartsDefinition)) {
  264. if (!array_key_exists($moreParts[0].'.'.$moreParts[1], $this->selectedColumns)) {
  265. $this->listSelectClause .= ($this->listSelectClause == '' ? ' ' : ', ').$moreParts[0].'.'.$moreParts[1].' AS '.$moreParts[0].'_'.$moreParts[1];
  266. $this->selectedColumns[$moreParts[0].'.'.$moreParts[1]] = $childPartsDefinition['type_name'];
  267. }
  268. if (!in_array($moreParts[0], $this->joinedTables)) {
  269. $this->listFromClause .= ' LEFT OUTER JOIN '.strtolower($partDefinition['ref_table_name']).' AS '.$moreParts[0].' ON '.$moreParts[0].'.id = '.$this->createAlias(get_class($model)).'.'.$moreParts[0].' ';
  270. $this->joinedTables[] = $moreParts[0];
  271. }
  272. $heading['printExpression'][] = array('type' => 'field', 'field' => $moreParts[0].'_'.$moreParts[1]);
  273. if (!isset($heading['sortField'])) {
  274. $heading['sortField'] = $moreParts[0].'_'.$moreParts[1];
  275. }
  276. }
  277. }
  278. }
  279. }
  280. }
  281. }
  282. if (isset($listField['sort'])) {
  283. $heading['sortField'] = str_replace('.', '_', $listField['sort']);
  284. }
  285. }
  286. }
  287. if (isset($listField['link']) && $listField['link']) {
  288. $heading['link'] = $this->processLink($listField['link'], $model);
  289. }
  290. $heading['orderBy'] = $filterVars['orderBy'] == $heading['sortField'];
  291. $heading['orderDirection'] = $filterVars['orderDirection'];
  292. $retval[] = $heading;
  293. }
  294. return $retval;
  295. }
  296. protected function processLink($link, $model) {
  297. $retval = array();
  298. $currentTextNode = '';
  299. $linkParts = explode('/', $link);
  300. foreach($linkParts as $part) {
  301. $part = trim($part);
  302. if (substr($part, 0, 1) == ':') {
  303. $retval[] = array('type' => 'text', 'text' => $currentTextNode.'/');
  304. $currentTextNode = '';
  305. $fieldParts = explode('.', substr($part, 1));
  306. $partDefinition = $model->getFieldDefinition(Sodapop_Inflector::underscoresToCamelCaps($fieldParts[0], true, false));
  307. if (!is_null($partDefinition)) {
  308. if (!isset($fieldParts[1]) || $partDefinition['type_name'] != 'REFERENCE') {
  309. $columnName = trim($fieldParts[0]);
  310. if (!array_key_exists($this->createAlias(get_class($model)).'.'.$columnName, $this->selectedColumns)) {
  311. $this->listSelectClause .= ($this->listSelectClause == '' ? ' ' : ', ').$this->createAlias(get_class($model)).'.'.$columnName.' AS '.$this->createAlias(get_class($model)).'_'.$columnName;
  312. $this->selectedColumns[$this->createAlias(get_class($model)).'.'.$columnName] = $partDefinition['type_name'];
  313. }
  314. $retval[] = array('type' => 'field', 'field' => $this->createAlias(get_class($model)).'_'.$columnName);
  315. } else {
  316. $childTableClassname = Sodapop_Inflector::underscoresToCamelCaps(strtolower($partDefinition['ref_table_name']), false);
  317. $childObject = new $childTableClassname();
  318. $childPartsDefinition = $childObject->getFieldDefinition(Sodapop_Inflector::underscoresToCamelCaps($fieldParts[1], true, false));
  319. if (!is_null($childPartsDefinition)) {
  320. if (!array_key_exists($fieldParts[0].'.'.$fieldParts[1], $this->selectedColumns)) {
  321. $this->listSelectClause .= ($this->listSelectClause == '' ? ' ' : ', ').$fieldParts[0].'.'.$fieldParts[1].' AS '.$fieldParts[0].'_'.$fieldParts[1];
  322. $this->selectedColumns[$fieldParts[0].'.'.$fieldParts[1]] = $childPartsDefinition['type_name'];
  323. }
  324. if (!in_array($fieldParts[0], $this->joinedTables)) {
  325. $this->listFromClause .= ' LEFT OUTER JOIN '.strtolower($partDefinition['ref_table_name']).' AS '.$fieldParts[0].' ON '.$fieldParts[0].'.id = '.$this->createAlias(get_class($model)).'.'.$fieldParts[0].' ';
  326. $this->joinedTables[] = $fieldParts[0];
  327. }
  328. $retval[] = array('type' => 'field', 'field' => $fieldParts[0].'_'.$fieldParts[1]);
  329. }
  330. }
  331. }
  332. } else {
  333. $currentTextNode .= '/'.$part;
  334. }
  335. }
  336. if ($currentTextNode != '') {
  337. $retval[] = array('type' => 'text', 'text' => $currentTextNode);
  338. }
  339. return $retval;
  340. }
  341. protected function getData($grid, $filterVars, $model, $parentTableId = null) {
  342. $whereClause = '';
  343. if (!is_null($parentTableId)) {
  344. $whereClause .= ' WHERE '.$this->createAlias(get_class($model)).".parent_table_id = '".$parentTableId."' ";
  345. }
  346. if (count($filterVars['filters']) > 0) {
  347. foreach($filterVars['filters'] as $key => $filter){
  348. if (trim($filter) != '') {
  349. if ($whereClause == '') {
  350. $whereClause .= ' WHERE ';
  351. } else {
  352. $whereClause .= ' AND ';
  353. }
  354. if ($key == 'search') {
  355. // add each field in the select clause, then add each field from this model
  356. $search = '( ';
  357. foreach ($this->selectedColumns as $column => $typeName) {
  358. if ($typeName != 'INTEGER' && $typeName != 'FLOAT' && $typeName != 'REFERENCE' && $typeName != 'TIMESTAMP') {
  359. if ($search != '( ') {
  360. $search .= ' OR ';
  361. }
  362. $search .= $column ." LIKE '%".str_replace("'", "''", $filter)."%' ";
  363. } else if (is_numeric($filter) && ($typeName == 'INTEGER' || $typeName == 'FLOAT' || $typeName == 'REFERENCE')) {
  364. if ($search != '( ') {
  365. $search .= ' OR ';
  366. }
  367. $search .= $column ." = '".$filter."' ";
  368. }
  369. }
  370. foreach ($model->getFieldDefinitions() as $fieldName => $fieldDefinition) {
  371. $typeName = $fieldDefinition['type_name'];
  372. if (!in_array(Sodapop_Inflector::camelCapsToUnderscores(get_class($model)).'.'.Sodapop_Inflector::camelCapsToUnderscores($fieldName), $this->selectedColumns)) {
  373. if ($typeName != 'INTEGER' && $typeName != 'FLOAT' && $typeName != 'REFERENCE' && $typeName != 'TIMESTAMP') {
  374. if ($search != '( ') {
  375. $search .= ' OR ';
  376. }
  377. $search .= Sodapop_Inflector::camelCapsToUnderscores(get_class($model)).'.'.Sodapop_Inflector::camelCapsToUnderscores($fieldName) ." LIKE '%".str_replace("'", "''", $filter)."%' ";
  378. } else if (is_numeric($filter) && ($typeName == 'INTEGER' || $typeName == 'FLOAT' || $typeName == 'REFERENCE')) {
  379. if ($search != '( ') {
  380. $search .= ' OR ';
  381. }
  382. $search .= $column ." = '".$filter."' ";
  383. }
  384. }
  385. }
  386. $whereClause .= $search . ') ';
  387. } else {
  388. $whereClause .= Sodapop_Inflector::camelCapsToUnderscores($key)." = '".str_replace("'", "''", $filter)."' ";
  389. }
  390. }
  391. // potentially reset
  392. if ($whereClause == ' WHERE ') {
  393. $whereClause = '';
  394. }
  395. }
  396. }
  397. $retval = array('totalRows' => 0, 'numPerPage' => $filterVars['numPerPage'], 'startIndex' => $filterVars['startIndex'], 'data' => array());
  398. $countSelectStatement = 'SELECT count('.$this->createAlias(get_class($model)).'.id) FROM '.$this->listFromClause.' '.$whereClause;
  399. $countResult = $this->user->connection->runQuery($countSelectStatement);
  400. foreach ($countResult['data'] as $row) {
  401. $retval['totalRows'] = $row[0];
  402. }
  403. $orderBy = ' ORDER BY '.$this->createAlias(get_class($model)).'.id '.$filterVars['orderDirection'];
  404. foreach ($grid['headings'] as $gridValue) {
  405. if ($gridValue['id'] == $filterVars['orderBy']) {
  406. $orderBy = ' ORDER BY '.$gridValue['sortField'].' '.$filterVars['orderDirection'];
  407. break;
  408. }
  409. }
  410. $selectStatement = 'SELECT TOP '.$filterVars['numPerPage'].' STARTING AT '.$filterVars['startIndex'].' '.$this->listSelectClause.' FROM '.$this->listFromClause .' '.$whereClause.' '.$orderBy;
  411. $result = $this->user->connection->runQUery($selectStatement);
  412. $data = array();
  413. foreach ($result['data'] as $row) {
  414. $dataRow = array();
  415. for($i = 0; $i < count($result['columns']); $i++) {
  416. $dataRow[$result['columns'][$i]['columnname']] = $row[$i];
  417. }
  418. $data[] = $dataRow;
  419. }
  420. $retval['data'] = $data;
  421. $retval['emptyRows'] = $retval['numPerPage'] - count($data);
  422. return $retval;
  423. }
  424. protected function getModelForm($model) {
  425. $retval = array('groups' => array(), 'tabs' => array());
  426. if (isset($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($model), false)]) && isset($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($model), false)]['fields'])) {
  427. foreach ($this->application->models[Sodapop_Inflector::camelCapsToUnderscores(get_class($model), false)]['fields'] as $groupTabItem) {
  428. if (isset($groupTabItem['group'])) {
  429. $retval['groups'][] = array('label' => $groupTabItem['group'], 'showFieldset' => (isset($groupTabItem['fieldset']) && $groupTabItem['fieldset'] == 'false' ? false : true), 'fields' => $this->parseGroupInfo(isset($groupTabItem['fields']) ? $groupTabItem['fields'] : array(), $model));
  430. } else if (isset($groupTabItem['tab'])) {
  431. $retval['tabs'][$groupTabItem['tab']] = array();
  432. foreach ($groupTabItem['groups'] as $groupItem) {
  433. $retval['tabs'][$groupTabItem['tab']][$groupItem['group']] = $this->parseGroupInfo(isset($groupItem['fields']) ? $groupItem['fields'] : array(), $model);
  434. }
  435. }
  436. }
  437. } else {
  438. $retval['groups'][] = array('label' => 'Information', 'showFieldset' => true, 'fields' => array());
  439. $fieldDefinitions = $model->getFieldDefinitions();
  440. $invalidFields = array('id', 'modDate', 'createDate', 'modUserName', 'createUserName', 'activeFlag');
  441. foreach ($fieldDefinitions as $fieldName => $fieldDefinition) {
  442. if (!in_array($fieldName,$invalidFields )) {
  443. $fieldArray = array();
  444. $fieldArray['id'] = $this->createAlias(get_class($model)).'_'.strtolower($fieldDefinition['column_name']);
  445. $fieldArray['label'] = $fieldDefinition['display_name'];
  446. $fieldArray['arrayFlag'] = $fieldDefinition['array_flag'] == '1';
  447. if ($fieldDefinition['type_name'] == 'REFERENCE') {
  448. $referenceModelClassname = Sodapop_Inflector::underscoresToCamelCaps(strtolower($fieldDefinition['ref_table_name']), false);
  449. $referenceModel = new $referenceModeClassName();
  450. $referenceFieldDefinitions = $referenceModel->getFieldDefinitions();
  451. $fieldArray['type'] = 'select';
  452. $optionQuery = (isset($field['query']) ? $field['query'] : 'SELECT '.(isset($field['select']) ? $field['select'] : 'id, '.strtolower($referenceFieldDefinitions['column_name'])).' FROM '.strtolower($fieldDefinition['ref_table_name']).' '.(isset($field['where']) ? 'WHERE '.$field['where'] : '').' '.(isset($field['order']) ? 'ORDER BY '.$field['order'] : ''));
  453. $optionsResult = $this->user->connection->runQuery($optionQuery);
  454. $fieldArray['options'] = array();
  455. foreach ($optionsResult['data'] as $optionRow) {
  456. $fieldArray['options'][$optionRow[0]] = $optionRow[1];
  457. }
  458. $fieldArray['default'] = $model->$fieldName->id ? $model->$fieldName->id : $fieldDefinition['default_value'];
  459. } else {
  460. $fieldArray['type'] = $fieldDefinition['type_name'];
  461. $fieldArray['default'] = $model->$fieldName ? $model->$fieldName : $fieldDefinition['default_value'];
  462. }
  463. $retval['groups'][0]['fields'][] = $fieldArray;
  464. }
  465. }
  466. }
  467. //echo 'Main :'.var_export($retval);
  468. return $retval;
  469. }
  470. protected function parseGroupInfo($fields, $model) {
  471. $retval = array();
  472. if ($fields) {
  473. foreach ($fields as $field) {
  474. $fieldArray = array();
  475. if (isset($field['subtable'])) {
  476. $subtableModelClassname = Sodapop_Inflector::underscoresToCamelCaps($field['subtable'], false);
  477. $subtableModel = new $subtableModelClassname;
  478. $filterVars = array('numPerPage' => 1000, 'filters' => array(), 'startIndex' => 0, 'orderBy' => (isset($this->application->models[$field['subtable']]) && isset($this->application->models[$field['subtable']]['list_order_by']) ? $this->application->models[$field['subtable']]['list_order_by'] : 'id'), 'orderDirection' => 'ASC');
  479. $fieldArray['subtable'] = true;
  480. $fieldArray['grid'] = $this->buildGrid($filterVars, $subtableModel);
  481. $fieldArray['data'] = $this->getData($fieldArray['grid'], $filterVars, $subtableModel, $model->id);
  482. } else {
  483. $fieldName = Sodapop_Inflector::underscoresToCamelCaps($field['name'], true, false);
  484. $fieldDefinition = $model->getFieldDefinition($fieldName);
  485. $fieldArray['id'] = $this->createAlias(get_class($model)).'_'.$field['name'];
  486. $fieldArray['subtable'] = false;
  487. $fieldArray['label'] = isset($field['label']) ? $field['label'] : $fieldDefinition['display_name'];
  488. $fieldArray['arrayFlag'] = $fieldDefinition['array_flag'] == '1';
  489. if ($fieldDefinition['type_name'] == 'REFERENCE') {
  490. $referenceModelClassname = Sodapop_Inflector::underscoresToCamelCaps(strtolower($fieldDefinition['ref_table_name']), false);
  491. $referenceModel = new $referenceModelClassname(isset($model->$fieldName->id) ? $model->$fieldName->id : $fieldDefinition['default_value']);
  492. if ($field['visualization'] == 'editor') {
  493. $fieldArray['type'] = 'form';
  494. $fieldArray['form'] = $this->getModelForm($referenceModel);
  495. } else {
  496. $referenceFieldDefinitions = $referenceModel->getFieldDefinitions();
  497. $fieldArray['type'] = 'select';
  498. $optionQuery = (isset($field['query']) ? $field['query'] : 'SELECT '.(isset($field['select']) ? $field['select'] : 'id, '.strtolower($referenceFieldDefinitions['column_name'])).' FROM '.strtolower($fieldDefinition['ref_table_name']).' '.(isset($field['where']) ? 'WHERE '.$field['where'] : '').' '.(isset($field['order']) ? 'ORDER BY '.$field['order'] : ''));
  499. $optionsResult = $this->user->connection->runQuery($optionQuery);
  500. $fieldArray['options'] = array();
  501. foreach ($optionsResult['data'] as $optionRow) {
  502. $fieldArray['options'][$optionRow[0]] = $optionRow[1];
  503. }
  504. }
  505. $fieldArray['default'] = isset($model->$fieldName->id) ? $model->$fieldName->id : $fieldDefinition['default_value'];
  506. } else {
  507. $fieldArray['type'] = $fieldDefinition['type_name'];
  508. $fieldArray['default'] = $model->$fieldName ? $model->$fieldName : $fieldDefinition['default_value'];
  509. }
  510. }
  511. $retval[] = $fieldArray;
  512. }
  513. }
  514. return $retval;
  515. }
  516. protected function processPost($actionName, $model) {
  517. $fieldDefinitions = $model->getFieldDefinitions();
  518. $invalidFields = array('id', 'modDate', 'createDate', 'modUserName', 'createUserName', 'activeFlag');
  519. foreach ($fieldDefinitions as $fieldName => $fieldDefinition) {
  520. if (!in_array($fieldName,$invalidFields)) {
  521. if ($fieldDefinition['type_name'] != 'REFERENCE') {
  522. if (isset($this->request->variables[$this->createAlias(get_class($model)).'_'.strtolower($fieldDefinition['column_name'])])) {
  523. $model->$fieldName = $this->request->variables[$this->createAlias(get_class($model)).'_'.strtolower($fieldDefinition['column_name'])];
  524. }
  525. } else {
  526. $referenceModelClassname = Sodapop_Inflector::underscoresToCamelCaps(strtolower($fieldDefinition['ref_table_name']), false);
  527. $referenceColumnPrefix = $this->createAlias(get_class($model)).'_'.strtolower($fieldDefinition['column_name']);
  528. if (trim($this->request->variables[$this->createAlias(get_class($model)).'_'.strtolower($fieldDefinition['column_name'])]) != '') {
  529. $referenceModel = new $referenceModelClassname($this->request->variables[$referenceColumnPrefix]);
  530. $referenceAction = 'update';
  531. } else {
  532. $referenceModel = new $referenceModelClassname();
  533. $referenceAction = 'insert';
  534. }
  535. $referenceFieldDefinitions = $referenceModel->getFieldDefinitions();
  536. foreach ($referenceFieldDefinitions as $referenceFieldName => $referenceFieldDefinition) {
  537. if (isset($this->request->variables[$referenceColumnPrefix.'_'.$this->createAlias(get_class($referenceModel)).'_'.strtolower($referenceFieldDefinition['column_name'])]) && !in_array($referenceFieldName,$invalidFields)) {
  538. if ($referenceFieldDefinition['type_name'] != 'REFERENCE') {
  539. $referenceModel->$referenceFieldName = $this->request->variables[$referenceColumnPrefix.'_'.$this->createAlias(get_class($referenceModel)).'_'.strtolower($referenceFieldDefinition['column_name'])];
  540. } else {
  541. $referenceReferenceModelClassname = Sodapop_Inflector::underscoresToCamelCaps(strtolower($referenceFieldDefinition['ref_table_name']), false);
  542. $referenceModel->$referenceFieldName = new $referenceReferenceModelClassname($this->request->variables[$referenceColumnPrefix.'_'.$this->createAlias(get_class($referenceModel)).'_'.strtolower($referenceFieldDefinition['column_name'])]);
  543. }
  544. }
  545. }
  546. $referenceModel->$referenceAction();
  547. $model->$fieldName = $referenceModel;
  548. }
  549. }
  550. }
  551. $model->$actionName();
  552. }
  553. protected function renderForm($form, $namespace = '', $readonly = false) {
  554. $retval = '';
  555. foreach ($form['groups'] as $group) {
  556. $retval .= $this->renderFormGroup($group, count($form['groups']) == 1 ? false : true, $namespace, $readonly);
  557. }
  558. foreach ($form['tabs'] as $tab) {
  559. }
  560. return $retval;
  561. }
  562. protected function renderFormGroup($group, $showFieldset = true, $namespace = '', $readonly = false) {
  563. $retval = '';
  564. $retval .= '<fieldgroup label="'.htmlentities($group['label']).'" border="'.($showFieldset ? 'true' : 'false').'">';
  565. foreach ($group['fields'] as $field) {
  566. if (isset($field['subtable']) && $field['subtable']) {
  567. $retval .= $this->renderSubtable();
  568. } else if ($field['type'] == 'form') {
  569. $retval .= '<hidden id="'.$field['id'].'" value="'.$field['default'].'" />'.$this->renderForm($field['form'], $field['id'], $readonly);
  570. } else {
  571. $retval .= '<'.strtolower($field['type']).'input id="'.($namespace != '' ? $namespace.'_' : '').$field['id'].'" label="'.$field['label'].'" array="'.($field['arrayFlag'] ? 'true' : 'false').'" default="'.htmlentities(serialize($field['default'])).'" readonly="'.($readonly ? 'true' : 'false' ).'" />';
  572. }
  573. }
  574. $retval .= '</fieldgroup>';
  575. return $retval;
  576. }
  577. protected function getInitialActions() {
  578. $retval = array();
  579. if ($this->model instanceof Sodapop_Database_Form_Abstract) {
  580. foreach ($this->model->getFormStatuses() as $statusId => $status) {
  581. if ($status['initial_flag'] == 1 && $this->user->hasFormPermission(strtolower(Sodapop_Inflector::camelCapsToUnderscores($this->modelClassname, false)), $status['adjective'], 'CALL' )) {
  582. $retval[] = array(strtolower(substr($this->modelClassname, 0, 1)).substr($this->modelClassname, 1).'/'.strtolower($status['verb']) => $status['display_verb']);
  583. }
  584. }
  585. } else {
  586. if ($this->user->hasTablePermission(strtolower(Sodapop_Inflector::camelCapsToUnderscores($this->modelClassname, false)), 'INSERT')) {
  587. $retval[] = array(strtolower(substr($this->modelClassname, 0, 1)).substr($this->modelClassname, 1).'/insert' => 'Insert');
  588. }
  589. }
  590. return $retval;
  591. }
  592. protected function getNextActions($model) {
  593. $retval = array();
  594. if ($model instanceof Sodapop_Database_Form_Abstract) {
  595. foreach ($this->model->getFormStatuses() as $statusId => $status) {
  596. if ($status['initial_flag'] == 1 && $this->user->hasFormPermission(strtolower(Sodapop_Inflector::camelCapsToUnderscores($this->modelClassname, false)), $status['adjective'], 'CALL' )) {
  597. $retval[] = array(strtolower(substr($this->modelClassname, 0, 1)).substr($this->modelClassname, 1).'/'.strtolower($status['verb']) => $status['display_verb']);
  598. }
  599. }
  600. } else {
  601. if (!$model->id && $this->user->hasTablePermission(strtolower(Sodapop_Inflector::camelCapsToUnderscores($this->modelClassname, false)), 'INSERT')) {
  602. $retval[] = array(strtolower(substr($this->modelClassname, 0, 1)).substr($this->modelClassname, 1).'/insert' => 'Insert');
  603. }
  604. if ($model->id && $this->user->hasTablePermission(strtolower(Sodapop_Inflector::camelCapsToUnderscores($this->modelClassname, false)), 'UPDATE')) {
  605. $retval[] = array(strtolower(substr($this->modelClassname, 0, 1)).substr($this->modelClassname, 1).'/update' => 'Update');
  606. }
  607. if ($model->id && $this->user->hasTablePermission(strtolower(Sodapop_Inflector::camelCapsToUnderscores($this->modelClassname, false)), 'DELETE')) {
  608. $retval[] = array(strtolower(substr($this->modelClassname, 0, 1)).substr($this->modelClassname, 1).'/delete' => 'Delete');
  609. }
  610. }
  611. return $retval;
  612. }
  613. protected function createAlias($modelName) {
  614. $keywords = array('order', 'table' , 'form', 'column', 'field');
  615. $retval = Sodapop_Inflector::camelCapsToUnderscores($modelName, true);
  616. if (in_array($retval, $keywords)) {
  617. return $retval.'z';
  618. } else {
  619. return $retval;
  620. }
  621. }
  622. }