23 import(
'Dataface/Table.php');
24 import(
'Dataface/RelatedRecord.php');
25 import(
'Dataface/LinkTool.php');
33 define(
'DATAFACE_RECORD_RELATED_RECORD_BLOCKSIZE', 30);
125 static function _nextId(){
146 var $propertyChangeListeners=array();
181 var $_relatedValues = array();
188 var $_relatedValuesLoaded = array();
193 var $_numRelatedRecords = array();
197 var $_lastRelatedRecordStart = 0;
202 var $_lastRelatedRecordLimit = 30;
207 var $_relationshipRanges;
228 var $_transientValues=array();
244 var $_dirtyFlags = array();
251 var $_relatedDirtyFlags = array();
256 var $_isLoaded = array();
261 var $_metaDataValues=array();
275 var $_relatedMetaValues=array();
282 var $_delegate = null;
300 var $vetoSecurity =
false;
308 var $vetoFields = array();
341 $this->_id = Dataface_Record::_nextId();
344 $this->_delegate =& $this->_table->getDelegate();
345 $this->lang =
$app->_conf[
'lang'];
347 if ( $values !== null ){
348 if ( is_a($values,
'StdClass') ){
349 $values = get_object_vars($values);
351 if ( is_array($values) ){
352 foreach ($values as $k=>$v){
376 unset($this->propertyChangeListeners);
379 unset($this->vetoFields);
380 unset($this->_delegate);
381 unset($this->_metaDataValues);
382 unset($this->_transientValues);
383 unset($this->_oldValues);
385 if ( isset($this->_parentRecord) ){
386 $this->_parentRecord->__destruct();
387 unset($this->_parentRecord);
413 $del =& $this->_table->getDelegate();
415 if ( isset($del) && method_exists($del, $function) ){
416 return $del->$function($this);
418 }
else if ( isset($parent) ){
420 return $parent->callDelegateFunction($function, $fallback);
445 $params[
'record'] =& $this;
446 $actions = $this->_table->getActions($params);
449 if ( isset($parent) ){
450 $actions = array_merge_recursive_unique($parent->getActions($params), $actions);
478 $this->cache=array();
480 $this->_relatedValuesLoaded = array();
482 $this->_relatedValues = array();
483 $this->_relatedMetaValues = array();
517 if ( !is_string($str) )
return $str;
520 while ( preg_match(
'/(?<!\\\)\$([0-9a-zA-Z\._\-]+)/', $blackString, $matches ) ){
521 if ( $this->_table->hasField($matches[1]) ){
522 $replacement = $this->
strval($matches[1]);
526 $replacement = $matches[1];
528 $str = preg_replace(
'/(?<!\\\)\$'.$matches[1].
'/', $replacement, $str);
529 $blackString = preg_replace(
'/(?<!\\\)\$'.$matches[1].
'/',
"", $blackString);
564 if ( isset( $this->_relationshipRanges[$relationshipName] ) ){
565 return $this->_relationshipRanges[$relationshipName];
567 return $this->_table->getRelationshipRange($relationshipName);
584 if ( !isset( $this->_relationshipRanges ) ) $this->_relationshipRanges = array();
585 $this->_relationshipRanges[$relationshipName] = array($lower, $upper);
609 function _relatedRecordLoaded($relname,
$index, $where=0, $sort=0){
612 return ( isset( $this->_relatedValuesLoaded[$relname][$where][$sort][$blockNumber] ) and $this->_relatedValuesLoaded[$relname][$where][$sort][$blockNumber] );
628 function _translateRangeToBlocks($lower, $upper){
632 return array(intval($lowerBlock), intval($upperBlock));
650 function _relatedRecordBlockLoaded($relname, $block, $where=0, $sort=0){
651 return ( isset( $this->_relatedValuesLoaded[$relname][$where][$sort][$block] ) and $this->_relatedValuesLoaded[$relname][$where][$sort][$block] );
672 function _loadRelatedRecordBlock($relname, $block, $where=0, $sort=0){
673 if ( $this->_relatedRecordBlockLoaded($relname, $block, $where, $sort) )
return true;
675 $relationship =& $this->_table->getRelationship($relname);
676 if ( !is_object($relationship) ){
679 'scripts.Dataface.Record._loadRelatedRecordBlock.ERROR_GETTING_RELATIONSHIP',
680 "Error getting relationship '$relname'. The value returned by getRelationship() was '$relationship'.",
681 array(
'relationship'=>$relname,
'retval'=>$relationship)
695 $sql = $this->
parseString($relationship->getSQL($this->loadBlobs, $where, $sort));
698 $sql .=
" LIMIT ".addslashes($start).
",".addslashes($limit);
703 $res = $db->query($sql, $this->_table->db, null,
true);
704 if ( !$res and !is_array($res) ){
706 throw new Exception( mysql_error($this->_table->db).
708 'scripts.Dataface.Record._loadRelatedRecordBlock.ERROR_LOADING_RELATED_RECORDS',
709 "Error loading related records for relationship '$relname' in table '".$this->_table->tablename.
"'. There was a problem performing the sql query '$sql'. The Mysql error returned was '".mysql_error($this->_table->db),
710 array(
'relationship'=>$relname,
'table'=>$this->_table->tablename,
'mysql_error'=>mysql_error($this->_table->db),
'sql'=>$sql)
716 foreach ($res as $row){
717 $record_row = array();
719 foreach ($row as $key=>$value){
721 if ( strpos($key,
'__') === 0 ){
722 $meta_row[$key] = $value;
724 $record_row[$key] = $this->_table->parse($relname.
'.'.$key, $value);
728 $this->_relatedValues[$relname][$where][$sort][
$index++] =& $record_row;
729 $this->_relatedMetaValues[$relname][$where][$sort][
$index-1] =& $meta_row;
735 $this->_relatedValuesLoaded[$relname][$where][$sort][$block] =
true;
775 if ( !isset( $this->_numRelatedRecords[$relname][$where]) ){
776 $relationship =& $this->_table->getRelationship($relname);
779 $sql = $this->
parseString($relationship->getSQL($this->loadBlobs, $where));
783 $sql = stristr($sql,
' FROM ');
784 $sql =
"SELECT COUNT(*) as num".$sql;
789 $res = $db->query($sql, $this->_table->db, null,
true);
790 if ( !$res and !is_array($res) ){
794 'scripts.Dataface.Record.numRelatedRecords.ERROR_CALCULATING_NUM_RELATED_RECORDS',
795 "Error calculating the number of related records there are for the relationship '$relname' in the table '".$this->_table->tablename.
"'. There was a problem performing the sql query '$sql'. The MYSQL error returned was '".mysql_error($this->_table->db).
"'.\n<br>",
796 array(
'relationship'=>$relname,
'table'=>$this->_table->tablename,
'mysql_error'=>mysql_error($this->_table->db),
'sql'=>$sql)
800 $this->_numRelatedRecords[$relname][$where] = $res[0][
'num'];
802 return $this->_numRelatedRecords[$relname][$where];
868 function &
getRelatedRecords( $relname, $multipleRows=
true , $start = null, $limit=null, $where=0, $sort=0){
869 if ( !is_bool($multipleRows) and intval($multipleRows) > 0 ){
876 $start = $multipleRows;
877 $multipleRows =
true;
878 }
else if ( $multipleRows ===
'all'){
880 $where = ($start === null ? 0:$start);
884 $multipleRows =
true;
888 }
else if ( is_string($multipleRows) and intval($multipleRows) === 0 and $multipleRows !==
"0"){
890 if ( is_string($start) and intval($start) === 0 and $start !==
"0" ){
899 $where = $multipleRows;
900 $multipleRows =
'all';
905 if ( $where === null ) $where = 0;
906 if ( $sort === null ) $sort = 0;
908 if ( $start === null){
910 $start = $defaultStart;
912 $this->_lastRelatedRecordStart = $start;
915 if ( $limit === null ){
917 $limit = $defaultEnd-$defaultStart;
919 $this->_lastRelatedRecordLimit = $limit;
923 $range = $this->_translateRangeToBlocks($start,$start+$limit-1);
924 if ( $where === null ) $where = 0;
925 if ( $sort === null ) $sort = 0;
927 $relationship =& $this->_table->getRelationship($relname);
928 $order_column = $relationship->getOrderColumn();
930 $sort = $order_column;
934 for ( $i=$range[0]; $i<=$range[1]; $i++){
935 $res = $this->_loadRelatedRecordBlock($relname, $i, $where, $sort);
942 if ( $multipleRows ===
true ){
946 for ( $i=$start; $i<$start+$limit; $i++){
947 if ( !isset( $this->_relatedValues[$relname][$where][$sort][$i] ) )
continue;
948 $out[$i] =& $this->_relatedValues[$relname][$where][$sort][$i];
952 }
else if (is_array($multipleRows) ){
953 throw new Exception(
"Unsupported feature: using array query for multiple rows in getRelatedRecords", E_USER_ERROR);
955 foreach ( array_keys($this->_relatedValues[$relname][$where][$sort]) as $rowIndex ){
956 $row =& $this->_relatedValues[$relname][$where][$sort][$rowIndex];
958 foreach ( $multipleRows as $key=>$value ){
959 if ( strpos($key,
'.')!==
false ){
961 list($dummy, $key) = explode(
'.', $key);
962 if ( trim($dummy) != trim($relname) ){
967 $fullpath = $relname.
'.'.$key;
968 $nvalue = $this->_table->normalize($fullpath, $value);
969 if ( $nvalue != $this->_table->normalize($fullpath, $rowIndex) ){
974 if ( $match )
return $row;
980 if (@count($this->_relatedValues[$relname][$where][$sort])>0){
981 if ( is_int( $start ) ){
982 return $this->_relatedValues[$relname][$where][$sort][$start];
984 return reset($this->_relatedValues[$relname][$where][$sort]);
1040 $delegate =& $this->_table->getDelegate();
1041 if ( isset($delegate) and method_exists($delegate,
'getChildren')){
1042 $children =& $delegate->getChildren($this);
1044 }
else if ( ( $rel =& $this->_table->getChildrenRelationship() ) !== null ){
1047 while ( $it->hasNext() ){
1048 $child = $it->next();
1049 $out[] = $child->toRecord();
1078 if ( !isset($children) || count($children) == 0 )
return null;
1079 return $children[0];
1119 $delegate =& $this->_table->getDelegate();
1120 if ( isset($delegate) and method_exists($delegate,
'getParent')){
1121 $parent = $delegate->getParent($this);
1123 }
else if ( ( $rel =& $this->_table->getParentRelationship() ) !== null ){
1126 if ( $it->hasNext() ){
1127 $parent = $it->next();
1128 $out = $parent->toRecord();
1134 $contextRecord =
$app->getRecordContext($this->
getId());
1135 if ( $contextRecord ){
1136 $parent = $contextRecord->getParent();
1170 $relationship =& $this->_table->getRelationship($relationshipName);
1172 throw new Exception(
"Relationship $relationship could not be found: ".$relationship->getMessage());
1174 $order_column = $relationship->getOrderColumn();
1176 $sort = $order_column;
1210 while ($it->hasNext() ){
1211 $out[] =& $it->next();
1236 if ( isset($this->cache[__FUNCTION__][$relationshipName][
$index][$where][$sort]) ){
1237 return $this->cache[__FUNCTION__][$relationshipName][
$index][$where][$sort];
1240 if ( $it->hasNext() ){
1241 $rec =& $it->next();
1242 $this->cache[__FUNCTION__][$relationshipName][
$index][$where][$sort] =& $rec;
1274 $r =& $this->_table->getRelationship($relationship);
1275 $order_col = $r->getOrderColumn();
1277 $order_table =& $r->getTable($order_col);
1283 if ( $it->hasNext() ){
1284 $prev_record =& $it->next();
1285 if ( $it->hasNext() ){
1286 $curr_record =& $it->next();
1290 if ( !isset($prev_record) || !isset($curr_record) ){
1291 return PEAR::raiseError(
'Attempt to move record up in "'.$relationship.
'" but the index "'.
$index.
'" did not exist.');
1294 if ( intval($prev_record->val($order_col)) == intval($curr_record->val($order_col)) ){
1302 $prev = $prev_record->toRecord($order_table->tablename);
1303 $curr = $curr_record->toRecord($order_table->tablename);
1304 $temp = $prev->val($order_col);
1305 $res = $prev->setValue($order_col, $curr->val($order_col));
1307 $res = $prev->save();
1309 $res = $curr->setValue($order_col, $temp);
1311 $res = $curr->save();
1351 $r =& $this->_table->getRelationship($relationship);
1352 $order_col = $r->getOrderColumn();
1354 $order_table =& $r->getTable($order_col);
1385 if ( isset($start) ){
1389 $aExists = ($start > 0);
1390 $countA = count($subset);
1392 $countB = count($B);
1396 $dExists = ( $countB-$countA >=2 );
1398 $dExists = ($countB-$countA >= 1);
1403 if ( $aExists ) $AOffset++;
1406 if ( (!$aExists or $B[0 + $AOffset]->
val($order_col) > $B[0]->val($order_col) )
1408 (!$dExists or $B[$countA-1+$AOffset]->
val($order_col) < $B[$countB-1]->val($order_col) )
1410 ( ($B[$countA-1+$AOffset]->
val($order_col) - $B[0+$AOffset]->
val($order_col)) >= ($countA - 1) ) ){
1413 $sortIndex = array();
1414 $i = $B[0+$AOffset]->val($order_col);
1415 foreach ($subset as $record){
1416 $sortIndex[$record->getId()] = $i++;
1421 $i1 = $countA+$AOffset;
1422 for ( $i = $i0; $i<$i1; $i++ ){
1423 $B[$i]->setValue($order_col, $sortIndex[ $B[$i]->
getId() ] );
1424 $res = $B[$i]->save();
1438 while ( $it->hasNext() ){
1439 $rec =& $it->next();
1441 $orderRecord =& $rec->toRecord($order_table->tablename);
1442 $orderRecord->setValue($order_col, $i++);
1443 $res = $orderRecord->save();
1446 unset($orderRecord);
1503 if ( strpos($key,
'.')!==
false ){
1504 throw new Exception(
"Unsupported operation: setting value on related record.", E_USER_ERROR);
1510 if ( strpos($key,
"__") === 0 && $this->useMetaData ){
1520 if ( !array_key_exists($key, $this->_table->fields() ) ){
1522 if ( array_key_exists($key, $this->_table->transientFields()) ){
1524 $this->_transientValues[$key] = $value;
1529 else if ( !array_key_exists($key, $this->_table->graftedFields(
false)) ){
1532 if ( isset($parent) and $parent->_table->hasField($key) ){
1534 $parent->setValue($key, $value,
$index);
1547 $this->_values[$key] = $this->_table->parse($key, $value);
1549 $this->_isLoaded[$key] =
true;
1561 if ( $this->vetoSecurity ){
1562 $this->vetoFields[$key] =
true;
1569 if ( array_key_exists($key, $this->_table->keys() ) ){
1571 if ( isset($parent) ){
1572 $keys = array_keys($this->_table->keys());
1573 $pkeys = array_keys($parent->_table->keys());
1574 $key_index = array_search($key,
$keys);
1576 $parent->setValue($pkeys[$key_index], $this->
getValue($key,
$index));
1605 $fields = $this->_table->fields(
false,
true);
1606 foreach ($values as $key=>$value){
1607 if ( isset(
$fields[$key] ) ){
1609 }
else if ( strpos($key,
'__')===0){
1617 $versionField = $this->_table->getVersionField();
1618 if ( !isset($versionField) ){
1621 return intval($this->
val($versionField));
1809 static $callcount=0;
1811 if ( $debug ) echo
"Num calls to getValue(): $callcount";
1812 if ( isset($this->cache[__FUNCTION__][
$fieldname][
$index][$where][$sort]) ){
1819 throw new Exception(
1821 'scripts.Dataface.Record.getValue.ERROR_PARAMETER_2',
1822 "In Dataface_Record.getValue() expected 2nd parameter to be integer but received array."
1825 if ( is_array($where) ){
1826 throw new Exception(
1828 'scripts.Dataface.Record.getValue.ERROR_PARAMETER_3',
1829 "In Dataface_Record.getValue() expected 3rd parameter to be a string, but received array."
1832 if ( is_array($sort) ){
1833 throw new Exception(
1835 'scripts.Dataface.Record.getValue.ERROR_PARAMETER_4',
1836 "In Dataface_Record.getValue() expected 4th parameter to be a string but received array."
1842 $delegate =& $this->_delegate;
1844 if ( !isset( $this->_values[
$fieldname] ) ) {
1846 if ( $delegate !== null and method_exists($delegate,
"field__$fieldname")){
1847 $methodname =
"field__$fieldname";
1851 }
else if ( array_key_exists($fieldname, $this->_table->transientFields()) ){
1852 $transientFields =& $this->_table->transientFields();
1853 if ( array_key_exists( $fieldname, $this->_transientValues) ){
1855 }
else if ( isset($transientFields[$fieldname][
'relationship']) and $transientFields[$fieldname][
'widget'][
'type'] ==
'grid'){
1858 $currRelationship =& $this->_table->getRelationship($transientFields[$fieldname][
'relationship']);
1859 $relKeys =& $currRelationship->keys();
1861 foreach ($rrecords as $rrecord){
1862 $row = $rrecord->strvals();
1864 foreach ( array_keys($row) as $row_field ){
1865 $ptable =& $rrecord->_relationship->getTable($row_field);
1866 $precord =& $rrecord->toRecord($ptable->tablename);
1868 $row[
'__permissions__'][$row_field] = $precord->getPermissions(array(
'field'=>$row_field));
1869 if ( isset($relKeys[$row_field]) ) unset($row[
'__permissions__'][$row_field][
'edit']);
1873 $row[
'__id__'] = $rrecord->getId();
1880 unset($currRelationship);
1883 }
else if ( isset($transientFields[$fieldname][
'relationship']) and $transientFields[$fieldname][
'widget'][
'type'] ==
'checkbox'){
1886 $currRelationship =& $this->_table->getRelationship($transientFields[$fieldname][
'relationship']);
1887 foreach ($rrecords as $rrecord){
1888 $row = $rrecord->strvals();
1889 $domRec = $rrecord->toRecord();
1892 foreach (array_keys($domRec->_table->keys()) as $relKey){
1893 $rowStr[] = urlencode($relKey).
'='.urlencode($row[$relKey]);
1895 $out[] = implode(
'&',$rowStr);
1897 unset($rowStr, $domRec);
1902 unset($currRelationship);
1907 if ( isset($delegate) and method_exists($delegate, $fieldname.
'__init') ){
1908 $methodname = $fieldname.
'__init';
1909 $out = $delegate->$methodname($this);
1915 if ( !isset(
$out) ){
1916 $methodname =
'initTransientField';
1918 $appdel =
$app->getDelegate();
1919 if ( isset($appdel) and method_exists($appdel, $methodname) ){
1920 $out = $appdel->$methodname($this, $transientFields[$fieldname]);
1929 if ( !isset(
$out) ){
1930 $event =
new StdClass;
1931 $event->record = $this;
1932 $event->field = $transientFields[
$fieldname];
1937 $app->fireEvent(
'initTransientField', $event);
1940 $out = @$event->out;
1951 }
else if ( ( $parent =& $this->
getParentRecord() ) and $parent->_table->hasField($fieldname) ){
1953 return $parent->getValue($fieldname,
$index,$where,$sort,$debug);
2070 if ( !isset( $this->_values ) ) $this->_values = array();
2192 $delegate =&
$table->getDelegate();
2194 if ( $delegate !== null and method_exists( $delegate, $rel_fieldname.
'__toString') ){
2195 $methodname = $rel_fieldname.
'__toString';
2196 $value = $delegate->$methodname($value);
2200 if ( !is_scalar($value) ){
2201 $methodname = $this->_table->getType(
$fieldname).
"_to_string";
2202 if ( method_exists( $this->_table, $methodname) ){
2204 $value = $this->_table->$methodname($value);
2206 $value = $this->array2string($value);
2215 $evt =
new stdClass;
2217 $evt->field =&
$table->getField($rel_fieldname);
2218 $evt->value = $value;
2219 $evt->type =
$table->getType($rel_fieldname);
2220 $table->app->fireEvent(
'after_getValueAsString', $evt);
2221 $value = $evt->value;
2229 function array2string($value){
2230 if ( is_string($value) )
return $value;
2231 if ( is_array($value) ){
2232 if ( count($value) > 0 and is_array($value[0]) ){
2237 return implode($delim, array_map(array(&$this,
'array2string'), $value));
2273 foreach (
$keys as $key){
2318 $s = $this->_table->getSerializer();
2494 if ( isset($this->cache[__FUNCTION__][
$fieldname][
$index][$where][$sort]) ){
2500 $del =& $this->_table->getDelegate();
2501 if ( $del and method_exists($del,
'no_access_text') ){
2502 return $del->no_access_text($this, array(
'field'=>
$fieldname));
2510 if ( !$rrecord )
return null;
2521 $delegate =& $this->_table->getDelegate();
2522 if ( $delegate !== null and method_exists( $delegate,
$fieldname.
"__display") ){
2524 $out = $delegate->$methodname($this);
2538 foreach (
$keys as $key){
2539 $qstr .=
"&$key".
"=".$this->
strval($key,
$index,$where,$sort);
2541 $out = DATAFACE_SITE_HREF.
"?-action=getBlob&-table=".
$field[
'tablename'].
"&-field=$fieldname&-index=$index$qstr";
2546 else if ( $this->_table->isContainer(
$fieldname) ){
2551 $strvl=rawurlencode($strvl);
2554 if ( strlen(
$out) > 1 and
$out{0} ==
'/' and
$out{1} ==
'/' ){
2567 $field->addUserInfo(
"Failed to get field '$fieldname' while trying to display its value in Record::display()");
2572 $vocab =
$field[
'vocabulary'];
2574 $valuelist =&
$table->getValuelist($vocab);
2579 if (
$field[
'repeat'] and is_array($value) ){
2581 foreach ($value as $value_item){
2582 if ( isset( $valuelist[$value_item] ) ){
2583 $out .= $valuelist[$value_item].
', ';
2585 $out .= $value_item.
', ';
2596 if ( isset($valuelist[$value]) ){
2597 $out = $valuelist[$value];
2609 if ( isset($parent) and $parent->_table->hasField(
$fieldname) ){
2621 $evt =
new stdClass;
2622 $evt->record = $this;
2625 $table->app->fireEvent(
'Record::display', $evt);
2675 $recid = $this->
getId();
2677 $domid = $uri.
'-'.rand();
2681 $delegate =& $this->_table->getDelegate();
2682 if ( isset($delegate) && method_exists($delegate,
$fieldname.
'__htmlValue') ){
2684 $res = $delegate->$methodname($this);
2687 $res =
'<span id="'.$domid.
'" df:id="'.$uri.
'" class="df__editable">'.$res.
'</span>';
2692 if ( isset($parent) and $parent->_table->hasField(
$fieldname) ){
2697 if ( !@
$field[
'passthru'] and $this->escapeOutput) $val = nl2br(htmlspecialchars($val));
2699 $del =& $this->_table->getDelegate();
2700 if ( $del and method_exists($del,
'no_access_link') ){
2701 $link = $del->no_access_link($this, array(
'field'=>
$fieldname));
2702 return '<a href="'.htmlspecialchars($link).
'">'.$val.
'</a>';
2713 $val =
'<img src="'.$val.
'"';
2714 if ( !isset($params[
'width']) and isset(
$field[
'width']) ){
2715 $params[
'width'] =
$field[
'width'];
2717 foreach ($params as $pkey=>$pval){
2718 $val .=
' '.$pkey.
'="'.$pval.
'"';
2722 $file_icon = df_translate(
2724 df_absolute_url(DATAFACE_URL).
'/images/document_icon.gif'
2726 $val =
'<img src="'.$file_icon.
'"/><a href="'.$val.
'" target="_blank"';
2727 foreach ($params as $pkey=>$pval){
2728 $val .=
' '.$pkey.
'="'.$pval.
'"';
2730 $val .=
'>View Field Content In New Window ('.$this->getMimetype(
$fieldname,
$index,$where,$sort).
')</a>';
2737 $val =
'<span id="'.$domid.
'" df:id="'.$uri.
'" class="df__editable">'.$val.
'</span>';
2768 if (
$field[
'Type'] ==
'container' ){
2771 $out = substr($strval, 0, $maxlength);
2772 if ( strlen($strval)>$maxlength) {
2802 if ( is_array($params) ) $params = http_build_query($params);
2803 if ( !$params ) $params =
'max_width=75&max_height=100';
2805 if ( strpos(
$out,
'?') ===
false )
$out .=
'?';
2865 return (isset( $this->_values) and array_key_exists(
$fieldname, $this->_values) );
2901 $absValues = array();
2902 foreach ( $values as $key=>$value){
2903 $absValues[$this->_table->tablename.
".".$key] = $value;
2935 if ( strlen($filename)===0 ){
2939 return $field[
'savepath'].
'/'.$filename;
2961 if ( !isset( $this->_metaDataValues ) ) $this->_metaDataValues = array();
2962 $this->_metaDataValues[$key] = $value;
2964 if ( isset($parent) ){
2965 $parent->setMetaDataValue($key, $value);
2981 $this->_values = array();
2982 $this->_relatedValues = array();
2983 $this->_valCache = array();
2988 if ( isset($parent) ){
2989 $parent->clearValues();
3003 unset($this->_values[
$field]);
3007 if ( isset($parent) ){
3008 $parent->clearValue();
3054 $this->propertyChangeListeners[$key][] = &$listener;
3072 if ( !isset($key) ) $key =
'*';
3073 if ( !isset($callback) ) unset($this->propertyChangeListeners[$key]);
3074 else if ( isset($this->propertyChangeListeners[$key]) ){
3075 if ( (
$index = array_search($listener,$this->propertyChangeListeners[$key])) !==
false){
3076 unset($this->propertyChangeListeners[$key][
$index]);
3098 if ( isset($key) )
$keys[] = $key;
3099 foreach (
$keys as $key){
3100 if ( !isset($this->propertyChangeListeners[$key] ) )
continue;
3101 foreach ( array_keys($this->propertyChangeListeners[$key]) as $lkey){
3102 $this->propertyChangeListeners[$key][$lkey]->propertyChanged($this,$origKey, $oldValue, $newValue);
3129 if ( is_a($source,
'Dataface_Record') and is_a($parentRecord,
'Dataface_Record') and $source->_id === $parentRecord->_id ){
3130 $pkeys = $source->_table->keys();
3131 $pkey_names = array_keys($pkeys);
3132 $okeys = $this->_table->keys();
3133 $okey_names = array_keys($okeys);
3135 if ( !array_key_exists($key, $pkeys) )
return false;
3138 $key_index = array_search($key, $pkey_names);
3139 if ( $key_index ===
false )
throw new Exception(
"An error occurred trying to find the index of the parent's key. This is a code error that should be fixded by the developer.", E_USER_ERROR);
3142 if ( !isset($okey_names[$key_index]) )
3143 throw new Exception(
"Attempt to keep the current record in sync with its parent but they seem to have a different number of primary keys. To use Dataface inheritance, tables must have a corresponding primary key.", E_USER_ERROR);
3146 $this->
setValue( $okey_names[$key_index], $newValue);
3192 foreach ( $query as $key=>$val ){
3193 $query[$key] =
'='.$val;
3198 if ( $nullIfNotFound )
return null;
3201 foreach ( $query as $key=>$value){
3202 $record->setValue($key, substr($value,1));
3238 $pkeys1 = array_keys($this->_table->keys());
3239 $pkeys2 = array_keys(
$table->keys());
3241 if ( count($pkeys1) != count($pkeys2) ){
3242 return PEAR::raiseError(
"Attempt to get join record [".$this->_table->tablename.
"] -> [".
$table->tablename.
"] but they have a different number of columns as primary key.");
3245 for ($i =0; $i<count($pkeys1); $i++ ){
3246 $query[$pkeys2[$i]] = $this->
strval($pkeys1[$i]);
3262 return $this->_table->tabs($this);
3296 return $this->_table->getRoles($this, $params);
3307 return $this->_table->getRolePermissions($this, $params);
3397 $params[
'record'] =& $this;
3398 return $this->_table->getPermissions($params);
3412 return ( isset($perms[$perm]) and $perms[$perm] );
3454 if ( !is_array($params) ){
3455 $params = array(
'message'=> &$params);
3457 $res = $this->_table->validate(
$fieldname, $value, $params);
3461 if (
$field[
'widget'][
'type'] ==
'file' and @
$field[
'validators'][
'required'] and is_array($value) and $this->
getLength(
$fieldname) == 0 and !is_uploaded_file(@$value[
'tmp_name'])){
3465 $params[
'message'] =
"$fieldname is a required field.";
3466 $params[
'message_i18n_id'] =
"Field is a required field";
3467 $params[
'message_i18n_params'] = array(
'field'=>
$fieldname);
3471 $delegate =& $this->_table->getDelegate();
3472 if ( $delegate !== null and method_exists($delegate,
$fieldname.
"__validate") ){
3479 $res = $delegate->$methodname($this,$value,$params);
3488 if ( isset($parent) and $parent->_table->hasField(
$fieldname) ){
3489 $res = $parent->validate(
$fieldname, $value, $params);
3511 if ( !isset($this->_parentRecord) ){
3512 $parent =& $this->_table->getParent();
3513 if ( isset($parent) ){
3514 $this->_parentRecord =
new Dataface_Record($parent->tablename, array());
3515 foreach ( array_keys($parent->keys()) as $key ){
3516 $this->_parentRecord->addPropertyChangeListener( $key, $this);
3520 return $this->_parentRecord;
3543 if ( isset($this->_values) ){
3548 if ( isset($parent) ){
3549 $parent->setSnapshot();
3565 return (is_array($this->_oldValues) and count($this->_oldValues) > 0);
3577 $this->_oldValues = null;
3579 if ( isset($parent) ){
3580 $parent->clearSnapshot();
3598 if ( isset( $this->_oldValues[$field] ) ){
3605 return $this->_oldValues;
3618 return $this->
getSnapshot(array_keys($this->_table->keys()));
3641 return (isset( $this->_relatedDirtyFlags[
$path[0]]) and
3642 isset( $this->_relatedDirtyFlags[$path[0]][$path[1]]) and
3643 $this->_relatedDirtyFlags[$path[0]][$path[1]] ===
true );
3646 if ( $checkParent ){
3648 if ( isset($parent) and $parent->_table->hasField(
$fieldname) ){
3668 if ( isset($parent) ){
3669 $res = $parent->recordChanged();
3670 if ( $res )
return true;
3674 $fields =& $this->_table->fields();
3691 $keys = array_keys($this->_dirtyFlags);
3692 foreach (
$keys as $i) {
3693 $this->_dirtyFlags[$i] =
false;
3694 $this->vetoFields[$i] =
false;
3696 foreach (array_keys($this->_relatedDirtyFlags) as $rel_name){
3697 foreach ( array_keys($this->_relatedDirtyFlags[$rel_name]) as $field_name){
3698 $this->_relatedDirtyFlags[$rel_name][$field_name] =
false;
3706 if ( isset($parent) ){
3707 $parent->clearFlags();
3725 if ( strpos($name,
'.') !==
false ){
3727 $path = explode(
'.', $name);
3729 if ( !isset($this->_relatedDirtyFlags[
$path[0]]) ){
3732 if ( !isset($this->_relatedDirtyFlags[$path[0]][$path[1]]) ){
3735 $this->_relatedDirtyFlags[$path[0]][$path[1]] =
false;
3738 $this->_dirtyFlags[$name] =
false;
3739 $this->vetoFields[$name] =
false;
3741 if ( isset($parent) and $parent->_table->hasField($name) ){
3742 $parent->clearFlag($name);
3767 if ( !isset($this->_relatedDirtyFlags[
$path[0]]) ){
3768 $this->_relatedDirtyFlags[$path[0]] = array();
3770 $this->_relatedDirtyFlags[$path[0]][$path[1]] =
true;
3775 if ( isset($parent) and $parent->_table->hasField(
$fieldname)){
3791 if ( isset($parent) and $parent->_table->hasField(
$fieldname) ){
3794 return ( isset( $this->_isLoaded[
$fieldname] ) and $this->_isLoaded[$fieldname]);
3817 $delegate =&
$table->getDelegate();
3823 if ( method_exists($delegate,
$fieldname.
"__link") ){
3825 $link = $delegate->$methodname($this);
3830 }
else if ( isset(
$field[
'link']) ){
3841 if ( is_array($link) ){
3842 foreach ( array_keys($link) as $key){
3849 }
else if ( $link ){
3870 function _getSubfield(&$fieldval,
$path){
3871 if ( !is_array($fieldval) ){
3872 return PEAR::raiseError(
"_getSubfield() expects its first parameter to be an array.");
3875 $temp1 =& $fieldval[array_shift(
$path)];
3877 while (
sizeof(
$path) > 0 ){
3879 $temp1 =& $temp2[array_shift(
$path)];
3971 if ( !isset($this->_title) ){
3972 $delegate =& $this->_table->getDelegate();
3974 if ( $delegate !== null and method_exists($delegate,
'getTitle') ){
3976 $title = $delegate->getTitle($this);
3980 if ( isset($parent) ){
3981 $title = $parent->getTitle(
true);
3986 if ( isset($title) ) $this->_title = $title;
3990 if ( !isset($title) ){
3991 $fields =& $this->_table->fields();
3992 $found_title =
false;
3995 foreach (array_keys(
$fields) as $field_name){
3996 if ( isset(
$fields[$field_name][
'title']) ){
3997 $title = $this->
display($field_name);
3998 $found_title =
true;
4000 else if ( !isset($title) and $this->_table->isChar($field_name) ){
4001 $title = $this->
display($field_name );
4003 if ( $found_title)
break;
4006 if ( !isset( $title) ){
4007 $title =
"Untitled ".$this->_table->getLabel().
" Record";
4011 $this->_title = $title;
4014 return $this->_title;
4047 }
else if ( $descriptionField = $this->_table->getDescriptionField() ){
4048 return $this->
htmlValue($descriptionField);
4080 }
else if ( $createdField = $this->_table->getCreatedField() ){
4081 if ( strcasecmp($this->_table->getType($createdField),
'timestamp') === 0 ){
4082 $date = $this->
val($createdField);
4083 return strtotime($date[
'year'].
'-'.$date[
'month'].
'-'.$date[
'day'].
' '.$date[
'hours'].
':'.$date[
'minutes'].
':'.$date[
'seconds']);
4086 return strtotime($this->
display($createdField));
4116 }
else if ( $creatorField = $this->_table->getCreatorField() ){
4117 return $this->
display($creatorField);
4148 }
else if ( $lastModifiedField = $this->_table->getLastUpdatedField() ){
4149 if ( strcasecmp($this->_table->getType($lastModifiedField),
'timestamp') === 0 ){
4150 $date = $this->
val($lastModifiedField);
4151 return strtotime($date[
'year'].
'-'.$date[
'month'].
'-'.$date[
'day'].
' '.$date[
'hours'].
':'.$date[
'minutes'].
':'.$date[
'seconds']);
4154 $strtime = $this->
strval($lastModifiedField);
4156 return strtotime($strtime);
4160 if ( !isset($this->pouch[
'__mtime']) ){
4161 $sql =
"select mtime from dataface__record_mtimes where recordhash='".addslashes(md5($this->
getId())).
"'";
4165 }
catch ( Exception $ex){
4169 list($mtime) = mysql_fetch_row($res);
4170 @mysql_free_result($res);
4171 $this->pouch[
'__mtime'] = intval($mtime);
4172 }
catch (Exception $ex){
4173 error_log(
"Failed SQL query $sql");
4174 $this->pouch[
'__mtime'] = 0;
4177 return $this->pouch[
'__mtime'];
4208 }
else if ( $bodyField = $this->_table->getBodyField() ){
4275 return $this->
getURL($params);
4317 $delegate =& $this->_table->getDelegate();
4318 if ( $delegate !== null and method_exists($delegate,
'getBreadCrumbs') ){
4319 return $delegate->getBreadCrumbs($this);
4323 if ( ( $parent = $this->
getParent() ) !== null ){
4324 $bc = $parent->getBreadCrumbs();
4325 $bc[$this->
getTitle()] = $this->
getURL( array(
'-action'=>
'browse'));
4408 if ( is_string($params) ){
4409 $pairs = explode(
'&',$params);
4411 foreach ( $pairs as $pair ){
4412 list($key,$value) = array_map(
'urldecode',explode(
'=', $pair));
4413 $params[$key] = $value;
4417 $del =& $this->_table->getDelegate();
4418 if ( $del and method_exists($del,
'no_access_link')){
4419 return $del->no_access_link($this, $params);
4423 $params[
'-table'] = $this->_table->tablename;
4424 if ( !isset($params[
'-action']) ) $params[
'-action'] =
'browse';
4425 foreach (array_keys($this->_table->keys()) as $key){
4426 $params[$key] =
'='.$this->strval($key);
4429 $delegate =& $this->_table->getDelegate();
4430 if ( isset($delegate) and method_exists($delegate,
'getURL') ){
4431 $res = $delegate->getURL($this, $params);
4432 if ( $res and is_string($res) )
return $res;
4435 import(
'Dataface/LinkTool.php');
4448 $keys = array_keys($this->_table->keys());
4450 foreach (
$keys as $key){
4451 $params[] = urlencode($key).
'='.urlencode($this->
strval($key));
4453 return $this->_table->tablename.
'?'.implode(
'&',$params);
4480 if ( isset(
$field[
'mimetype']) and strlen(
$field[
'mimetype']) > 0 ){
4484 if ( $this->_table->isContainer(
$fieldname) ){
4486 if ( strlen($filename) > 0 ){
4492 if(extension_loaded(
'fileinfo')) {
4493 $res = finfo_open(FILEINFO_MIME);
4495 }
else if (function_exists(
'mime_content_type')) {
4546 list($relname, $localfieldname) = explode(
'.',
$fieldname);
4549 $relatedRecord->setValues($this->_relatedMetaValues[$relname][0][0][
$index]);
4550 return $relatedRecord->getLength($localfieldname);
4558 $key =
'__'.$fieldname.
'_length';
4559 if ( isset($this->_metaDataValues[$key] ) ){
4560 return $this->_metaDataValues[$key];
4597 return df_save_record($this, $this->
strvals(array_keys($this->_table->keys())),
$lang, $secure);
4607 function delete($secure=
false){
4608 import(
'Dataface/IO.php');
4610 return $io->delete($this, $secure);
4622 foreach ( $strvals as $key=>$val){
4635 foreach ($override as $k=>$v){
4639 return json_encode(
$out);
4664 $this->_records =& $records;
4665 $this->_keys = array_keys($records);
4681 return reset($this->_keys);
4686 return (
current($this->_keys) !==
false);
4703 $this->_record =& $record;
4704 $this->_relationshipName = $relationshipName;
4705 $this->_where = $where;
4706 $this->_sort = $sort;
4707 if ( $start !==
'all' ){
4709 $this->_records =& $record->getRelatedRecords($relationshipName,
true, $start, $limit, $where, $sort);
4711 $this->_records =& $record->getRelatedRecords($relationshipName,
'all',$where, $sort);
4713 if ( is_array($this->_records) ){
4714 $this->_keys = array_keys($this->_records);
4716 $this->_keys = array();
4728 $rec->setValues($this->_record->_relatedMetaValues[$this->_relationshipName][$this->_where][$this->_sort][
current($this->_keys)]);
4733 return reset($this->_keys);
4737 return (
current($this->_keys) !==
false);
4750 return $this->r->val($name);
4754 $this->r->setValue($name, $value);
4758 $this->r->setValue($name, null);