Support additional options for pseudoConstant::get CRM-12464
[civicrm-core.git] / CRM / Profile / Selector / Listings.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.3 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2013
32 * $Id$
33 *
34 */
35
36/**
37 * This class is used to retrieve and display a range of
38 * contacts that match the given criteria (specifically for
39 * results of advanced search options.
40 *
41 */
42class CRM_Profile_Selector_Listings extends CRM_Core_Selector_Base implements CRM_Core_Selector_API {
43
44 /**
45 * array of supported links, currenly view and edit
46 *
47 * @var array
48 * @static
49 */
50 static $_links = NULL;
51
52 /**
53 * we use desc to remind us what that column is, name is used in the tpl
54 *
55 * @var array
56 * @static
57 */
58 static $_columnHeaders;
59
60 /**
61 * The sql params we use to get the list of contacts
62 *
63 * @var string
64 * @access protected
65 */
66 protected $_params;
67
68 /**
69 * the public visible fields to be shown to the user
70 *
71 * @var array
72 * @access protected
73 */
74 protected $_fields;
75
76 /**
77 * the custom fields for this domain
78 *
79 * @var array
80 * @access protected
81 */
82 protected $_customFields;
83
84 /**
85 * cache the query object
86 *
87 * @var object
88 * @access protected
89 */
90 protected $_query;
91
92 /**
93 * cache the expanded options list if any
94 *
95 * @var object
96 * @access protected
97 */
98 protected $_options;
99
100 /**
101 * The group id that we are editing
102 *
103 * @var int
104 */
105 protected $_gid;
106
107 /**
108 * Do we enable mapping of users
109 *
110 * @var boolean
111 */
112 protected $_map;
113
114 /**
115 * Do we enable edit link
116 *
117 * @var boolean
118 */
119 protected $_editLink;
120
121 /**
122 * Should we link to the UF Profile
123 *
124 * @var boolean
125 */
126 protected $_linkToUF;
127
128 /**
129 * Store profile ids if multiple profile ids are passed using comma separated.
130 * Currently lets implement this functionality only for dialog mode
131 */
132 protected $_profileIds = array();
133
134 protected $_multiRecordTableName = NULL;
135 /**
136 * Class constructor
137 *
138 * @param string params the params for the where clause
139 *
140 * @return CRM_Contact_Selector_Profile
141 * @access public
142 */
143 function __construct(
144 &$params,
145 &$customFields,
146 $ufGroupIds = NULL,
147 $map = FALSE,
148 $editLink = FALSE,
149 $linkToUF = FALSE
150 ) {
151 $this->_params = $params;
152
153 if (is_array($ufGroupIds)) {
154 $this->_profileIds = $ufGroupIds;
155 $this->_gid = $ufGroupIds[0];
156 }
157 else {
158 $this->_profileIds = array($ufGroupIds);
159 $this->_gid = $ufGroupIds;
160 }
161
162 $this->_map = $map;
163 $this->_editLink = $editLink;
164 $this->_linkToUF = $linkToUF;
165
166 //get the details of the uf group
167 if ($this->_gid) {
168 $groupId = CRM_Core_DAO::getFieldValue('CRM_Core_BAO_UFGroup',
169 $this->_gid, 'limit_listings_group_id'
170 );
171 }
172
173 // add group id to params if a uf group belong to a any group
174 if ($groupId) {
175 if (CRM_Utils_Array::value('group', $this->_params)) {
176 $this->_params['group'][$groupId] = 1;
177 }
178 else {
179 $this->_params['group'] = array($groupId => 1);
180 }
181 }
182
183 $this->_fields = CRM_Core_BAO_UFGroup::getListingFields(CRM_Core_Action::VIEW,
184 CRM_Core_BAO_UFGroup::PUBLIC_VISIBILITY |
185 CRM_Core_BAO_UFGroup::LISTINGS_VISIBILITY,
186 FALSE, $this->_profileIds
187 );
188
189 $this->_customFields = &$customFields;
190
191 $returnProperties = CRM_Contact_BAO_Contact::makeHierReturnProperties($this->_fields);
192 $returnProperties['contact_type'] = 1;
193 $returnProperties['contact_sub_type'] = 1;
194 $returnProperties['sort_name'] = 1;
195
196 $queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_params, 1);
197 $this->_query = new CRM_Contact_BAO_Query($queryParams, $returnProperties, $this->_fields);
198
199 //the below is done for query building for multirecord custom field listing
200 //to show all the custom field multi valued records of a particular contact
201 $this->setMultiRecordTableName($this->_fields);
202
203 $this->_options = &$this->_query->_options;
204 }
205 //end of constructor
206
207 /**
208 * This method returns the links that are given for each search row.
209 *
210 * @return array
211 * @access public
212 *
213 */
214 static function &links($map = FALSE, $editLink = FALSE, $ufLink = FALSE, $gids = NULL) {
215 if (!self::$_links) {
216 self::$_links = array();
217
218 $viewPermission = TRUE;
219 if ($gids) {
220 // check view permission for each profile id, in case multiple profile ids are rendered
221 // then view action is disabled if any profile returns false
222 foreach ($gids as $profileId) {
223 $viewPermission = CRM_Core_Permission::ufGroupValid($profileId, CRM_Core_Permission::VIEW);
224 if (!$viewPermission) {
225 break;
226 }
227 }
228 }
229
230 if ($viewPermission) {
231 self::$_links[CRM_Core_Action::VIEW] = array(
232 'name' => ts('View'),
233 'url' => 'civicrm/profile/view',
234 'qs' => 'reset=1&id=%%id%%&gid=%%gid%%',
235 'title' => ts('View Profile Details'),
236 );
237 }
238
239 if ($editLink) {
240 self::$_links[CRM_Core_Action::UPDATE] = array(
241 'name' => ts('Edit'),
242 'url' => 'civicrm/profile/edit',
243 'qs' => 'reset=1&id=%%id%%&gid=%%gid%%',
244 'title' => ts('Edit'),
245 );
246 }
247
248 if ($ufLink) {
249 self::$_links[CRM_Core_Action::PROFILE] = array(
250 'name' => ts('Website Profile'),
251 'url' => 'user/%%ufID%%',
252 'qs' => ' ',
253 'title' => ts('View Website Profile'),
254 );
255 }
256
257 if ($map) {
258 self::$_links[CRM_Core_Action::MAP] = array(
259 'name' => ts('Map'),
260 'url' => 'civicrm/profile/map',
261 'qs' => 'reset=1&cid=%%id%%&gid=%%gid%%',
262 'title' => ts('Map'),
263 );
264 }
265 }
266 return self::$_links;
267 }
268 //end of function
269
270 /**
271 * getter for array of the parameters required for creating pager.
272 *
273 * @param
274 * @access public
275 */
276 function getPagerParams($action, &$params) {
277 $status =
278 CRM_Utils_System::isNull($this->_multiRecordTableName) ? ts('Contact %%StatusMessage%%') : ts('Contact Multi Records %%StatusMessage%%');
279 $params['status'] = $status;
280 $params['csvString'] = NULL;
281 $params['rowCount'] = CRM_Utils_Pager::ROWCOUNT;
282
283 $params['buttonTop'] = 'PagerTopButton';
284 $params['buttonBottom'] = 'PagerBottomButton';
285 }
286 //end of function
287
288 /**
289 * returns the column headers as an array of tuples:
290 * (name, sortName (key to the sort array))
291 *
292 * @param string $action the action being performed
293 * @param enum $output what should the result set include (web/email/csv)
294 *
295 * @return array the column headers that need to be displayed
296 * @access public
297 */
298 function &getColumnHeaders($action = NULL, $output = NULL) {
299 static $skipFields = array('group', 'tag');
300 $multipleFields = array('url');
301 $direction = CRM_Utils_Sort::ASCENDING;
302 $empty = TRUE;
303 if (!isset(self::$_columnHeaders)) {
304 self::$_columnHeaders = array(array('name' => ''),
305 array(
306 'name' => ts('Name'),
307 'sort' => 'sort_name',
308 'direction' => CRM_Utils_Sort::ASCENDING,
309 ),
310 );
311
312 $locationTypes = CRM_Core_PseudoConstant::locationType();
313
314 foreach ($this->_fields as $name => $field) {
315 // skip pseudo fields
316 if (substr($name, 0, 9) == 'phone_ext') {
317 continue;
318 }
319
320 if (CRM_Utils_Array::value('in_selector', $field) &&
321 !in_array($name, $skipFields)
322 ) {
323
324 if (strpos($name, '-') !== FALSE) {
325 $value = explode('-', $name);
326 $fieldName = CRM_Utils_Array::value(0, $value);
327 $lType = CRM_Utils_Array::value(1, $value);
328 $type = CRM_Utils_Array::value(2, $value);
329
330 if (!in_array($fieldName, $multipleFields)) {
331 if ($lType == 'Primary') {
332 $locationTypeName = 1;
333 }
334 else {
335 $locationTypeName = $locationTypes[$lType];
336 }
337
338 if (in_array($fieldName, array(
339 'phone', 'im', 'email'))) {
340 if ($type) {
341 $name = "`$locationTypeName-$fieldName-$type`";
342 }
343 else {
344 $name = "`$locationTypeName-$fieldName`";
345 }
346 }
347 else {
348 $name = "`$locationTypeName-$fieldName`";
349 }
350 }
351 else {
352 $name = "website-{$lType}-{$fieldName}";
353 }
354 }
355
356 self::$_columnHeaders[] = array(
357 'name' => $field['title'],
358 'sort' => $name,
359 'direction' => $direction,
360 );
361
362 $direction = CRM_Utils_Sort::DONTCARE;
363 $empty = FALSE;
364 }
365 }
366
367 // if we dont have any valid columns, dont add the implicit ones
368 // this allows the template to check on emptiness of column headers
369 if ($empty) {
370 self::$_columnHeaders = array();
371 }
372 else {
373 self::$_columnHeaders[] = array('desc' => ts('Actions'));
374 }
375 }
376 return self::$_columnHeaders;
377 }
378
379 /**
380 * Returns total number of rows for the query.
381 *
382 * @param
383 *
384 * @return int Total number of rows
385 * @access public
386 */
387 function getTotalCount($action) {
388 $additionalWhereClause = 'contact_a.is_deleted = 0';
389 $additionalFromClause = NULL;
390 $returnQuery = NULL;
391
392 if ($this->_multiRecordTableName &&
393 !array_key_exists($this->_multiRecordTableName, $this->_query->_whereTables)) {
394 $additionalFromClause = CRM_Utils_Array::value($this->_multiRecordTableName, $this->_query->_tables);
395 $returnQuery = TRUE;
396 }
397
398 $countVal = $this->_query->searchQuery(0, 0, NULL, TRUE, NULL, NULL, NULL,
399 $returnQuery, $additionalWhereClause, NULL, $additionalFromClause
400 );
401
402 if (!$returnQuery) {
403 return $countVal;
404 }
405
406 if ($returnQuery) {
407 $sql = preg_replace('/DISTINCT/', '', $countVal);
408 return CRM_Core_DAO::singleValueQuery($sql);
409 }
410 }
411
412 /**
413 * Return the qill for this selector
414 *
415 * @return string
416 * @access public
417 */
418 function getQill() {
419 return $this->_query->qill();
420 }
421
422 /**
423 * returns all the rows in the given offset and rowCount
424 *
425 * @param enum $action the action being performed
426 * @param int $offset the row number to start from
427 * @param int $rowCount the number of rows to return
428 * @param string $sort the sql string that describes the sort order
429 * @param enum $output what should the result set include (web/email/csv)
430 *
431 * @return int the total number of rows for this action
432 */
433 function &getRows($action, $offset, $rowCount, $sort, $output = NULL) {
434
435 $multipleFields = array('url');
436 //$sort object processing for location fields
437 if ($sort) {
438 $vars = $sort->_vars;
439 $varArray = array();
440 foreach ($vars as $key => $field) {
441 $field = $vars[$key];
442 $fieldArray = explode('-', $field['name']);
443 $fieldType = CRM_Utils_Array::value('2', $fieldArray);
444 if (is_numeric(CRM_Utils_Array::value('1', $fieldArray))) {
445 if (!in_array($fieldType, $multipleFields)) {
446 $locationType = new CRM_Core_DAO_LocationType();
447 $locationType->id = $fieldArray[1];
448 $locationType->find(TRUE);
449 if ($fieldArray[0] == 'email' || $fieldArray[0] == 'im' || $fieldArray[0] == 'phone') {
450 $field['name'] = "`" . $locationType->name . "-" . $fieldArray[0] . "-1`";
451 }
452 else {
453 $field['name'] = "`" . $locationType->name . "-" . $fieldArray[0] . "`";
454 }
455 }
456 else {
457 $field['name'] = "`website-" . $fieldArray[1] . "-{$fieldType}`";
458 }
459 }
460 $varArray[$key] = $field;
461 }
462 }
463
464 $sort->_vars = $varArray;
465
466 $additionalWhereClause = 'contact_a.is_deleted = 0';
467 $returnQuery = NULL;
468 if ($this->_multiRecordTableName) {
469 $returnQuery = TRUE;
470 }
471
472 $result = $this->_query->searchQuery($offset, $rowCount, $sort, NULL, NULL,
473 NULL, NULL, $returnQuery, $additionalWhereClause
474 );
475
476 if ($returnQuery) {
477 $resQuery = preg_replace('/GROUP BY contact_a.id[\s]+ORDER BY/', ' ORDER BY', $result);
478 $result = CRM_Core_DAO::executeQuery($resQuery);
479 }
480
481 // process the result of the query
482 $rows = array();
483
484 // check if edit is configured in profile settings
485 if ($this->_gid) {
486 $editLink = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $this->_gid, 'is_edit_link');
487 }
488
489 //FIXME : make sure to handle delete separately. CRM-4418
490 $mask = CRM_Core_Action::mask(array(CRM_Core_Permission::getPermission()));
491 if ($editLink && ($mask & CRM_Core_Permission::EDIT)) {
492 // do not allow edit for anon users in joomla frontend, CRM-4668
493 $config = CRM_Core_Config::singleton();
494 if (!$config->userFrameworkFrontend) {
495 $this->_editLink = TRUE;
496 }
497 }
498 $links = self::links($this->_map, $this->_editLink, $this->_linkToUF, $this->_profileIds);
499
500 $locationTypes = CRM_Core_PseudoConstant::locationType();
501
502 $names = array();
503 static $skipFields = array('group', 'tag');
504
505 foreach ($this->_fields as $key => $field) {
506 // skip pseudo fields
507 if (substr($key, 0, 9) == 'phone_ext') {
508 continue;
509 }
510
511 if (CRM_Utils_Array::value('in_selector', $field) &&
512 !in_array($key, $skipFields)
513 ) {
514 if (strpos($key, '-') !== FALSE) {
515 $value = explode('-', $key);
516 $fieldName = CRM_Utils_Array::value(0, $value);
517 $id = CRM_Utils_Array::value(1, $value);
518 $type = CRM_Utils_Array::value(2, $value);
519
520 if (!in_array($fieldName, $multipleFields)) {
521 $locationTypeName = NULL;
522 if (is_numeric($id)) {
523 $locationTypeName = CRM_Utils_Array::value($id, $locationTypes);
524 }
525 else {
526 if ($id == 'Primary') {
527 $locationTypeName = 1;
528 }
529 }
530
531 if (!$locationTypeName) {
532 continue;
533 }
534 $locationTypeName = str_replace(' ', '_', $locationTypeName);
535 if (in_array($fieldName, array(
536 'phone', 'im', 'email'))) {
537 if ($type) {
538 $names[] = "{$locationTypeName}-{$fieldName}-{$type}";
539 }
540 else {
541 $names[] = "{$locationTypeName}-{$fieldName}";
542 }
543 }
544 else {
545 $names[] = "{$locationTypeName}-{$fieldName}";
546 }
547 }
548 else {
549 $names[] = "website-{$id}-{$fieldName}";
550 }
551 }
552 elseif ($field['name'] == 'id') {
553 $names[] = 'contact_id';
554 }
555 else {
556 $names[] = $field['name'];
557 }
558 }
559 }
560
561
562 $multipleSelectFields = array('preferred_communication_method' => 1);
563 $multiRecordTableId = NULL;
564 if ($this->_multiRecordTableName) {
565 $multiRecordTableId = "{$this->_multiRecordTableName}_id";
566 }
567
568 // we need to determine of overlay profile should be shown
569 $showProfileOverlay = CRM_Core_BAO_UFGroup::showOverlayProfile();
570
571 $imProviders = CRM_Core_PseudoConstant::IMProvider();
572 $websiteTypes = CRM_Core_PseudoConstant::websiteType();
573 $languages = CRM_Core_PseudoConstant::languages();
574 while ($result->fetch()) {
575 if (isset($result->country)) {
576 // the query returns the untranslated country name
577 $i18n = CRM_Core_I18n::singleton();
578 $result->country = $i18n->translate($result->country);
579 }
580 $row = array();
581 $empty = TRUE;
582 $row[] = CRM_Contact_BAO_Contact_Utils::getImage($result->contact_sub_type ?
583 $result->contact_sub_type : $result->contact_type,
584 FALSE,
585 $result->contact_id,
586 $showProfileOverlay
587 );
588 if ($result->sort_name) {
589 $row['sort_name'] = $result->sort_name;
590 $empty = FALSE;
591 }
592 else {
593 continue;
594 }
595
596 foreach ($names as $name) {
597 if ($cfID = CRM_Core_BAO_CustomField::getKeyID($name)) {
598 $row[] = CRM_Core_BAO_CustomField::getDisplayValue($result->$name,
599 $cfID,
600 $this->_options,
601 $result->contact_id
602 );
603 }
604 elseif (substr($name, -4) == '-url' &&
605 !empty($result->$name)
606 ) {
607 $url = CRM_Utils_System::fixURL($result->$name);
608 $typeId = substr($name, 0, -4) . "-website_type_id";
609 $typeName = $websiteTypes[$result->$typeId];
610 if ($typeName) {
611 $row[] = "<a href=\"$url\">{$result->$name} (${typeName})</a>";
612 }
613 else {
614 $row[] = "<a href=\"$url\">{$result->$name}</a>";
615 }
616 }
617 elseif ($name == 'preferred_language') {
618 $row[] = $languages[$result->$name];
619 }
620 elseif ($multipleSelectFields &&
621 array_key_exists($name, $multipleSelectFields)
622 ) {
623 // FIXME: Code related to the old CRM_Quest - should be removed
624 $key = $name;
625 $paramsNew = array($key => $result->$name);
626 if ($key == 'test_tutoring') {
627 $name = array($key => array('newName' => $key, 'groupName' => 'test'));
628 // for readers group
629 }
630 elseif (substr($key, 0, 4) == 'cmr_') {
631 $name = array(
632 $key => array('newName' => $key,
633 'groupName' => substr($key, 0, -3),
634 ));
635 }
636 else {
637 $name = array($key => array('newName' => $key, 'groupName' => $key));
638 }
639 CRM_Core_OptionGroup::lookupValues($paramsNew, $name, FALSE);
640 $row[] = $paramsNew[$key];
641 }
642 elseif (strpos($name, '-im')) {
643 if (!empty($result->$name)) {
644 $providerId = $name . "-provider_id";
645 $providerName = $imProviders[$result->$providerId];
646 $row[] = $result->$name . " ({$providerName})";
647 }
648 else {
649 $row[] = '';
650 }
651 }
652 elseif (strpos($name, '-phone-')) {
653 $phoneExtField = str_replace('phone', 'phone_ext', $name);
654 if (isset($result->$phoneExtField)) {
655 $row[] = $result->$name . " (" . $result->$phoneExtField . ")";
656 }
657 else {
658 $row[] = $result->$name;
659 }
660 }
661 elseif (in_array($name, array(
662 'addressee', 'email_greeting', 'postal_greeting'))) {
663 $dname = $name . '_display';
664 $row[] = $result->$dname;
665 }
666 elseif (in_array($name, array(
667 'birth_date', 'deceased_date'))) {
668 $row[] = CRM_Utils_Date::customFormat($result->$name);
669 }
670 elseif (isset($result->$name)) {
671 $row[] = $result->$name;
672 }
673 else {
674 $row[] = '';
675 }
676
677 if (!empty($result->$name)) {
678 $empty = FALSE;
679 }
680 }
681
682 $newLinks = $links;
683 $params = array(
684 'id' => $result->contact_id,
685 'gid' => implode(',', $this->_profileIds),
686 );
687
688 // pass record id param to view url for multi record view
689 if ($multiRecordTableId && $newLinks) {
690 if ($result->$multiRecordTableId){
691 if ($newLinks[CRM_Core_Action::VIEW]['url'] == 'civicrm/profile/view') {
692 $newLinks[CRM_Core_Action::VIEW]['qs'] .= "&multiRecord=view&recordId=%%recordId%%&allFields=1";
693 $params['recordId'] = $result->$multiRecordTableId;
694 }
695 }
696 }
697
698 if ($this->_linkToUF) {
699 $ufID = CRM_Core_BAO_UFMatch::getUFId($result->contact_id);
700 if (!$ufID) {
701 unset($newLinks[CRM_Core_Action::PROFILE]);
702 }
703 else {
704 $params['ufID'] = $ufID;
705 }
706 }
707
708 $row[] = CRM_Core_Action::formLink($newLinks,
709 $mask,
710 $params
711 );
712
713 if (!$empty) {
714 $rows[] = $row;
715 }
716 }
717 return $rows;
718 }
719
720 /**
721 * name of export file.
722 *
723 * @param string $output type of output
724 *
725 * @return string name of the file
726 */
727 function getExportFileName($output = 'csv') {
728 return ts('CiviCRM Profile Listings');
729 }
730
731 /**
732 * set the _multiRecordTableName to display the result set
733 * according to multi record custom field values
734 */
735 function setMultiRecordTableName($fields) {
736 $customGroupId = $multiRecordTableName = NULL;
737 $selectorSet = FALSE;
738
739 foreach ($fields as $field => $properties) {
740 if (!CRM_Core_BAO_CustomField::getKeyID($field)) {
741 continue;
742 }
743 if ($cgId = CRM_Core_BAO_CustomField::isMultiRecordField($field)) {
744 $customGroupId = CRM_Utils_System::isNull($customGroupId) ? $cgId : $customGroupId;
745
746 //if the field is submitted set multiRecordTableName
747 if ($customGroupId) {
748 $isSubmitted = FALSE;
749 foreach ($this->_query->_params as $key => $value) {
750 //check the query params 'where' element
751 if ($value[0] == $field) {
752 $isSubmitted = TRUE;
753 break;
754 }
755 }
756
757 if ($isSubmitted) {
758 $this->_multiRecordTableName = $multiRecordTableName =
759 CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroupId, 'table_name');
760 if ($multiRecordTableName) {
761 return;
762 }
763 }
764
765 if (CRM_Utils_Array::value('in_selector', $properties)) {
766 $selectorSet = TRUE;
767 }
768 }
769 }
770 }
771
772 if (!isset($customGroupId) || !$customGroupId) {
773 return;
774 }
775
776 //if the field is in selector and not a searchable field
777 //get the proper customvalue table name
778 if ($selectorSet) {
779 $this->_multiRecordTableName = $multiRecordTableName =
780 CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroupId, 'table_name');
781 }
782 } //func close
783}
784//end of class
785