/classes/forms.class.php
PHP | 3080 lines | 2314 code | 423 blank | 343 comment | 721 complexity | 9241f4cf853f563d49e48ce58fa196ae MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, Apache-2.0, GPL-2.0, LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- <?php
- //-- debugging
- //define('SHOW_QUERY' ,false);
- //-- InputType
- define('itNONE' ,'');
- define('itBUTTON' ,'button');
- define('itSUBMIT' ,'submit');
- define('itRESET' ,'reset');
- define('itCHECKBOX' ,'checkbox');
- define('itOPTION' ,'option');
- define('itPASSWORD' ,'password');
- define('itPLAINPASSWORD','plain_password');
- define('itTEXT' ,'text');
- define('itTEXTAREA' ,'textarea');
- define('itCOMBO' ,'combo');
- define('itLISTBOX' ,'listbox');
- define('itFILE' ,'file');
- define('itDATE' ,'date');
- define('itTIME' ,'time');
- define('itDATETIME' ,'datetime');
- //-- FilterCompareType
- define('ctCUSTOM' ,'{custom}');
- define('ctIGNORE' ,'{ignore}');
- define('ctMATCH' ,'{MATCH}');
- define('ctMATCHBOOLEAN' ,'{MATCH_BOOLEAN}');
- define('ctANY' ,'');
- define('ctEQ' ,'=');
- define('ctNOTEQ' ,'!=');
- define('ctLT' ,'<');
- define('ctGT' ,'>');
- define('ctLTEQ' ,'<=');
- define('ctGTEQ' ,'>=');
- define('ctLIKE' ,'LIKE');
- define('ctNOTLIKE' ,'NOT LIKE');
- define('ctIN' ,'IN');
- define('ctIS' ,'IS');
- define('ctISNOT' ,'IS NOT');
- define('ctREGEX' ,'REGEXP');
- define('ctBETWEEN' ,'BETWEEN');
- //-- Filter Sections
- define('FILTER_HAVING' ,'having');
- define('FILTER_WHERE' ,'where');
- //-- Date Formats
- // date
- // define("SQL_FORMAT_DATE" ,'%Y-%m-%d');
- // define("SQL_FORMAT_TIME" ,'%H:%i:%s');
- // define("SQL_FORMAT_DATETIME" ,SQL_FORMAT_DATE.' '.SQL_FORMAT_TIME);
- // define("SQL_FORMAT_EMPTY_DATE" ,'00/00/0000');
- // define("PHP_FORMAT_DATE" ,'d/m/Y'); // used with date(), but strftime() uses the SQL format
- // timestamp
- // define("SQL_FORMAT_TIMESTAMP" ,'%d/%m/%Y %H:%i:%s');
- // define("SQL_FORMAT_EMPTY_TIMESTAMP" ,'00/00/0000 00:00:00');
- // define("PHP_FORMAT_TIMESTAMP" ,'d/m/Y H:i:s'); // used with date(), but strftime() uses the SQL format
- // Javascript date/time regex:
- // datetimeRegex = new RegExp("([0-9]{2})/([0-9]{2})/([0-9]{4})( ([0-9]{2}):([0-9]{2}):([0-9]{2})(\.[0-9]+)?)?");
- // datetimeRegex = new RegExp("([0-9]{2})/([0-9]{2})/([0-9]{4}) ([0-9]{2}):([0-9]{2}):([0-9]{2})(\.[0-9]+)?|([0-9]{2})/([0-9]{2})/([0-9]{4})|([0-9]{2}):([0-9]{2}):([0-9]{2})(\.[0-9]+)?");
- // define('SQL_DATETIME_REGEX' ,"(([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})(\.[0-9]+)?)");
- // define('SQL_DATE_REGEX' ,"(([0-9]{4})-([0-9]{2})-([0-9]{2}))");
- // define('SQL_TIME_REGEX' ,"(([0-9]{2}):([0-9]{2}):([0-9]{2})(\.[0-9]+)?)");
- // define('DATETIME_REGEX' ,"((([0-9]{2})/([0-9]{2})/([0-9]{4}) ([0-9]{2}):([0-9]{2}):([0-9]{2})(\.[0-9]+)?)|(([0-9]{2})/([0-9]{2})/([0-9]{4}))|(([0-9]{2}):([0-9]{2}):([0-9]{2})(\.[0-9]+)?))");
- // MODULE OPTIONS
- define('ALWAYS_ACTIVE',flag_gen());
- define('INSTALL_INACTIVE',flag_gen());
- define('NO_HISTORY',flag_gen());
- define('DISTINCT_ROWS',flag_gen());
- define('ALLOW_FILTER',flag_gen());
- define('ALLOW_EDIT',flag_gen());
- define('ALLOW_ADD',flag_gen());
- define('ALLOW_DELETE',flag_gen());
- define('NO_NAV',flag_gen());
- define('PERSISTENT',flag_gen());
- define('PERSISTENT_PARENT',flag_gen());
- define('SHOW_FUNCTIONS',flag_gen());
- define('SHOW_TOTALS',flag_gen());
- define('LIST_HIDE_HEADER',flag_gen());
- define('LIST_HIDE_STATUS',flag_gen());
- define('DEFAULT_OPTIONS',ALLOW_FILTER);
- // START CLASSES
- class uFilter {
- public $filter;
- public $compareType;
- public $inputType;
- public $value;
- public function __construct($filter,$compareType,$inputType,$value) {
- $this->filter = $filter;
- $this->compareType = $compareType;
- $this->inputType = $inputType;
- $this->value = $value;
- }
- }
- class uDataset {
- protected $module = null;
- protected $query = null;
- protected $countQuery = null;
- protected $args = array();
- protected $recordCount = null;
-
- public function __construct($module,$filter,$clearFilters) {
- // initialise count
- $this->module = $module;
- $this->module->_SetupFields();
-
- if ($filter===NULL) $filter = array();
- if (isset($filter) && !is_array($filter)) $filter = array($this->module->GetPrimaryKey()=>$filter);
- $fltrs = $this->module->filters;
- if ($clearFilters) $this->module->ClearFilters();
- foreach ($filter as $field => $val) {
- if ($val instanceof uFilter) {
- if (($fltr =& $this->module->GetFilterInfo($val->filter))) {
- $fltr['value'] = $val->value;
- } else {
- $this->module->AddFilter($val->filter,$val->compareType,$val->inputType,$val->value);
- }
- continue;
- }
- if (is_numeric($field)) { // numeric key is custom filter
- $this->module->AddFilter($val,ctCUSTOM);
- continue;
- }
- if (($fltr =& $this->module->GetFilterInfo($field))) { // filter uid exists
- $fltr['value'] = $val;
- continue;
- }
- $this->module->AddFilter($field,ctEQ,itNONE,$val);
- }
- $this->BuildSqlQuery($this->args);
-
- $this->module->filters = $fltrs;
- }
- public function BuildSqlQuery(&$args) {
- // GET SELECT
- $select = $this->module->GetSelectStatement();
- // GET FROM
- $from = ' FROM '.$this->module->GetFromClause();
- // GET WHERE
- $where = $this->module->GetWhereStatement($args); $where = $where ? "\n WHERE $where" : ''; // uses WHERE modifier
- // GET GROUPING
- $group = $this->module->GetGrouping(); $group = $group ? "\n GROUP BY $group" : '';
- // GET HAVING
- $having = $this->module->GetHavingStatement($args); $having = $having ? "\n HAVING $having" : ''; // uses HAVING modifier to account for aliases
- // GET ORDER
- $order = $this->module->GetOrderBy(); $order = $order ? "\n ORDER BY $order" : '';
- $having1 = $this->module->GetFromClause() ? $having : '';
- $order1 = $this->module->GetFromClause() ? $order : '';
- $union = '';
- if (isset($this->module->UnionModules) && is_array($this->module->UnionModules)) {
- foreach ($this->module->UnionModules as $moduleName) {
- $obj = utopia::GetInstance($moduleName);
- $obj->_SetupFields();
- $select2 = $obj->GetSelectStatement();
- $from2 = ' FROM '.$this->module->GetFromClause();
- $where2 = $obj->GetWhereStatement($args); $where2 = $where2 ? "\n WHERE $where2" : '';
- $group2 = $obj->GetGrouping(); $group2 = $group2 ? "\n GROUP BY $group2" : '';
- $having2 = $obj->GetHavingStatement($args);
- $having2 = $having2 ? $having.' AND ('.$having2.')' : $having;
- // if (!empty($having2)) $having2 = $having.' AND ('.$having2.')';
- // else $having2 = $having;
- $order2 = $obj->GetOrderBy(); $order2 = $order2 ? "\n ORDER BY $order2" : '';
- $union .= "\nUNION\n(SELECT $select2$from2$where2$group2$having2$order2)";
- }
- $union .= " $order";
- }
-
- $this->query = "(SELECT $select$from$where$group$having1$order1)$union";
- if ($having) $this->countQuery = "(SELECT COUNT(*) FROM ((SELECT $select$from$where$group$having1$order1)$union) AS `_`)";
- else $this->countQuery = "(SELECT COUNT(*) FROM (SELECT NULL$from$where$group ORDER BY NULL) as `_`)";
- }
-
-
- public function DebugDump() {
- return $this->query."\n".var_export($this->args,true);
- }
-
- public function CountPages($items_per_page=10) {
- return (int)ceil($this->CountRecords() / $items_per_page);
- }
- public function CountRecords() {
- if ($this->recordCount === NULL) {
- try {
- $this->recordCount = database::query($this->countQuery,$this->args)->fetchColumn();
- } catch (Exception $e) { return 0; }
- }
- return $this->recordCount;
- }
-
- public function GetFirst() {
- return $this->GetOffset(0,1)->fetch();
- }
-
- /* page is zero indexed */
- public function &GetPage($page, $items_per_page=10) {
- $limit = '';
- if ($items_per_page > 0) {
- if ($page >= $this->CountPages($items_per_page)) $page = 0;
- $start = $items_per_page * $page;
- return $this->GetOffset($start,$items_per_page);
- }
- return $this;
- }
-
- public function &GetOffset($offset,$count) {
- $ql = $this->query.' LIMIT ?,?';
- $qa = $this->args; $qa[] = intval($offset); $qa[] = intval($count);
- $this->ds =& database::query($ql,$qa);
- return $this;
- }
-
- protected $ds = null;
- public function fetch() { return $this->CreateRecord($this->ds()->fetch()); }
- public function fetchAll() { return $this->CreateRecords($this->ds()->fetchAll()); }
- public function &ds() {
- if ($this->ds === null) $this->ds = database::query($this->query,$this->args);
- return $this->ds;
- }
-
- public function CreateRecords($rows) {
- if (!isset($rows) || !is_array($rows)) return $rows;
- $rc = count($rows);
- for ($i = 0; $i < $rc; $i++) {
- $rows[$i] = $this->CreateRecord($rows[$i]);
- }
- return $rows;
- }
- public function CreateRecord($row) {
- if (!isset($row) || !is_array($row)) return $row;
- // make link tables into array
- foreach ($row as $field=>$val) {
- if (empty($val)) continue;
- if (!isset($this->module->fields[$field])) continue;
- $fieldData = $this->module->fields[$field];
- if (!isset($fieldData['vtable'])) continue;
- if (!is_subclass_of($fieldData['vtable']['tModule'],'iLinkTable')) continue;
- $row[$field] = explode("\x1F",$val);
- }
- return $row;
- }
- }
- /**
- * Basic Utopia module. Enables use of adding parents and module to be installed and run.
- * No field or data access is available, use uDataModule and its decendants.
- */
- abstract class uBasicModule implements iUtopiaModule {
- public static function Initialise() {}
- /* static $singleton = NULL;
- public static function &call($method) {
- $null = NULL;
- if (self::$singleton == NULL) { ErrorLog('Singleton not configured'); }//ErrorLog("Error Calling {$classname}->{$funcname}"); return $null;}
- if (!method_exists(self::$singleton,$method)) { return $null; }
-
- $stack = debug_backtrace();
- $args = array();
- if (isset($stack[0]["args"]))
- for($i=2; $i < count($stack[0]["args"]); $i++)
- $args[$i-2] = & $stack[0]["args"][$i];
-
- $call = array(self::$singleton,$funcname);
- $return = call_user_func_array($call,$args);
-
- return $return;
- }
- public static function __callStatic($name, $arguments) {
- // Note: value of $name is case sensitive.
- $instance = utopia::GetInstance(get_class($this));
- return call_user_func_array(array($instance,$name),$arguments);
- }*/
- public function flag_is_set($flag) {
- $options = $this->GetOptions();
- return flag_is_set($options,$flag);
- }
- public function GetOptions() { return DEFAULT_OPTIONS; }
-
- protected $bypassSecurity = false;
- public function BypassSecurity($flag) {
- $this->bypassSecurity = $flag;
- }
- public function GetTitle() { return get_class($this); }
- public function GetDescription() {}
- public function GetKeywords() {}
- protected $isSecurePage = false;
- public function SetSecure() {
- $this->isSecurePage = true;
- }
- public $isDisabled = false;
- public function DisableModule($message='') {
- if (!$message) $message = true;
- $this->isDisabled = $message;
- }
-
- public function AssertURL($http_response_code = 301, $currentOnly = true) {
- if (!$currentOnly || get_class($this) == utopia::GetCurrentModule()) {
- $url = $this->GetURL($_GET);
- $checkurl = $_SERVER['REQUEST_URI'];
- if (($this->isSecurePage && !utopia::IsRequestSecure()) || $checkurl !== $url) {
- $abs = '';
- if ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') != $this->isSecurePage) {
- $layer = 'http';
- if ($this->isSecurePage) $layer .= 's';
- $abs = $layer.'://'.utopia::GetDomainName();
- }
- header('Cache-Control: no-store, no-cache, must-revalidate'); // don't cache redirects
- header('Location: '.$abs.$url,true,$http_response_code); die();
- }
- }
- }
- public $hasRun = false;
- public function _RunModule() {
- $this->AssertURL();
-
- if ($this->isDisabled) { echo $this->isDisabled; return; }
- // build linklist of children
- $children = utopia::GetChildren(get_class($this));
- foreach ($children as $child => $links) {
- $obj = utopia::GetInstance($child);
- foreach ($links as $info) {
- if ($obj->flag_is_set(ALLOW_ADD)
- && !$this->flag_is_set(ALLOW_ADD)
- && is_subclass_of($child,'uSingleDataModule')
- && ($info['parentField'] === NULL || $info['parentField'] === '*')) {
- $url = $obj->GetURL(array('_n_'.$obj->GetModuleId()=>'1'));
- utopia::LinkList_Add('list_functions:'.get_class($this),null,CreateNavButton('New '.$obj->itemName,$url,array('class'=>'new-item')),1);
- }
- }
- }
-
- // BEFORE
- ob_start();
- $beforeResult = uEvents::TriggerEvent('BeforeRunModule',$this);
- $beforeContent = ob_get_clean();
- if (utopia::UsingTemplate() && $beforeContent) $beforeContent = '<div class="module-container '.get_class($this).' BeforeRunModule">'.$beforeContent.'</div>';
- echo $beforeContent;
- if ($beforeResult === FALSE) return FALSE;
- // RUN
- ob_start();
- $result = $this->RunModule();
- $runContent = ob_get_clean();
- if (utopia::UsingTemplate() && $runContent) $runContent = '<div class="module-container '.get_class($this).' RunModule">'.$runContent.'</div>';
- echo $runContent;
- if ($result === FALSE) return false;
- $this->hasRun = true;
-
- // AFTER
- ob_start();
- $afterResult = uEvents::TriggerEvent('AfterRunModule',$this);
- $afterContent = ob_get_clean();
- if (utopia::UsingTemplate() && $afterContent) $afterContent = '<div class="module-container '.get_class($this).' AfterRunModule">'.$afterContent.'</div>';
- echo $afterContent;
- if ($afterResult === FALSE) return FALSE;
- }
- public $parentsAreSetup = false;
- public abstract function SetupParents();
- public function _SetupParents() {
- if ($this->parentsAreSetup) return;
- $this->parentsAreSetup = true;
- uEvents::TriggerEvent('BeforeSetupParents',$this);
- $this->SetupParents();
- uEvents::TriggerEvent('AfterSetupParents',$this);
- }
- public $parents = array();
- public function HasParent($parentModule) {
- $children = utopia::GetChildren($parentModule);
- return array_key_exists(get_class($this),$children);
- }
- public function HasChild($childModule) {
- $children = utopia::GetChildren(get_class($this));
- return array_key_exists($childModule,$children);
- }
- // parentModule =
- // sourceField = the field on the parent which the filter is taken from (generally the PK value of the current module)
- // destinationField = the field on the current module which the filter is set to.
- // parentField = the field which will be "linked from", if null or empty, a child button is created. allows easy injection to list forms.
- // EG: 'client list', array('client id'=>'client id'), 'client name' : applies a link from the "client name" field on the "client list" to open the current form where "client id" = "client id"
- // EG: 'client list', 'title', 'title id', 'title' : applies a link from the "title" field on the "client list" to open the current form where "title id" = "title"
- // EG: 'client form', 'client id', 'client id' : creates a button on the "client form" page to open the current form and where "client id" = "client id"
- // TODO: AddParent - overriden in data module
- // suggested change: sourceField, destinationField become an array of "filters", eg: array("title" => "title id")
- /**
- * Add a parent of this module, linked by a field.
- *
- * @param string $parentModule The classname of the parent
- * @param string|array optional $fieldLinks
- * @param string optional $parentField
- * @param string optional $text
- */
- public static function AddParent($parentModule,$fieldLinks=NULL,$parentField=NULL,$text=NULL) {
- if (isset($fieldLinks) && is_string($fieldLinks)) $fieldLinks = array(array('fromField'=>$fieldLinks,'toField'=>$fieldLinks,'ct'=>ctEQ));
- if (isset($fieldLinks) && is_array($fieldLinks) && !array_key_exists(0,$fieldLinks)) {
- if (array_key_exists('fromField',$fieldLinks) && array_key_exists('toField',$fieldLinks)) {
- $fieldLinks = array($fieldLinks);
- } else {
- // change from array(from>to) to new format
- $newFL = array();
- foreach ($fieldLinks as $from => $to) {
- $newFL[] = array('fromField'=>$from,'toField'=>$to,'ct'=>ctEQ);
- }
- $fieldLinks = $newFL;
- }
- }
- if (isset($fieldLinks) && !is_array($fieldLinks)) // must be null or array
- trigger_error('Cannot add parent ('.$parentModule.') of '.get_called_class().', fieldLinks parameter is an invalid type.',E_USER_ERROR);
- $info = array('parentField'=>$parentField, 'fieldLinks' => $fieldLinks, 'text' => $text);
- utopia::AddChild($parentModule, get_called_class(), $info);
-
- return $fieldLinks;
- }
- public static function AddChild($childModule,$fieldLinks=NULL,$parentField=NULL,$text=NULL) {
- //$childModule = (string)$childModule;
- //echo "addchild $childModule<br/>";
- //$obj = utopia::GetInstance($childModule);
- $childModule::AddParent(get_called_class(),$fieldLinks,$parentField,$text);
- }
- /**
- * Register this module to receive Ajax calls. Normal execution will be terminated in order to process the specified callback function.
- *
- * @param string $ajaxIdent
- * @param string $callback
- * @param (bool|function) $requireLogin Either True or False for admin login, or a custom callback function.
- * @return bool
- */
- public function RegisterAjax($ajaxIdent, $callback) {
- return utopia::RegisterAjax($ajaxIdent, $callback);
- }
- public function GetVar($varname) {
- return $this->$varname;
- }
- final static public function GetUUID() {
- $class = get_called_class();
- if (isset($class::$uuid)) return $class::$uuid;
- $uuid = preg_replace('((.{8})(.{4})(.{4})(.{4})(.+))','$1-$2-$3-$4-$5',md5($class));
- return $uuid;
- }
-
- public function GetModuleId() {
- return utopia::GetModuleId($this);
- }
-
- public $rewriteMapping=NULL;
- public $rewriteURLReadable=NULL;
- public $rewritePersistPath=FALSE;
- public function HasRewrite($field = NULL) {
- if ($this->rewriteMapping === NULL) return false;
- if ($field === NULL) return $this->rewriteMapping !== NULL;
- foreach ($this->rewriteMapping as $key => $map) {
- if (strpos($map,'{'.$field.'}') !== FALSE) return true;
- }
- return false;
- }
-
- /**
- * Indicate that this module should rewrite its URL
- * @param mixed $mapping NULL to turn off rewriting. FALSE to strip all but uuid. TRUE to allow longer path. ARRAY( '{fieldName}' , 'some-random-text' , '{another_field}' )
- * @param bool $URLReadable specifies that all segments of the url should be stripped of non-alphanumeric characters.
- */
- public function SetRewrite($mapping,$URLReadable = false) {
- if ($mapping === NULL) {
- $this->rewriteMapping = NULL; return;
- }
- if (is_string($mapping) && $mapping !== '') $mapping = array($mapping);
- if ($mapping === true) $this->rewritePersistPath = true;
- if (!is_array($mapping)) $mapping = array();
- // defaults?
- $this->rewriteMapping = $mapping;
- $this->rewriteURLReadable = $URLReadable;
-
- $this->ParseRewrite();
- }
- public function ParseRewrite($caseSensative = false) {
- if ($this->rewriteMapping === NULL) return FALSE;
- if (get_class($this) !== utopia::GetCurrentModule()) return FALSE;
- $uuid = $this->GetUUID(); if (is_array($uuid)) $uuid = reset($uuid);
-
- $sections = utopia::GetRewriteURL();
- $sections = preg_replace('/^'.preg_quote($uuid,'/').'\/?/','',$sections);
- $sections = explode('/',$sections);
- if (!$sections) return FALSE;
-
- $return = array('uuid'=>$uuid);
- foreach ($sections as $key => $value) {
- $replace = array();
- if (!array_key_exists($key,$this->rewriteMapping)) continue;
- $map = $this->rewriteMapping[$key];
- // generate preg for section
- if (preg_match_all('/{([a-zA-Z0-9_]+)}/',$map,$matches)) {
- foreach ($matches[1] as $match) {
- $map = str_replace('{'.$match.'}','(.*)',$map);
- $replace[] = $match;
- }
- }
- if (preg_match('/'.$map.'/',$value,$matches)) {
- unset($matches[0]);
- foreach($matches as $key => $match) {
- $return[$replace[$key-1]] = $match;
- }
- }
- }
- // TODO: named filters not being picked up
- $_GET = array_merge($return,$_GET);
- $_REQUEST = array_merge($return,$_REQUEST);
- return $return;
- }
- public function RewriteURL(&$filters) {
- $mapped = $this->rewriteMapping;
- foreach ($mapped as $key => $val) {
- if (preg_match_all('/{([a-zA-Z0-9_]+)}/',$val,$matches)) {
- $URLreadable = is_array($this->rewriteURLReadable) ? $this->rewriteURLReadable[$key] : $this->rewriteURLReadable;
- foreach ($matches[1] as $fieldName) {
- $newVal = '';
- if (array_key_exists($fieldName,$filters)) $newVal = $filters[$fieldName];
- elseif (array_key_exists('_f_'.$fieldName,$filters)) $newVal = $filters['_f_'.$fieldName];
- unset($filters[$fieldName]);
- unset($filters['_f_'.$fieldName]);
-
- if ($URLreadable) $newVal = trim(UrlReadable($newVal),'-');
- $mapped[$key] = str_replace('{'.$fieldName.'}',$newVal,$mapped[$key]);
- }
- }
- if ($mapped[$key] === preg_replace('/{([a-zA-Z0-9_]+)}/','',$val)) $mapped[$key] = '';
- $mapped[$key] = rawurlencode($mapped[$key]);
- }
- if (isset($filters['uuid'])) unset($filters['uuid']);
- $uuid = $this->GetUUID(); if (is_array($uuid)) $uuid = reset($uuid);
- array_unshift($mapped,$uuid);
- $newPath = PATH_REL_ROOT.join('/',$mapped);
- $oldPath = parse_url($_SERVER['REQUEST_URI'],PHP_URL_PATH);
- if (strpos($oldPath,'/u/')===0) $oldPath = str_replace('/u/','/',$oldPath);
- if ($this->rewritePersistPath && utopia::GetCurrentModule() == get_class($this)) $newPath .= str_replace($newPath,'',$oldPath);
- // DONE: ensure all rewrite segments are accounted for (all '/' are present)
- return rtrim($newPath,'/');
- }
- public function GetURL($filters = NULL) {
- if (!is_array($filters)) $filters = array();
- $uuid = $this->GetUUID(); if (is_array($uuid)) $uuid = reset($uuid);
- unset($filters['uuid']);
- $filters = array('uuid'=>$uuid) + $filters;
- $url = DEFAULT_FILE;
- if ($this->rewriteMapping !== NULL)
- $url = $this->RewriteURL($filters);
-
- $query = http_build_query($filters);
- if ($query) $query = '?'.$query;
-
- return $url.$query;
- }
- public function IsInstalled() {
- return utopia::ModuleExists(get_class($this));
- }
- public function GetSortOrder() {
- //if (is_object($module)) $module = get_class($module);
- // if (get_class($this) == utopia::GetCurrentModule()) return 1;
- return NULL;
- }
- public function __construct() { if (!defined('INIT_COMPLETE')) throw new Exception('No instances should be created until init is complete'); $this->_SetupParents(); }
- public abstract function RunModule(); // called when current_path = parent_path/<module_name>/
- }
- /**
- * Abstract class extending the basic module, adding data access and filtering.
- *
- */
- abstract class uDataModule extends uBasicModule {
- public function __construct() {
- parent::__construct();
- $this->_SetupFields();
- $parents = utopia::GetParents(get_class($this));
- foreach ($parents as $parent => $pArr) {
- foreach ($pArr as $info) {
- if (isset($info['fieldLinks'])) foreach ($info['fieldLinks'] as $link) {
- $this->AddFilter($link['toField'],ctEQ,itNONE);
- }
- }
- }
- }
- public $fields = array();
- public $filters = array(FILTER_WHERE=>array(),FILTER_HAVING=>array());
- public $sqlTableSetupFlat = NULL;
- public $sqlTableSetup = NULL;
- public $dataset = NULL;
- public $currentRecord = NULL;
- public $hasEditableFilters = FALSE;
- public function flag_is_set($flag,$field=null) {
- if ($field && isset($this->fields[$field]['options'])) return flag_is_set($this->fields[$field]['options'],$flag);
- return parent::flag_is_set($flag);
- }
- public abstract function GetTabledef();
- public abstract function SetupFields();
- public $isAjax = true;
-
- public $fieldsSetup = FALSE;
- public function _SetupFields() {
- if ($this->fieldsSetup == TRUE) return;
- $this->fieldsSetup = TRUE;
- $fltr =& $this->AddFilter(array($this,'GetGlobalSearch'),ctCUSTOM,'search',null,null,'Search');
- $fltr['uid'] = $this->GetModuleId().'_global_search_';
- $fltr['attributes']['class'] = 'uGlobalSearch';
-
- uEvents::TriggerEvent('BeforeSetupFields',$this);
- $this->SetupFields();
- $this->SetupUnionFields();
- if (is_array($this->UnionModules)) foreach ($this->UnionModules as $modulename) {
- $obj = utopia::GetInstance($modulename);
- $obj->_SetupFields();
- }
- uEvents::TriggerEvent('AfterSetupFields',$this);
- }
- public function GetStringFields() {
- $ignoreTypes = array(ftIMAGE,ftFILE);
- $fields = array();
- foreach ($this->sqlTableSetupFlat as $t) {
- $o = utopia::GetInstance($t['tModule']);
- foreach ($o->fields as $f => $finfo) {
- if (in_array($finfo['type'],$ignoreTypes)) continue;
- $fields[] = "`{$t['alias']}`.`{$f}`";
- }
- }
- return $fields;
- }
- public function GetGlobalSearch($val,&$args) {
- if (!$val) return '';
- $all = array(array());
- $cAll = count($all);
- $fields = $this->GetStringFields();
-
- // match phrases
- preg_match_all('/(".+?")|([\w\+\']+)/',$val,$matches);
- foreach ($matches[0] as $v) {
- $v = trim($v,'"');
- switch (strtolower($v)) {
- case 'or': $all[] = array(); $cAll = count($all);
- case 'and': continue 2;
- }
- $allflds = array();
- foreach ($fields as $f) {
- $args[] = '%'.$v.'%';
- $allflds[] = $f.' LIKE ?';
- }
- $all[$cAll-1][] = '('.implode(' OR ',$allflds).')'.PHP_EOL;
- }
-
- $a = array();
- foreach ($all as $or) {
- $a[] = implode(' AND ',$or);
- }
-
- return implode(' OR ',$a);
- }
- public function ParseRewrite($caseSensative = false) {
- $this->_SetupFields();
- $parsed = parent::ParseRewrite($caseSensative);
- if (!$parsed) return FALSE;
- foreach ($parsed as $key => $val) {
- // check for filter with key
- $filter =& $this->FindFilter($key);
- if ($filter) $filter['value'] = $val;
- }
- return $parsed;
- }
- /* public function RewriteURL($filters) {
- foreach ($filters as $key => $val) {
- $fltr =& $this->FindFilter($key);
- if ($fltr) {
- $filters['_f_'.$fltr['uid']] = $val;
- unset($filters[$key]);
- }
- }
- //print_r($filters);
- return parent::RewriteURL($filters);
- }*/
- public function MergeRewriteFilters(&$filters,$rec) {
- if (!is_array($filters)) return false;
- if (!$this->HasRewrite()) return false;
- if (!$rec) return false;
- foreach ($this->rewriteMapping as $seg) {
- if (preg_match_all('/{([a-zA-Z0-9_]+)}/',$seg,$matches)) {
- foreach ($matches[1] as $match) {
- if (isset($filters[$match])) continue;
- if (array_key_exists($match,$rec)) $filters[$match] = $rec[$match];
- $fltr = $this->FindFilter($match);
- if (!$fltr) continue;
- unset($filters['_f_'.$fltr['uid']]);
- }
- }
- }
- return true;
- }
- public function RewriteFilters(&$filters = NULL) {
- if (!is_array($filters)) return false;
- if (!$this->HasRewrite()) return false;
- foreach ($filters as $uid => $val) {
- $fltr = $this->GetFilterInfo(substr($uid,3));
- if (!$fltr) continue;
- if ($fltr['default'] == $fltr['value']) continue;
- $filters[$fltr['fieldName']] = $val;
- unset($filters[$uid]);
- }
- if (array_key_exists($this->GetPrimaryKey(), $filters)) {
- foreach ($this->rewriteMapping as $seg) {
- if (preg_match_all('/{([a-zA-Z0-9_]+)}/',$seg,$matches)) {
- foreach ($matches[1] as $match) {
- if (isset($filters[$match])) continue;
- $rec = $this->LookupRecord($filters[$this->GetPrimaryKey()],true);
- if (!$rec) return;
- $this->MergeRewriteFilters($filters,$rec);
- return;
- }
- }
- }
- }
- return true;
- }
- public function GetURL($filters = NULL) {
- $this->_SetupParents();
- $this->_SetupFields();
- if ($filters === FALSE) return parent::GetURL($filters);
- if (!is_array($filters) && $filters !== NULL) {
- $f = $this->FindFilter($this->GetPrimaryKey());
- if ($f) $filters = array('_f_'.$f['uid']=>$filters);
- else $filters = array($this->GetPrimaryKey()=>$filters);
- }
-
- foreach ($this->filters as $filterType) {
- foreach ($filterType as $filterSet) {
- foreach ($filterSet as $filter) {
- // is the current filter referenced in $filters? if not, continue;
- if (!is_callable($filter['fieldName']) && !isset($filters[$filter['fieldName']]) && !isset($filters['_f_'.$filter['uid']])) continue;
-
- $val = $this->GetFilterValue($filter['uid']);
- if (!is_callable($filter['fieldName']) && isset($filters[$filter['fieldName']])) $val = $filters[$filter['fieldName']];
- if (isset($filters['_f_'.$filter['uid']])) $val = $filters['_f_'.$filter['uid']];
-
- /*if (!empty($filter['default']) && $val == $filter['default']) {
- unset($filters[$filter['fieldName']]);
- unset($filters['_f_'.$filter['uid']]);
- continue;
- }*/
- if (!$val) continue;
- if ($this->HasRewrite($filter['fieldName'])) {
- if (isset($filters[$filter['fieldName']])) continue;
- $filters[$filter['fieldName']] = $val;
- unset($filters['_f_'.$filter['uid']]);
- continue;
- }
- continue; // skip below
- $filters['_f_'.$filter['uid']] = $val;
- unset($filters[$filter['fieldName']]);
- }
- }
- }
- $this->RewriteFilters($filters);
- return parent::GetURL($filters);
- }
- public function GetEncodedFieldName($field,$pkValue=NULL) {
- $pk = is_null($pkValue) ? '' : "($pkValue)";
- return cbase64_encode(get_class($this).":$field$pk");
- }
- public function CreateSqlField($field,$pkValue) {
- return "usql-".$this->GetEncodedFieldName($field,$pkValue);
- }
-
- public function GetDeleteButton($pk,$btnText = NULL,$title = NULL) {
- $title = $title ? "Delete '$title'" : 'Delete Record';
- return '<a class="btn btn-del" name="'.$this->CreateSqlField('__u_delete_record__',$pk).'" href="#" title="'.$title.'">'.$btnText.'</a>';
- }
- public function DrawSqlInput($field,$defaultValue='',$pkValue=NULL,$attributes=NULL,$inputTypeOverride=NULL,$valuesOverride=NULL) {
- $of = $field;
- if (strpos($field,':') !== FALSE) list($field) = explode(':',$field);
- if ($attributes==NULL) $attributes = array();
- if (isset($this->fields[$field]['attr'])) $attributes = array_merge($this->fields[$field]['attr'],$attributes);
- $inputType = $inputTypeOverride ? $inputTypeOverride : $this->fields[$field]['inputtype'];
- $length = $this->GetFieldProperty($field,'length') ? $this->GetFieldProperty($field,'length') : $this->GetTableProperty($field,'length');
- $values = $valuesOverride ? $valuesOverride : $this->GetValues($field,$pkValue);
- if (isset($this->fields[$field]['vtable']['parent']) && !is_subclass_of($this->fields[$field]['vtable']['tModule'],'iLinkTable') && $pkValue !== NULL) {
- $rec = null;
- foreach ($this->fields[$field]['vtable']['joins'] as $from=>$to) {
- if ($from == $field) {
- if (!$rec) $rec = $this->LookupRecord($pkValue);
- $defaultValue = $rec[$this->GetPrimaryKeyConstant($field)];
- break;
- }
- }
- }
- if (!isset($attributes['class'])) $attributes['class'] = '';
- if ($this->isAjax) $attributes['class'] .= ' uf';
- $attributes['class'] = trim($attributes['class']);
- $fieldName = $this->CreateSqlField($of,$pkValue);
- if ($inputType == itFILE) $attributes['id'] = $fieldName;
- return utopia::DrawInput($fieldName,$inputType,$defaultValue,$values,$attributes);
- }
- public function GetPrimaryKeyConstant($fieldAlias=NULL) {
- if (!is_null($fieldAlias)) {
- return '_'.$this->GetFieldProperty($fieldAlias,'tablename').'_pk';
- }
- return '_'.$this->sqlTableSetup['alias'].'_pk';
- }
-
- public function GetPrimaryKey() {
- return $this->sqlTableSetup['pk'];
- }
- public $pkt = NULL;
- public function GetPrimaryKeyTable($fieldAlias=NULL) {
- if (!is_null($fieldAlias)) {
- $setup = $this->sqlTableSetupFlat[$this->GetFieldProperty($fieldAlias,'tablename')];
- return $setup['pk'];
- }
- return $this->sqlTableSetup['pk'];
- }
- public $pt = NULL;
- public function GetPrimaryTable($fieldAlias=NULL) {
- if (!is_null($fieldAlias)) {
- $setup = $this->sqlTableSetupFlat[$this->GetFieldProperty($fieldAlias,'tablename')];
- return $setup['table'];
- }
- if ($this->pt == NULL) $this->pt = TABLE_PREFIX.$this->GetTabledef();
- return $this->pt;
- }
- public $UnionModules = NULL;
- public $UNION_MODULE = FALSE;
- public function AddUnionModule($modulename) {
- // check fields match! Union modules MUST have identical fields
- $this->UNION_MODULE = TRUE;
- if ($this->UnionModules == NULL) {
- $this->UnionModules = array();
- // $this->_SetupFields();
- // $this->AddField('__module__',"'".get_class($this)."'",'');
- // $tbl = is_array($this->sqlTableSetup) ? $this->sqlTableSetup['alias'] : '';
- // $this->AddField('__module_pk__',$this->GetPrimaryKey(),$tbl);
- }
- $this->UnionModules[] = $modulename;
- $obj = utopia::GetInstance($modulename);
- $obj->UNION_MODULE = TRUE;
- }
- public function AddUnionParent($parentModule) {
- $obj = utopia::GetInstance($parentModule);
- $obj->AddUnionModule(get_class($this));
- }
- public function SetupUnionFields() {
- if ($this->UNION_MODULE !== TRUE) return;
- $this->AddField('__module__',"'".get_class($this)."'",'');
- $tbl = is_array($this->sqlTableSetup) ? $this->sqlTableSetup['alias'] : '';
- $this->AddField('__module_pk__',$this->GetPrimaryKey(),$tbl);
- }
- // this value will be used on new records or field updates
- public function SetDefaultValue($name,$moduleOrValue,$getField=NULL,$valField=NULL,$onlyIfNull=FALSE) { //,$whereField=NULL,$rowField=NULL) {
- if ($getField==NULL || $valField==NULL) {
- $this->SetFieldProperty($name,'default_value',$moduleOrValue);
- } else {
- $this->SetFieldProperty($name,'default_lookup',array('module'=>$moduleOrValue,'getField'=>$getField,'valField'=>$valField));
- // create a callback, when valField is updated, to set value of $name to the new DefaultValue (IF that value is empty?)
- if (!array_key_exists($valField,$this->fields) && get_class($this) != utopia::GetCurrentModule() && utopia::GetCurrentModule()) {
- $obj = utopia::GetInstance(utopia::GetCurrentModule());
- $obj->AddOnUpdateCallback($valField,array($this,'RefreshDefaultValue'),$name,$onlyIfNull);
- } else
- $this->AddOnUpdateCallback($valField,array($this,'RefreshDefaultValue'),$name,$onlyIfNull);
- }
- }
- protected function RefreshDefaultValue($pkVal, $fieldName,$onlyIfNull) {
- $row = $this->LookupRecord($pkVal);
- if ($row == NULL) return;
- if ($onlyIfNull && !empty($row[$fieldName])) return;
- //$pkVal = $row[$this->GetPrimaryKey()];
- $dVal = $this->GetDefaultValue($fieldName);
- // echo "update $fieldName on $pkVal to: $dVal";
- $this->UpdateField($fieldName,$dVal,$pkVal);
- }
- public function GetDefaultValue($name) {
- // echo "GetDefaultValue($name)";
- // default value should take implicit value as priority over filter value?
- // NO implicit value takes priority
- // is d_v set?
- $dv = $this->GetFieldProperty($name,'default_value');
- if (!empty($dv)) return $dv;
- // is d_l set? lookup value... lookup field from module,,, what about WHERE?
- $dl = $this->GetFieldProperty($name,'default_lookup');
- if (!empty($dl)) {
- // find the value of valField
- $row = $this->GetCurrentRecord();
- return $row[$dl['getField']];
- }
- // is filter set?
- //print_r($this->filters);
- //AjaxEcho("//no predifined default set, searching filters");
- $fltr =& $this->FindFilter($name,ctEQ);
- if ($fltr === NULL) return '';
- $uid = $fltr['uid'];
- $value = $this->GetFilterValue($uid);
- if (!empty($value)) return $value;
- return '';
- // not processed
- /* foreach ($this->filters[FILTER_WHERE] as $filterset) {
- if (!array_key_exists($name,$filterset))continue;
- $filterData = $filterset[$name];
- if (empty($filterData)) continue;
- if ($filterData['ct'] != ctEQ) continue;
- return $filterData['value'];
- }
- foreach ($this->filters[FILTER_HAVING] as $filterset) {
- if (!array_key_exists($name,$filterset))continue;
- $filterData = $filterset[$name];
- if (empty($filterData)) continue;
- if ($filterData['ct'] != ctEQ) continue;
- return $filterData['value'];
- }*/
- }
- public function GetLookupValue($alias,$pkValue) {
- if (empty($pkValue)) return;
- $this->_SetupFields();
- $fieldData = $this->fields[$alias];
- $str = $this->GetFieldLookupString($alias)." as `$alias`";
- $table = $fieldData['vtable']['table'];
- $pk = $fieldData['vtable']['pk'];
- $stm = database::query("SELECT $str FROM $table as {$fieldData['tablename']} WHERE $pk = ?",array($pkValue));
- $row = $stm->fetch();
- if (empty($row[$alias])) return $pkValue;
- return $row[$alias];
- }
-
- public function TableExists($alias) {
- return array_key_exists($alias,$this->sqlTableSetupFlat);
- }
- /**
- * Creates a virtual table for use within the module. Allowing access to fields within the database.
- * @param string $alias table alias
- * @param string $tableModule classname of the uTableDef
- * @param string $parent alias of the table to join to
- * @param mixed $joins string if fields to join have the same name, array to specify different fields array('parent_field'=>'local_field')
- * @param string $joinType specify the type of join to perform (default: LEFT JOIN)
- * @see AddField
- */
- public function CreateTable($alias, $tableModule=NULL, $parent=NULL, $joins=NULL, $joinType='LEFT JOIN') {
- // nested array
- // first create the current alias
- if ($tableModule == NULL) $tableModule = $this->GetTabledef();
- // $alias = strtolower($alias);
- // $parent = strtolower($parent);
- // $fromField = strtolower($fromField);
- // $toField = strtolower($toField);
- if (!$this->sqlTableSetupFlat) $this->sqlTableSetupFlat = array();
- if ($this->TableExists($alias)) { throw new Exception("Table with alias '$alias' already exists"); return; }
- $tableObj = utopia::GetInstance($tableModule);
- $newTable = array();
- $this->sqlTableSetupFlat[$alias] =& $newTable;
- $newTable['alias'] = $alias;
- $newTable['table'] = TABLE_PREFIX.$tableModule;
- $newTable['pk'] = $tableObj->GetPrimaryKey();
- $newTable['tModule']= $tableModule;
-
- $this->AddField('_'.$alias.'_pk',$newTable['pk'],$alias);
- //$this->AddFilter('_'.$alias.'_pk',ctEQ,itNONE);
-
- if ($parent==NULL) {
- if ($this->sqlTableSetup != NULL) {
- ErrorLog('Can only have one base table');
- return;
- }
- $this->sqlTableSetup = $newTable;
- $this->AddField($newTable['pk'],$newTable['pk'],$alias);
- $this->AddFilter($newTable['pk'],ctEQ,itNONE);
- $this->AddField('_module',"'".get_class($this)."'",$alias);
- return;
- } else {
- $newTable['parent'] = $parent;
- }
- // $fromField in $this->sqlTableSetupFlat[$parent]['tModule']
- if (is_string($joins)) $joins = array($joins=>$joins);
- if (is_array($joins)) {
- $fromTable = utopia::GetInstance($this->sqlTableSetupFlat[$parent]['tModule']);
- $toTable = utopia::GetInstance($tableModule);
- foreach ($joins as $fromField => $toField) {
- if (!$fromTable->IsIndex($fromField)) error_log("Field `$fromField` used as lookup but NOT an indexed field in table `".$this->sqlTableSetupFlat[$parent]['tModule'].'`.');
- if (!$toTable->IsIndex($toField)) error_log("Field `$toField` used as lookup but NOT an indexed field in table `".$tableModule.'`.');
- }
- }
- //$newTable['fromField'] = $fromField;
- //$newTable['toField'] = $toField;
- $newTable['parent'] = $parent;
- $newTable['joins'] = $joins;
- $newTable['joinType'] = $joinType;
- // $this->sqlTableSetupFlat[$alias] = $newTable;
- // search through the table setup looking for the $linkFrom alias
- if (($srchParent =& $this->recurseSqlSetupSearch($this->sqlTableSetup,$parent))) {
- // found, add it
- if (!array_key_exists('children',$srchParent)) $srchParent['children'] = array();
- $srchParent['children'][] = $newTable;
- } else {
- // not found.. throw error
- ErrorLog("Cannot find $parent");
- }
- if (is_subclass_of($tableModule,'iLinkTable')) {
- $this->AddGrouping($this->GetPrimaryKey());
- }
- }
- public function GetValues($alias,$pkVal=null,$stringify = FALSE) {
- if (!is_string($alias)) return;
-
- $values = null;
- if (!isset($this->fields[$alias])) {
- $fltr =& $this->FindFilter($alias);
- $values = $fltr['values'];
- if (!is_array($values) && is_string($fltr['fieldName']) && isset($this->fields[$fltr['fieldName']])) $values = $this->GetValues($fltr['fieldName'],$pkVal,$stringify);
- } else {
- $values = $this->fields[$alias]['values'];
- }
- if (is_callable($values)) return call_user_func_array($values,array($this,$alias,$pkVal));
-
- if (!is_array($values) && IsSelectStatement($values)) {
- $values = database::getKeyValuePairs($values);
- }
-
- if ($stringify && is_array($values) && $values) {
- $values = array_combine(array_values($values),array_values($values));
- }
- return $values;
- }
- public function SetFieldOptions($alias,$newoptions) {
- $this->SetFieldProperty($alias,'options',$newoptions);
- }
- protected $spacerCount = NULL;
- public function AddSpacer($text = ' ',$titleText = '') {
- if ($this->spacerCount === NULL) $this->spacerCount = 0;
- $this->AddField("__spacer_{$this->spacerCount}__","'$text'",'',"$titleText");
- $this->spacerCount = $this->spacerCount + 1;
- }
- public function CharAlign($alias,$char) {
- $this->fields[$alias]['charalign'] = $char;
- }
- public function SetFormat($alias,$format,$condition = TRUE) {
- $this->fields[$alias]['formatting'][] = array('format' =>$format, 'condition' => $condition);
- }
- public $layoutSections = array();
- public $cLayoutSection = null;
- public function NewSection($title,$order = null) {
- if ($order === null) $order = count($this->layoutSections);
- $a = array('title'=>$title,'order'=>$order);
- $found = false;
- foreach ($this->layoutSections as $k => $i) {
- if ($i['title'] == $title) {
- $this->layoutSections[$k] = $a; $found = $k; break;
- }
- }
- $this->cLayoutSection = $found;
- if ($found === FALSE) {
- $this->layoutSections[] = $a;
- $this->cLayoutSection = count($this->layoutSections) -1;
- }
- array_sort_subkey($this->layoutSections,'order');
- }
- public function RenameSection($old,$new) {
- foreach ($this->layoutSections as $k => $i) {
- if ($i['title'] == $old) {
- $this->layoutSections[$k]['title'] = $new; break;
- }
- }
- }
- protected $defaultStyles = array();
- public function FieldStyles_SetDefault($inputType,$style) {
- if (!is_array($style)) { ErrorLog("Field Style is not an array ($field)"); return; }
- $this->defaultStyles[$inputType] = $style;
- }
- public function FieldStyles_Set($field,$style) {
- if (!is_array($style)) { ErrorLog("Field Style is not an array ($field)"); return; }
- $this->fields[$field]['style'] = $style;
- }
- public function FieldStyles_Add($field,$style) {
- if (!is_array($style)) { ErrorLog("Field Style is not an array ($field)"); return; }
- foreach ($style as $key=>$val)
- $this->fields[$field]['style'][$key] = $val;
- }
- public function FieldStyles_Unset($field,$key) {
- unset($this->fields[$field]['style'][$key]);
- }
- public function FieldStyles_Get($field,$rec=NULL) {
- if (strpos($field,':') !== FALSE) list($field) = explode(':',$field);
- if (!isset($this->fields[$field])) return null;
- $inputType = $this->fields[$field]['inputtype'];
- $defaultStyles = array_key_exists($inputType,$this->defaultStyles) ? $this->defaultStyles[$inputType] : array();
- $specificStyles = $this->GetFieldProperty($field,'style'); if (!$specificStyles) $specificStyles = array();
- $conditionalStyles = array();
-
- if (isset($this->fields[$field]['style_fn']) && is_callable($this->fields[$field]['style_fn'][0])) {
- $args = $this->fields[$field]['style_fn'][1];
- if (is_array($args)) array_unshift($args,$rec); else $args = array($rec);
- array_unshift($args,$field);
- $conditionalStyles = call_user_func_array($this->fields[$field]['style_fn'][0],$args);
- }
- if (!$conditionalStyles) $conditionalStyles = array();
- $styles = array_merge($defaultStyles,$specificStyles,$conditionalStyles);
-
- // if width/height has no delimiter, append 'px'
- if (isset($styles['width']) && is_numeric($styles['width'])) $styles['width'] = $styles['width'].'px';
- if (isset($styles['height']) && is_numeric($styles['height'])) $styles['height'] = $styles['height'].'px';
- return $styles;
- }
- public function ConditionalStyle_Set($field,$callback,$args=null) {
- $this->fields[$field]['style_fn'] = array($callback,$args);
- }
- public function ConditionalStyle_Unset($field) {
- unset($this->fields[$field]['style_fn']);
- }
- /**
- * Defines a virtual field in the module, allowing access to the data within the database.
- * @see CreateTable
- */
- public function &AddField($aliasName,$fieldName,$tableAlias=NULL,$visiblename=NULL,$inputtype=itNONE,$values=NULL) {//,$options=0,$values=NULL) {
- $this->_SetupFields();
- if ($tableAlias === NULL) $tableAlias = $this->sqlTableSetup['alias'];
-
- $this->fields[$aliasName] = array(
- 'alias' => $aliasName,
- 'tablename' => $tableAlias,
- 'visiblename' => $visiblename,
- 'inputtype' => $inputtype,
- 'options' => NULL, // this can be re-set using $this->SetFieldOptions
- 'field' => $fieldName,
- );
- $this->fields[$aliasName]['order'] = count($this->fields);
-
- $before = $this->insertBefore;
- if (is_string($before) && isset($this->fields[$before])) {
- $this->fields[$aliasName]['order'] = $this->fields[$before]['order'] - 0.5;
- }
- if (is_array($fieldName)) {
- $this->fields[$aliasName]['field'] = "";
- $this->AddPreProcessCallback($aliasName, $fieldName);
- }
- if ($tableAlias) $this->fields[$aliasName]['vtable'] = $this->sqlTableSetupFlat[$tableAlias];
- switch ($this->GetFieldType($aliasName)) {
- case ftFILE:
- case ftIMAGE:
- case ftUPLOAD:
- $this->AddField($aliasName.'_filename', $fieldName.'_filename', $tableAlias);
- $this->AddField($aliasName.'_filetype', $fieldName.'_filetype', $tableAlias);
- break;
- case ftCURRENCY:
- $list = uLocale::ListLocale();
- $this->AddField($aliasName.'_locale', $fieldName.'_locale', $tableAlias,(count($list)>1 ? 'Currency' : NULL),itCOMBO,$list);
- $this->AddPreProcessCallback($aliasName,array('utopia','convCurrency'));
- break;
- case ftDATE:
- $this->AddPreProcessCallback($aliasName,array('utopia','convDate'));
- break;
- case ftTIME:
- $this->AddPreProcessCallback($aliasName,array('utopia','convTime'));
- break;
- case ftDATETIME:
- case ftTIMESTAMP:
- $this->AddPreProcessCallback($aliasName,array('utopia','convDateTime'));
- break;
- }
- // values here
- if ($values === NULL) switch ($inputtype) {
- //case itNONE: // commented to prevent huge memory usage on BLOB fields. Set Values to true if you need it!
- case itCOMBO:
- case itOPTION:
- $values = true;
- default:
- break;
- }
- $this->fields[$aliasName]['values'] = $values;
- if ($visiblename !== NULL) {
- if (!$this->layoutSections) $this->NewSection('');
- $this->fields[$aliasName]['layoutsection'] = $this->cLayoutSection;
- }
- return $this->fields[$aliasName];
- }
- protected $insertBefore = null;
- public function SetAddFieldPosition($before=null) {
- $this->insertBefore = $before;
- }
- public function GetFields($visibleOnly=false,$layoutSection=NULL) {
- $arr = $this->fields;
- array_sort_subkey($arr,'order');
- foreach ($arr as $fieldName=>$fieldInfo) {
- if ($visibleOnly && $fieldInfo['visiblename']===NULL) unset($arr[$fieldName]);
- if ($layoutSection !== NULL && array_key_exists('layoutsection',$fieldInfo) && $fieldInfo['layoutsection'] !== $layoutSection) unset($arr[$fieldName]);
- }
- return $arr;
- }
- public function AssertField($field,$reference = NULL) {
- if (isset($this->fields[$field])) return TRUE;
- if (IsSelectStatement($field)) return FALSE;
- $found = useful_backtrace(0);
- ErrorLog("Field ($field) does not exist for {$found[0][0]}:{$found[0][1]} called by {$found[1][0]}:{$found[1][1]}.".($reference ? " Ref: $reference" : ''));
- }
- public function AddOnUpdateCallback($alias,$callback) {
- $this->_SetupFields();
- if (!$this->AssertField($alias)) return FALSE;
- // echo "add callback ".get_class($this).":$alias";
- $numargs = func_num_args();
- $arr = array();
- for ($i = 2; $i < $numargs; $i++)
- $arr[] = func_get_arg($i);
- $this->fields[$alias]['onupdate'][] = array($callback,$arr);
- return TRUE;
- }
- /** Instructs the core to send information to a custom function.
- * Accepts any number of args, passed to the callback function when the PreProcess function is called.
- * -- callback($fieldValue,...)
- * @param string Field Alias to attach the callback to.
- * @param function Reference to the function to call.
- * @param ... additional data
- */
- public function AddPreProcessCallback($alias,$callback) {
- if (!$this->FieldExists($alias)) return FALSE;
- if (count($callback) > 2) {
- $arr = array_splice($callback,2);
- } else {
- $numargs = func_num_args();
- $arr = array();
- for ($i = 2; $i < $numargs; $i++)
- $arr[] = func_get_arg($i);
- }
- $this->fields[$alias]['preprocess'][] = array($callback,$arr);
- }
- public function AddDistinctField($alias) {
- if (!$this->AssertField($alias)) return FALSE;
- // get original field
- $original = $this->fields[$alias];
- $this->AddField("distinct_$alias",'count('.$original['tablename'].'.'.$original['field'].')','',"count($alias)");
- $this->AddFilter("distinct_$alias",ctGTEQ,itNONE,1);
- }
- public $grouping = NULL;
- public function AddGrouping($alias,$clear = false) {
- if (!$this->grouping || $clear) $this->grouping = array();
- if (isset($this->fields[$alias])) $alias = '`'.$this->fields[$alias]['tablename'].'`.`'.$this->fields[$alias]['field'].'`';
- else $alias = '`'.$alias.'`';
- $this->grouping[] = $alias;
- }
- public $ordering = NULL;
- public function AddOrderBy($fieldName,$direction = 'ASC') {
- $fieldName = trim($fieldName);
- if ($this->ordering === NULL) $this->ordering = array();
- if (strpos($fieldName,',') !== FALSE) {
- foreach(explode(',',$fieldName) as $f) {
- $f = trim($f);
- $dir = 'ASC';
- if (strpos($f,' ') !== FALSE) list($f,$dir) = explode(' ',$f);
- $this->AddOrderBy($f,$dir);
- }
- return;
- }
- if (strpos($fieldName,' ') !== FALSE) {
- list($fieldName,$direction) = explode(' ',$fieldName);
- $fieldName = trim($fieldName);
- $direction = trim($direction);
- }
-
- if ($this->FieldExists($fieldName)) $fieldName = "`$fieldName`";
- $this->ordering[] = "$fieldName $direction";
- }
- /* FILTERS */
- // Filters work on a set/rule basis, each set contains rules which are AND'ed, and each set is then OR'd together this creates full flexibility with filtering the results.
- // EG: (set1.rule1 and set1.rule2) or (set2.rule1)
- // create a new set by calling $this->NewFilterset();
- public function NewFiltersetWhere() {
- $this->filters[FILTER_WHERE][] = array();
- }
- public function NewFiltersetHaving() {
- $this->filters[…
Large files files are truncated, but you can click here to view the full file