Xataface  2.0alpha2
Xataface Application Framework
 All Data Structures Namespaces Files Functions Variables Groups Pages
public-api.php
Go to the documentation of this file.
1 <?php
2 /*
3  * Xataface Web Application Framework
4  * Copyright (C) 2005-2011 Web Lite Solutions Corp (shannah@sfu.ca)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * @file dataface-public-api.php
21  * Author: Steve Hannah <shannah@sfu.ca>
22  * Created: December 14, 2005
23  *
24  * Description:
25  * ------------
26  * A Procedural API to the Dataface framework. This is designed to same developers
27  * time trying to figure out what all the classes are and what they do. This api
28  * provides functions to access all importand aspects of the framework.
29  *
30  */
31 
32 
33 if ( !defined( 'DATAFACE_PUBLIC_API_LOADED' ) ){
34 define('DATAFACE_PUBLIC_API_LOADED', true);
35 
50 function df_init($site_path, $dataface_url, $conf=null){
51  require_once dirname(__FILE__).'/init.php';
52  init($site_path, $dataface_url);
53 
54  import( 'PEAR.php');
55  import( 'Dataface/Application.php');
56 
57 
59  if ( df_get_file_system_version() != df_get_database_version() ){
60  $res = df_update();
61  if (PEAR::isError($res) ){
62  throw new Exception($res->getMessage(), E_USER_ERROR);
63  }
64  }
65  return $app;
66 
67 }
68 /* @} */
69 
70 function df_secure(&$records, $secure=true){
71  foreach ($records as $record){
72  $record->secureDisplay = $secure;
73  }
74 }
75 
76 if ( !function_exists('xmlentities') ){
77  function xmlentities($string) {
78  return str_replace ( array ( '&', '"', "'", '<', '>', '' ), array ( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;', '&apos;' ), $string );
79  }
80 }
81 
82 function df_update(){
83  import('actions/install.php');
84  $action = new dataface_actions_install;
85  $params = array();
86  $res = $action->handle($params);
87  if ( PEAR::isError($res) ){
88  return $res;
89  }
90 
91 }
92 
93 
94 
95 function &df_create_new_record_form($table, $fields=null){
96  import( 'Dataface/QuickForm.php');
98  return $form;
99 }
100 
101 function &df_create_edit_record_form(&$table, $fields=null){
102  import('Dataface/QuickForm.php');
104  return $form;
105 
106 }
107 
108 function &df_create_new_related_record_form(&$record, $relationshipName, $fieldNames=null){
109  import( 'Dataface/ShortRelatedRecordForm.php');
110  $form = new Dataface_ShortRelatedRecordForm($record,$relationshipName,'', $fieldNames);
111  return $form;
112 
113 }
114 
115 
116 function &df_create_existing_related_record_form(&$record, $relationshpName){
117  import( 'Dataface/ExistingRelatedRecordForm.php');
118  $form = new Dataface_ExistingRelatedRecordForm($record, $relationshipName);
119  return $form;
120 }
121 
122 
123 
124 
125 function &df_create_import_form(&$table, $relationshipName=null){
126  import( 'Dataface/ImportForm.php');
127  $form = new Dataface_ExistingRelatedRecordForm($record, $relationshipName);
128  return $form;
129 
130 }
131 
132 function &df_create_search_form($tablename, $query=array(), $fields=null){
133  import( 'Dataface/SearchForm.php');
135  $form = new Dataface_SearchForm($tablename, $app->db(), $query, $fields);
136  return $form;
137 }
138 
139 
140 
141 function &df_get_records($table, $query=null, $start=null, $limit=null, $preview=true){
142  import( 'Dataface/QueryTool.php');
144  if ( $query === null and $start === null and $limit === null ){
146  } else {
147  if ( $query === null or !$query ) $query = array();
148  if ( $start !== null ) $query['-skip'] = $start;
149  if ( $limit !== null ) $query['-limit'] = $limit;
150 
151  $queryTool = new Dataface_QueryTool($table, null, $query);
152  }
153 
154  $queryTool->loadSet('',false,false,$preview);
155  $it = $queryTool->iterator();
156  return $it;
157 }
158 
159 function &df_get_records_array($table, $query=null, $start=null, $limit=null, $preview=true){
160  $records = array();
161  $it = df_get_records($table,$query,$start,$limit,$preview);
162  if ( PEAR::isError($it) )return $it;
163  while ($it->hasNext()){
164  $records[] = $it->next();
165  }
166  return $records;
167 }
168 
169 function &df_get_related_records($query=array()){
170  if ( !isset($query['-relationship']) ) return PEAR::raiseError("No relationship specified");
171 
172  $source = df_get_record($query['-table'],$query);
173  if ( !$source ) return PEAR::raiseError("Source record not found");
174  if ( PEAR::isError($source) ) return $source;
175 
176  $relationship = $source->_table->getRelationship($query['-relationship']);
177 
178  if ( isset( $query['-related:sort']) ){
179  $sortcols = explode(',', trim($query['-related:sort']));
180  $sort_columns = array();
181  foreach ($sortcols as $sortcol){
182  $sortcol = trim($sortcol);
183  if (strlen($sortcol) === 0 ) continue;
184  $sortcol = explode(' ', $sortcol);
185  if ( count($sortcol) > 1 ){
186  $sort_columns[$sortcol[0]] = strtolower($sortcol[1]);
187  } else {
188  $sort_columns[$sortcol[0]] = 'asc';
189  }
190  }
191  unset($sortcols); // this was just a temp array so we get rid of it here
192  } else {
193  $sort_columns = array();
194  }
195  $sort_columns_arr = array();
196  foreach ( $sort_columns as $colkey=>$colorder) {
197  $sort_columns_arr[] = '`'.$colkey.'`'. $colorder;
198  }
199  if ( count($sort_columns_arr) > 0 ){
200  $sort_columns_str = implode(', ',$sort_columns_arr);
201  } else {
202  $sort_columns_str = 0;
203  }
204 
205  if ( isset($query['-related:search']) ){
206  $rwhere = array();
207  foreach ($relationship->fields() as $rfield){
208  //list($garbage,$rfield) = explode('.', $rfield);
209  $rwhere[] = '`'.str_replace('.','`.`',$rfield).'` LIKE \'%'.addslashes($query['-related:search']).'%\'';
210  }
211  $rwhere = implode(' OR ', $rwhere);
212  } else {
213  $rwhere = 0;
214  }
215  $start = isset($query['-related:start']) ? $query['-related:start'] : 0;
216  $limit = isset($query['-related:limit']) ? $query['-related:limit'] : 30;
217 
218  $out =& $source->getRelatedRecordObjects($query['-relationship'], $start, $limit, $rwhere, $sort_columns_str);
219  return $out;
220 }
221 
222 
223 function df_singularize($label){
224  if ( preg_match('/s$/i', $label) ){
225  if ( preg_match('/ies$/i', $label) ){
226  return preg_replace('/ies$/i', 'y', $label);
227  } else if ( preg_match('/([^aeiouy]{2})es$/i', $label)
228  and !preg_match('/[^l]les$/i', $label)
229  and !preg_match('/ees$/i', $label)
230  and !preg_match('/[aeoiuy][qwrtpsdfghjklzxcvbnm]es$/i', $label)
231 
232  ){
233  return preg_replace('/es$/', '', $label);
234  } else {
235  return preg_replace('/s$/', '', $label);
236  }
237  }
238  return $label;
239 }
240 
241 
242 function df_append_query($url, $query){
243  if ( strpos($url,'?') === false ){
244  $url .= '?';
245  }
246  foreach ($query as $k=>$v){
247  $url .= '&'.urlencode($k).'='.urlencode($v);
248  }
249  return $url;
250 }
251 
252 
253 function df_clear_views(){
254 
255 
256 
257 
258  $res = mysql_query("show tables like 'dataface__view_%'", df_db());
259  $views = array();
260  while ( $row = mysql_fetch_row($res) ){
261  $views[] = $row[0];
262  }
263  if ( $views ) {
264  $sql = "drop view `".implode('`,`', $views)."`";
265  //echo $sql;
266  //echo "<br/>";
267  $res = mysql_query("drop view `".implode('`,`', $views)."`", df_db());
268  if ( !$res ) throw new Exception(mysql_error(df_db()));
269  }
270 
271 
272 }
273 
274 function df_clear_cache(){
275  $res = @mysql_query("truncate table __output_cache", df_db());
276  //if ( !$res ) throw new Exception(mysql_error(df_db()));
277  return $res;
278 }
279 
280 
281 function &df_get_table_info($tablename){
282  import( 'Dataface/Table.php');
284  return $table;
285 }
286 
287 function &df_get_record($table, $query, $io=null){
288  import( 'Dataface/Record.php');
289  import( 'Dataface/IO.php');
290 
291  $record = new Dataface_Record($table, array());
292  if ( !isset($io) ){
293  $io = new Dataface_IO($table);
294  }
295 
296  $query['-limit'] = 1;
297  if ( @$query['-cursor'] > 0 ){
298  $query['-skip'] = $query['-cursor'];
299  }
300 
301  $res = $io->read($query, $record);
302  if ( PEAR::isError($res) ) {
303  //print_r($query);
304  //echo $res->toString();
305  $null = null;
306  return $null;
307  }
308  return $record;
309 }
310 
311 function &df_get_record_by_id($id){
312  import('Dataface/IO.php');
313  @list($id,$fieldname) = explode('#', $id);
314  $record = Dataface_IO::getByID($id);
315  return $record;
316 }
350 function df_parse_uri($uri){
351  static $cache = 0;
352  if ( $cache === 0 ) $cache = array();
353 
354  if ( !isset($cache[$uri]) ){
355  $out = array(
356  'table'=>null,
357  'relationship'=>null,
358  'query'=>null,
359  'related_where'=>null,
360  'field'=>null,
361  'action'=>null
362  );
363  if ( strpos($uri, '?') !== false ){
364  list($table,$query) = explode('?', $uri);
365  } else {
366  if ( strpos($uri, '#') !== false ){
367  list($table, $fieldname) = explode('#', $uri);
368  $query = null;
369  } else {
370  $table = $uri;
371  $query = null;
372  $fieldname = null;
373  }
374  }
375  if ( strpos($query,'#') !== false )
376  list($query,$fieldname) = explode('#', $query);
377 
378  //if ( !isset($table) || !isset($query)) return PEAR::raiseError("Dataface_IO::getByID expects an id of a specific form, but received ".$uri, DATAFACE_E_ERROR);
379 
380  if ( strpos($table, '://') !== false ){
381  list($action, $table) = explode('://', $table);
382  $out['action'] = $action;
383  }
384 
385  @list($table, $relationship) = explode('/', $table);
386 
387  // Find the keys for this one
388  $params = explode('&',$query);
389  $params2 = array();
390  foreach ($params as $param){
391  if ( !$param) continue;
392  list($key,$val) = explode('=', $param);
393  $params2[trim(urldecode($key))] = trim(urldecode($val));
394  }
395 
396  $out['table'] = $table;
397 
398  if ( !isset($relationship) ){
399  $out['query'] = $params2;
400 
401  if ( isset($fieldname) ){
402  $out['field'] = $fieldname;
403  }
404 
405 
406  } else {
407  $out['relationship'] = $relationship;
408  $primary_params = array();
409  $related_params = array();
410  foreach ($params2 as $key=>$val){
411  @list($key1,$key2) = explode('::',$key);
412  if ( !isset($key2) ){
413  $primary_params[trim(urldecode($key1))] = trim(urldecode($val));
414  } else {
415  $related_params[trim(urldecode($key2))] = trim(urldecode($val));
416  }
417  }
418 
419  if ( count($related_params) > 0 ){
420  $sql = array();
421  foreach ($related_params as $k=>$v){
422  $sql[] = "`{$k}`='{$v}'";
423  }
424  $sql = implode(' and ', $sql);
425  $out['related_where'] = $sql;
426  }
427 
428  $out['query'] = $primary_params;
429 
430  if ( isset($fieldname) ) {
431  $out['field'] = $fieldname;
432  }
433 
434 
435  }
436  // Let's make sure we don't overload it. If the array is greater
437  // than 250 items, we'll remove the first one in order to add this
438  // next one.
439  if ( count($cache) > 200 ) array_shift($cache);
440  $cache[$uri] = $out;
441  }
442  return $cache[$uri];
443 
444 
445 
446 }
447 
448 function df_get_selected_records($query){
449  if ( isset($query['--selected-ids']) ){
450  $selected = $query['--selected-ids'];
451  } else if ( isset($query['-selected-ids']) ){
452  $selected = $query['-selected-ids'];
453  } else {
454  return array();
455  }
456 
457  $ids = explode("\n", $selected);
458  $records = array();
459  foreach ($ids as $id){
460  $records[] = df_get_record_by_id($id);
461  }
462  return $records;
463 }
464 
465 function df_save_record(&$record, $keys=null, $lang=null, $secure=false){
466  import( 'Dataface/Record.php');
467  import( 'Dataface/IO.php');
468 
469  $io = new Dataface_IO($record->_table->tablename);
470  if ( isset($lang) ) $io->lang = $lang;
471  $res = $io->write($record, $keys, null, $secure);
472  $io->__destruct();
473  unset($io);
474  return $res;
475 
476 }
477 
478 function &df_get_valuelist($tablename, $valuelistname){
480  $vl =& $table->getValuelist($valuelistname);
481  return $vl;
482 }
483 
484 
485 
486 function &df_get_relationship_info($tablename, $relationshipname){
487  $table = df_get_table_info($tablename);
488  $relationship = $table->getRelationship($relationshipname);
489  return $relationship;
490 }
491 
492 
493 function df_register_skin($name, $template_dir){
494  import( 'Dataface/SkinTool.php');
496  $st->register_skin($name, $template_dir);
497 
498 }
499 
500 function df_display($context, $template_name){
501  import( 'Dataface/SkinTool.php');
503 
504  return $st->display($context, $template_name);
505 }
506 
507 function df_config_get($varname){
509  return $app->_conf[$varname];
510 }
511 
512 function df_config_set($varname, $value){
514  $app->_conf[$varname] = $value;
515 }
516 
517 function df_db(){
519  return $app->_db;
520 }
521 
522 function df_query($sql, $lang=null, $as_array=false, $enumerated=false){
523  import('Dataface/DB.php');
524  $db = Dataface_DB::getInstance();
525  return $db->query($sql,null,$lang,$as_array, $enumerated);
526 }
527 
528 function df_insert_id(){
529  import('Dataface/DB.php');
530  $db = Dataface_DB::getInstance();
531  return $db->insert_id();
532 }
533 
534 function df_translate($id, $default=null, $params=array(), $lang=null){
535  return Dataface_LanguageTool::getInstance($lang)->translate($id,$default,$params, $lang);
536 }
537 
538 function df_load_realm($realm, $lang=null){
539  Dataface_LanguageTool::getInstance($lang)->loadRealm($realm);
540 }
541 
542 function df_check_permission($permission, &$object, $params=array() ){
543  return Dataface_PermissionsTool::checkPermission($permission, $object, $params);
544 }
545 
546 function df_permission_names_as_array(&$perms){
548  return $ptool->namesAsArray($perms);
549 }
550 
551 function df_permission_names_as_string(&$perms){
553  return $ptool->namesAsString($perms);
554 }
555 
556 function df_block($params){
558  $query =& $app->getQuery();
559 
560  if ( isset($params['table']) ) $table = Dataface_Table::loadTable($params['table']);
561  else if ( isset($params['record']) ) $table = $params['record']->_table;
562  else $table = Dataface_Table::loadTable($query['-table']);
563 
564  if ( isset($params['name']) ) $name = $params['name'];
565  else throw new Exception('No name specified for block.', E_USER_ERROR);
566 
567  unset($params['name']); unset($params['table']);
568 
569  return $table->displayBlock($name, $params);
570 }
571 
572 
573 function df_translation_warning(&$record, $language=null){
574  import('Dataface/TranslationTool.php');
575  $tt = new Dataface_TranslationTool();
576  $tt->printTranslationStatusAlert($record, $language);
577 }
578 
579 function df_editable($content, $id){
580  $skinTool = Dataface_SkinTool::getInstance();
581  return $skinTool->editable(array('id'=>$id), $content, $skinTool);
582 }
583 
584 function df_offset($date){
585  if ( !$date ){
586  return df_translate('scripts.global.MESSAGE_UNKNOWN','Unknown');
587  }
588  $date = strtotime($date);
589  $offset = (strftime("%j")+strftime("%Y")*365)-
590  (strftime("%j",$date)+strftime("%Y",$date)*365);
591  if ($offset>7){
592  $offset = (strftime("%W")+strftime("%Y")*52)-
593  (strftime("%W",$date)+strftime("%Y",$date)*52);
594  $end=($offset!=0?($offset>1?$offset . " weeks ago":"a week ago"):"Today");
595  } else
596  $end=($offset!=0?($offset>1?"$offset days ago":"Yesterday"):"Today");
597  return strftime("%A, %B %d, %Y",$date)." - ". $end;
598 }
602 function &df_get($uri, $filter=null){
603  $res = Dataface_IO::getByID($uri, $filter);
604  return $res;
605 }
606 
610 function df_set($uri, $value){
611  $res = Dataface_IO::setByID($uri, $value);
612  return $res;
613 }
614 
615 if ( !function_exists('array_merge_recursive_unique') ){
616  // array_merge_recursive which override value with next value.
617  // based on: http://www.php.net/manual/hu/function.array-merge-recursive.php 09-Dec-2006 03:38
618  function array_merge_recursive_unique($array0, $array1){
619  $func = __FUNCTION__;
620  $result = array();
621  $arrays = func_get_args();
622  $keyarrs = array_map('array_keys', $arrays);
623  $keys = array_merge($keyarrs[0], $keyarrs[1]);
624  foreach ($keys as $key){
625  foreach ( $arrays as $array ){
626  if ( array_key_exists($key, $array) ){
627  if ( is_array($array[$key]) ){
628  if ( is_array(@$result[$key]) ) $result[$key] = $func($result[$key], $array[$key]);
629  else $result[$key] = $array[$key];
630  } else {
631  $result[$key] = $array[$key];
632  }
633  }
634  }
635  }
636 
637  return $result;
638  }
639 
640 
641  function array_merge_recursive_unique2($array0, $array1)
642  {
643  $arrays = func_get_args();
644  $remains = $arrays;
645 
646  // We walk through each arrays and put value in the results (without
647  // considering previous value).
648  $result = array();
649 
650  // loop available array
651  foreach($arrays as $array) {
652 
653  // The first remaining array is $array. We are processing it. So
654  // we remove it from remaing arrays.
655  array_shift($remains);
656 
657  // We don't care non array param, like array_merge since PHP 5.0.
658  if(is_array($array)) {
659  // Loop values
660  foreach($array as $key => $value) {
661  if(is_array($value)) {
662  // we gather all remaining arrays that have such key available
663  $args = array();
664  foreach($remains as $remain) {
665  if(array_key_exists($key, $remain)) {
666  array_push($args, $remain[$key]);
667  }
668  }
669 
670  if(count($args) > 2) {
671  // put the recursion
672  $result[$key] = call_user_func_array(__FUNCTION__, $args);
673  } else {
674  foreach($value as $vkey => $vval) {
675  $result[$key][$vkey] = $vval;
676  }
677  }
678  } else {
679  // simply put the value
680  $result[$key] = $value;
681  }
682  }
683  }
684  }
685  return $result;
686  }
687 }
688 
689 function df_is_logged_in(){
690  return ( class_exists('Dataface_AuthenticationTool') and ($auth = Dataface_AuthenticationTool::getInstance()) and $auth->isLoggedIn());
691 }
692 
693 function df_absolute_url($url){
694  if ( !$url ) return $_SERVER['HOST_URI'];
695  else if ( $url{0} == '/' ){
696  return $_SERVER['HOST_URI'].$url;
697  } else if ( preg_match('/http(s)?:\/\//', $url) ){
698  return $url;
699  } else {
700  $host_uri = $_SERVER['HOST_URI'];
701  $site_url = DATAFACE_SITE_URL;
702  if ( $site_url ) {
703  if ($site_url{0} == '/' ) $host_uri = $host_uri.$site_url;
704  else $host_uri = $host_uri.'/'.$site_url;
705  }
706 
707  return $host_uri.'/'.$url;
708  }
709 }
710 
711 
717 function df_utc_offset(){
718  $diff = preg_replace('/^([+-])(\d{1,2})(\d{2,2})$/', '$1$2:$3',date('O'));
719  return $diff;
720 
721 }
722 
723 
724 function df_tz_or_offset(){
725 
726  $tz = @date('e');
727  if ( $tz ) return $tz;
728  else return df_utc_offset();
729 
730 }
731 
732 
733 
734 
746  function df_get_file_system_version(){
747  static $version = -1;
748 
749  if ( $version == -1 ){
750  if ( file_exists('version.txt') ){
751  $varr = file('version.txt');
752 
753  $fs_version='0';
754  if ( $varr ){
755  list($fs_version) = $varr;
756  }
757  } else {
758  $fs_version = '0';
759  }
760 
761  $fs_version = explode(' ', $fs_version);
762  $fs_version = intval($fs_version[count($fs_version)-1]);
763  $version = $fs_version;
764  }
765  if ( !$version ) return df_get_database_version();
766 
767  return $version;
768 
769  }
770 
775  function df_get_database_version($db=null){
776  if (!$db ) $db = df_db();
777  static $version = -1;
778  if ( $version == -1 ){
779  $sql = "select `version` from dataface__version limit 1";
780  $res = @mysql_query($sql, $db);
781  if ( !$res ){
782  $res = mysql_query("create table dataface__version ( `version` int(5) not null default 0)", $db);
783  if ( !$res ) throw new Exception(mysql_error($db), E_USER_ERROR);
784  //$fs_version = df_get_file_system_version();
785  $res = mysql_query("insert into dataface__version values ('0')", $db);
786  if ( !$res ) throw new Exception(mysql_error($db), E_USER_ERROR);
787 
788  $res = mysql_query($sql, $db);
789  if ( !$res ){
790  throw new Exception(mysql_error($db), E_USER_ERROR);
791  }
792 
793  }
794  list($version) = mysql_fetch_row($res);
795  }
796  return $version;
797  }
798 
799 
800 
801 
802  function df_q($sql){
803 
804  if ( is_array($sql) ){
805  foreach ($sql as $q){
806  $res = df_q($q);
807  }
808  return $res;
809  } else {
810  $res = mysql_query($sql, df_db());
811  if ( !$res ){
812  error_log("Error executing SQL: $sql");
813  error_log(mysql_error(df_db()));
814  throw new Exception(mysql_error(df_db()));
815  }
816  return $res;
817  }
818  }
819 
820 
821  function df_IPv4To6($ip) {
822  if ( strpos($ip, ':') !== false ){
823  if ( $ip === '::1' ) return 'fe80::1';
824  return $ip;
825  }
826  if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === true) {
827  if (strpos($ip, '.') > 0) {
828  $ip = substr($ip, strrpos($ip, ':')+1);
829  } else { //native ipv6
830  return $ip;
831  }
832  }
833  $is_v4 = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
834  if (!$is_v4) { return false; }
835  $iparr = array_pad(explode('.', $ip), 4, 0);
836  $Part7 = base_convert(($iparr[0] * 256) + $iparr[1], 10, 16);
837  $Part8 = base_convert(($iparr[2] * 256) + $iparr[3], 10, 16);
838  return '::ffff:'.$Part7.':'.$Part8;
839  }
840 
841 } // end if ( !defined( DATAFACE_PUBLIC_API_LOADED ) ){