1: <?php
2: 3: 4: 5: 6:
7:
8: abstract class QHtmlTable_CodeGenerator extends QControl_CodeGenerator implements QDataList_CodeGenerator_Interface {
9:
10: 11: 12: 13: 14:
15: public function VarName($strPropName) {
16: return 'dtg' . $strPropName;
17: }
18:
19:
20: 21: 22: 23:
24:
25: 26: 27: 28: 29: 30: 31: 32:
33: public function DataListConnectorComments(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
34: $strCode = <<<TMPL
35: * @property QQCondition \$Condition Any condition to use during binding
36: * @property QQClauses \$Clauses Any clauses to use during binding
37:
38: TMPL;
39: return $strCode;
40: }
41:
42:
43: 44: 45: 46: 47: 48: 49:
50: public function DataListConnector(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
51: $strCode = $this->DataListMembers($objCodeGen, $objTable);
52: $strCode .= $this->DataListConstructor($objCodeGen, $objTable);
53: $strCode .= $this->DataListCreatePaginator($objCodeGen, $objTable);
54: $strCode .= $this->DataListCreateColumns($objCodeGen, $objTable);
55: $strCode .= $this->DataListDataBinder($objCodeGen, $objTable);
56: $strCode .= $this->DataListGet($objCodeGen, $objTable);
57: $strCode .= $this->DataListSet($objCodeGen, $objTable);
58:
59: return $strCode;
60: }
61:
62: 63: 64: 65: 66: 67: 68:
69: protected function DataListMembers(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
70: $strCode = <<<TMPL
71: /**
72: * @var null|QQCondition Condition to use to filter the list.
73: * @access protected
74: */
75: protected \$objCondition;
76:
77: /**
78: * @var null|QQClause[] Clauses to attach to the query.
79: * @access protected
80: */
81: protected \$objClauses;
82:
83:
84: TMPL;
85: $strCode .= $this->DataListColumnDeclarations($objCodeGen, $objTable);
86: return $strCode;
87: }
88:
89: 90: 91: 92: 93: 94: 95: 96: 97:
98: protected function DataListColumnDeclarations(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
99:
100: $strCode = <<<TMPL
101: // Publicly accessible columns that allow parent controls to directly manipulate them after creation.
102:
103: TMPL;
104: foreach ($objTable->ColumnArray as $objColumn) {
105: if (isset($objColumn->Options['FormGen']) && ($objColumn->Options['FormGen'] == QFormGen::None)) continue;
106: if (isset($objColumn->Options['NoColumn']) && $objColumn->Options['NoColumn']) continue;
107: $strColVarName = 'col' . $objCodeGen->ModelConnectorPropertyName($objColumn);
108: $strCode .= <<<TMPL
109: /** @var QHtmlTableNodeColumn */
110: public \${$strColVarName};
111:
112: TMPL;
113: }
114:
115: foreach ($objTable->ReverseReferenceArray as $objReverseReference) {
116: $strColVarName = 'col' . $objReverseReference->ObjectDescription;
117:
118: if ($objReverseReference->Unique) {
119: $strCode .= <<<TMPL
120: /** @var QHtmlTableNodeColumn {$strColVarName} */
121: public \${$strColVarName};
122:
123: TMPL;
124: }
125: }
126: $strCode .= "\n";
127: return $strCode;
128: }
129:
130: 131: 132: 133: 134: 135:
136: protected function DataListConstructor(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
137: $strClassName = $this->GetControlClass();
138:
139: $strCode = <<<TMPL
140:
141: /**
142: * {$strClassName} constructor. The default creates a paginator, sets a default data binder, and sets the grid up
143: * watch the data. Columns are set up by the parent control. Feel free to override the constructor to do things differently.
144: *
145: * @param QControl|QForm \$objParent
146: * @param null|string \$strControlId
147: */
148: public function __construct(\$objParent, \$strControlId = false) {
149: parent::__construct(\$objParent, \$strControlId);
150: \$this->CreatePaginator();
151: \$this->SetDataBinder('BindData', \$this);
152: \$this->Watch(QQN::{$objTable->ClassName}());
153: }
154:
155:
156: TMPL;
157: return $strCode;
158: }
159:
160: 161: 162: 163: 164:
165: public function DataListCreatePaginator(QCodeGenBase $objCodeGen, QSqlTable $objTable)
166: {
167: $strCode = <<<TMPL
168: /**
169: * Creates the paginator. Override to add an additional paginator, or to remove it.
170: */
171: protected function CreatePaginator() {
172: \$this->Paginator = new QPaginator(\$this);
173: \$this->ItemsPerPage = __FORM_LIST_ITEMS_PER_PAGE__;
174: }
175:
176: TMPL;
177: return $strCode;
178: }
179:
180: 181: 182: 183: 184: 185: 186: 187:
188: public function DataListCreateColumns(QCodeGenBase $objCodeGen, QSqlTable $objTable)
189: {
190: $strVarName = $objCodeGen->DataListVarName($objTable);
191:
192: $strCode = <<<TMPL
193: /**
194: * Creates the columns for the table. Override to customize, or use the ModelConnectorEditor to turn on and off
195: * individual columns. This is a public function and called by the parent control.
196: */
197: public function CreateColumns() {
198:
199: TMPL;
200:
201: foreach ($objTable->ColumnArray as $objColumn) {
202: if (isset($objColumn->Options['FormGen']) && ($objColumn->Options['FormGen'] == QFormGen::None)) continue;
203: if (isset($objColumn->Options['NoColumn']) && $objColumn->Options['NoColumn']) continue;
204:
205: $strCode .= <<<TMPL
206: \$this->col{$objCodeGen->ModelConnectorPropertyName($objColumn)} = \$this->CreateNodeColumn("{$objCodeGen->ModelConnectorControlName($objColumn)}", QQN::{$objTable->ClassName}()->{$objCodeGen->ModelConnectorPropertyName($objColumn)});
207:
208: TMPL;
209:
210: }
211:
212: foreach ($objTable->ReverseReferenceArray as $objReverseReference) {
213: if ($objReverseReference->Unique) {
214: $strCode .= <<<TMPL
215: \$this->col{$objReverseReference->ObjectDescription} = \$this->CreateNodeColumn("{$objCodeGen->ModelConnectorControlName($objReverseReference)}", QQN::{$objTable->ClassName}()->{$objReverseReference->ObjectDescription});
216:
217: TMPL;
218: }
219: }
220:
221: $strCode .= <<<TMPL
222: }
223:
224:
225: TMPL;
226:
227: return $strCode;
228: }
229:
230:
231: 232: 233: 234: 235: 236: 237:
238: protected function DataListDataBinder(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
239: $strObjectType = $objTable->ClassName;
240: $strCode = <<<TMPL
241: /**
242: * Called by the framework to access the data for the control and load it into the table. By default, this function will be
243: * the data binder for the control, with no additional conditions or clauses. To change what data is displayed in the list,
244: * you have many options:
245: * - Override this method in the Connector.
246: * - Set ->Condition and ->Clauses properties for semi-permanent conditions and clauses
247: * - Override the GetCondition and GetClauses methods in the Connector.
248: * - For situations where the data might change every time you draw, like if the data is filtered by other controls,
249: * you should call SetDataBinder after the parent creates this control, and in your custom data binder, call this function,
250: * passing in the conditions and clauses you want this data binder to use.
251: *
252: * This binder will automatically add the orderby and limit clauses from the paginator, if present.
253: **/
254: public function BindData(\$objAdditionalCondition = null, \$objAdditionalClauses = null) {
255: \$objCondition = \$this->GetCondition(\$objAdditionalCondition);
256: \$objClauses = \$this->GetClauses(\$objAdditionalClauses);
257:
258: if (\$this->Paginator) {
259: \$this->TotalItemCount = {$strObjectType}::QueryCount(\$objCondition, \$objClauses);
260: }
261:
262: // If a column is selected to be sorted, and if that column has a OrderByClause set on it, then let's add
263: // the OrderByClause to the \$objClauses array
264: if (\$objClause = \$this->OrderByClause) {
265: \$objClauses[] = \$objClause;
266: }
267:
268: // Add the LimitClause information, as well
269: if (\$objClause = \$this->LimitClause) {
270: \$objClauses[] = \$objClause;
271: }
272:
273: \$this->DataSource = {$strObjectType}::QueryArray(\$objCondition, \$objClauses);
274: }
275:
276:
277: TMPL;
278:
279: $strCode .= $this->DataListGetCondition($objCodeGen, $objTable);
280: $strCode .= $this->DataListGetClauses($objCodeGen, $objTable);
281:
282: return $strCode;
283: }
284:
285: 286: 287: 288: 289:
290: protected function DataListGetCondition(QCodeGenBase $objCodeGen, QSqlTable $objTable)
291: {
292: $strCode = <<<TMPL
293: /**
294: * Returns the condition to use when querying the data. Default is to return the condition put in the local
295: * objCondition member variable. You can also override this to return a condition.
296: *
297: * @return QQCondition
298: */
299: protected function GetCondition(\$objAdditionalCondition = null) {
300: // Get passed in condition, possibly coming from subclass or enclosing control or form
301: \$objCondition = \$objAdditionalCondition;
302: if (!\$objCondition) {
303: \$objCondition = QQ::All();
304: }
305: // Get condition more permanently bound
306: if (\$this->objCondition) {
307: \$objCondition = QQ::AndCondition(\$objCondition, \$this->objCondition);
308: }
309:
310: return \$objCondition;
311: }
312:
313:
314: TMPL;
315: return $strCode;
316: }
317:
318: 319: 320: 321: 322:
323: protected function DataListGetClauses(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
324: $strCode = <<<TMPL
325: /**
326: * Returns the clauses to use when querying the data. Default is to return the clauses put in the local
327: * objClauses member variable. You can also override this to return clauses.
328: *
329: * @return QQClause[]
330: */
331: protected function GetClauses(\$objAdditionalClauses = null) {
332: \$objClauses = \$objAdditionalClauses;
333: if (!\$objClauses) {
334: \$objClauses = [];
335: }
336: if (\$this->objClauses) {
337: \$objClauses = array_merge(\$objClauses, \$this->objClauses);
338: }
339:
340: return \$objClauses;
341: }
342:
343:
344: TMPL;
345: return $strCode;
346: }
347:
348:
349: 350: 351: 352: 353:
354: protected function DataListGet(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
355: $strCode = <<<TMPL
356: /**
357: * This will get the value of \$strName
358: *
359: * @param string \$strName Name of the property to get
360: * @return mixed
361: */
362: public function __get(\$strName) {
363: switch (\$strName) {
364: case 'Condition':
365: return \$this->objCondition;
366: case 'Clauses':
367: return \$this->objClauses;
368: default:
369: try {
370: return parent::__get(\$strName);
371: } catch (QCallerException \$objExc) {
372: \$objExc->IncrementOffset();
373: throw \$objExc;
374: }
375: }
376: }
377:
378:
379: TMPL;
380: return $strCode;
381: }
382:
383: 384: 385: 386: 387:
388: protected function DataListSet(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
389: $strCode = <<<TMPL
390: /**
391: * This will set the property \$strName to be \$mixValue
392: *
393: * @param string \$strName Name of the property to set
394: * @param string \$mixValue New value of the property
395: * @return mixed
396: */
397: public function __set(\$strName, \$mixValue) {
398: switch (\$strName) {
399: case 'Condition':
400: try {
401: \$this->objCondition = QType::Cast(\$mixValue, 'QQCondition');
402: \$this->MarkAsModified();
403: return;
404: } catch (QCallerException \$objExc) {
405: \$objExc->IncrementOffset();
406: throw \$objExc;
407: }
408: case 'Clauses':
409: try {
410: \$this->objClauses = QType::Cast(\$mixValue, QType::ArrayType);
411: \$this->MarkAsModified();
412: return;
413: } catch (QCallerException \$objExc) {
414: \$objExc->IncrementOffset();
415: throw \$objExc;
416: }
417: default:
418: try {
419: parent::__set(\$strName, \$mixValue);
420: break;
421: } catch (QCallerException \$objExc) {
422: \$objExc->IncrementOffset();
423: throw \$objExc;
424: }
425: }
426: }
427:
428:
429: TMPL;
430: return $strCode;
431: }
432:
433:
434:
435: 436: 437: 438:
439:
440: 441: 442: 443: 444: 445:
446: public function DataListHasFilter() {
447: return false;
448: }
449:
450: 451: 452: 453: 454: 455: 456:
457: public function DataListInstantiate(QCodeGenBase $objCodeGen, QSqlTable $objTable)
458: {
459: $strVarName = $objCodeGen->DataListVarName($objTable);
460:
461: $strCode = <<<TMPL
462: \$this->{$strVarName}_Create();
463:
464: TMPL;
465: return $strCode;
466: }
467:
468: 469: 470: 471: 472: 473: 474:
475: public function DataListRefresh(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
476: $strVarName = $objCodeGen->DataListVarName($objTable);
477: $strCode = <<<TMPL
478: \$this->{$strVarName}->Refresh();
479:
480: TMPL;
481: return $strCode;
482:
483: }
484:
485: 486: 487: 488: 489: 490: 491:
492: public function DataListHelperMethods(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
493: $strCode = $this->DataListParentCreate($objCodeGen, $objTable);
494: $strCode .= $this->DataListParentCreateColumns($objCodeGen, $objTable);
495: $strCode .= $this->DataListParentMakeEditable($objCodeGen, $objTable);
496: $strCode .= $this->DataListGetRowParams($objCodeGen, $objTable);
497:
498: return $strCode;
499: }
500:
501:
502: 503: 504: 505: 506: 507: 508:
509: protected function DataListParentCreate(QCodeGenBase $objCodeGen, QSqlTable $objTable)
510: {
511: $strPropertyName = $objCodeGen->DataListPropertyName($objTable);
512: $strVarName = $objCodeGen->DataListVarName($objTable);
513:
514: $strCode = <<<TMPL
515: /**
516: * Creates the data grid and prepares it to be row clickable. Override for additional creation operations.
517: **/
518: protected function {$strVarName}_Create() {
519: \$this->{$strVarName} = new {$strPropertyName}List(\$this);
520: \$this->{$strVarName}_CreateColumns();
521: \$this->{$strVarName}_MakeEditable();
522: \$this->{$strVarName}->RowParamsCallback = [\$this, "{$strVarName}_GetRowParams"];
523:
524: TMPL;
525:
526: if (($o = $objTable->Options) && isset ($o['Name'])) {
527: $strCode .= <<<TMPL
528: \$this->{$strVarName}->Name = "{$o['Name']}";
529:
530: TMPL;
531: }
532:
533:
534: $strCode .= $this->ConnectorCreateOptions($objCodeGen, $objTable, null, $strVarName);
535:
536: $strCode .= <<<TMPL
537: }
538:
539: TMPL;
540: return $strCode;
541: }
542:
543: 544: 545: 546: 547: 548: 549:
550: protected function DataListParentCreateColumns(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
551: $strVarName = $objCodeGen->DataListVarName($objTable);
552:
553: $strCode = <<<TMPL
554:
555: /**
556: * Calls the list connector to add the columns. Override to customize column creation.
557: **/
558: protected function {$strVarName}_CreateColumns() {
559: \$this->{$strVarName}->CreateColumns();
560: }
561:
562: TMPL;
563:
564: return $strCode;
565:
566: }
567:
568: 569: 570: 571: 572: 573: 574:
575: protected function DataListParentMakeEditable(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
576: $strVarName = $objCodeGen->DataListVarName($objTable);
577:
578: $strCode = <<<TMPL
579:
580: protected function {$strVarName}_MakeEditable() {
581: \$this->{$strVarName}->AddAction(new QCellClickEvent(), new QAjaxControlAction(\$this, '{$strVarName}_CellClick', null, null, '\$j(this).parent().data("value")'));
582: \$this->{$strVarName}->AddCssClass('clickable-rows');
583: }
584:
585: protected function {$strVarName}_CellClick(\$strFormId, \$strControlId, \$strParameter) {
586: if (\$strParameter) {
587: \$this->EditItem(\$strParameter);
588: }
589: }
590:
591: TMPL;
592:
593: return $strCode;
594: }
595:
596: 597: 598: 599: 600: 601: 602:
603: protected function DataListGetRowParams(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
604: $strVarName = $objCodeGen->DataListVarName($objTable);
605:
606: $strCode = <<<TMPL
607: public function {$strVarName}_GetRowParams(\$objRowObject, \$intRowIndex) {
608: \$strKey = \$objRowObject->PrimaryKey();
609: \$params['data-value'] = \$strKey;
610: return \$params;
611: }
612: TMPL;
613:
614: return $strCode;
615:
616: }
617:
618:
619: 620: 621: 622:
623:
624:
625: 626: 627: 628: 629: 630: 631: 632:
633: public function DataListSubclassOverrides(QCodeGenBase $objCodeGen, QSqlTable $objTable) {
634: $strVarName = $objCodeGen->DataListVarName($objTable);
635: $strPropertyName = QCodeGen::DataListPropertyName($objTable);
636:
637: $strCode = <<<TMPL
638: /*
639: Uncomment this block to directly create the columns here, rather than creating them in the {$strPropertyName}List connector.
640: You can then modify the column creation process by editing the function below. Or, you can instead call the parent function
641: and modify the columns after the {$strPropertyName}List creates the default columns.
642:
643: protected function {$strVarName}_CreateColumns() {
644:
645: TMPL;
646:
647: foreach ($objTable->ColumnArray as $objColumn) {
648: if (isset($objColumn->Options['FormGen']) && ($objColumn->Options['FormGen'] == QFormGen::None)) continue;
649: if (isset($objColumn->Options['NoColumn']) && $objColumn->Options['NoColumn']) continue;
650:
651: $strCode .= <<<TMPL
652: \$col = \$this->{$strVarName}->CreateNodeColumn("{$objCodeGen->ModelConnectorControlName($objColumn)}", QQN::{$objTable->ClassName}()->{$objCodeGen->ModelConnectorPropertyName($objColumn)});
653:
654: TMPL;
655:
656: }
657:
658: foreach ($objTable->ReverseReferenceArray as $objReverseReference) {
659: if ($objReverseReference->Unique) {
660: $strCode .= <<<TMPL
661: \$col = \$this->{$strVarName}->CreateNodeColumn("{$objCodeGen->ModelConnectorControlName($objReverseReference)}", QQN::{$objTable->ClassName}()->{$objReverseReference->ObjectDescription});
662:
663: TMPL;
664: }
665: }
666:
667: $strCode .= <<<TMPL
668: }
669:
670: */
671:
672: TMPL;
673:
674: $strCode .= <<<TMPL
675:
676: /*
677: Uncomment this block to use an Edit column instead of clicking on a highlighted row in order to edit an item.
678:
679: protected \$pxyEditRow;
680:
681: protected function {$strVarName}_MakeEditable () {
682: \$pxyEditRow = new QControlProxy(\$this);
683: \$pxyEditRow->AddAction(new QClickEvent(), new QAjaxControlAction(\$this, '{$strVarName}_EditClick'));
684: \$this->{$strVarName}->CreateLinkColumn(QApplication::Translate('Edit'), QApplication::Translate('Edit'), \$pxyEditRow, QQN::{$objTable->ClassName}()->Id, null, false, 0);
685: }
686:
687: protected function {$strVarName}_EditClick(\$strFormId, \$strControlId, \$param) {
688: \$this->EditItem(\$param);
689: }
690: */
691:
692: TMPL;
693:
694: return $strCode;
695: }
696:
697: }
698: