107 var $_metaDataValues;
117 var $_absoluteColumnNames;
122 var $_lockedFields=array();
131 var $_dirtyFlags=array();
148 if ( !is_a($record,
'Dataface_Record') ){
149 throw new Exception(
"Error in Dataface_RelatedRecord constructor. Expected first argument to be of type 'Dataface_Record' but received '".get_class($record).
"'.", E_USER_ERROR);
151 $this->_record =& $record;
152 $this->_relationshipName = $relationshipName;
153 $this->_relationship =& $record->_table->getRelationship($relationshipName);
154 if ( is_array($values) ){
165 function _initValues(){
166 if ( !isset( $this->_values ) ){
167 $fkeys = $this->_relationship->getForeignKeyValues();
168 $this->_values = array();
169 $this->_absoluteColumnNames = array();
171 $cols = $this->_relationship->fields(
true);
172 foreach ($cols as $col){
174 $this->_values[
$field] = null;
175 if ( isset($this->_absoluteColumnNames[
$field]) and
177 $this->_absoluteColumnNames[
$field] = $this->_relationship->getDomainTable().
'.'.
$field;
179 $this->_absoluteColumnNames[
$field] = $col;
187 if ( isset( $fkeys[
$table][$field]) and is_scalar($fkeys[
$table][$field]) and strpos($fkeys[
$table][$field],
'$') ===0 ){
189 $this->_values[
$field] = $this->_record->parseString($fkeys[
$table][$field]);
211 $this->cache = array();
225 if ( isset($this->cache[__FUNCTION__][
$tablename]) ){
226 return $this->cache[__FUNCTION__][
$tablename];
228 if ( !isset($tablename) ){
229 $tablename = $this->_relationship->getDomainTable();
241 $fieldnames = $this->_relationship->fields(
true);
243 foreach ( $fieldnames as $key ){
244 list($currTablename, $columnName) = explode(
'.', $key);
245 if ( ($currTablename == $tablename or
$table->hasField($columnName)) and array_key_exists($key, $absVals)){
247 $values[$columnName] = $absVals[$key];
249 }
else if ( isset($this->_relationship->_schema[
'aliases'][$columnName])
251 $values[$this->_relationship->_schema[
'aliases'][$columnName]] = $absVals[$key];
255 foreach ( $this->_values as $key=>$val ){
256 if ( !isset($values[$key]) and
$table->hasField($key) ) $values[$key] = $this->_values[$key];
261 foreach (array_keys($values) as $key){
263 if ( $this->
isDirty($key) ) $record->setFlag($key);
266 $this->cache[__FUNCTION__][
$tablename] =& $record;
282 $tables =& $this->_relationship->getDestinationTables();
284 foreach ( array_keys($tables) as
$index ){
339 return eval(
'return ('.$condition.
');');
354 $params[
'record'] =& $this;
355 return $this->_record->_table->tablename->getActions($params);
380 $this->_dirtyFlags = array();
410 return ( isset($this->_dirtyFlags[
$fieldname]) );
435 if ( !isset( $this->_metaDataValues ) ) $this->_metaDataValues = array();
436 $this->_metaDataValues[$key] = $value;
456 $key =
'__'.$fieldname.
'_length';
457 if ( isset( $this->_metaDataValues[$key] ) ){
458 return $this->_metaDataValues[$key];
473 $this->_initValues();
481 if ( isset( $this->_lockedFields[
$fieldname]) )
return;
482 $val = $this->_record->_table->parse($this->_relationshipName.
".".$fieldname, $value);
483 if ( $val != @$this->_values[$fieldname] ){
493 return PEAR::raiseError(
"Cannot set duplicate value in relationship. The field $fieldname is part of the domain table and not part of $table in this relationship.");
495 return $this->
setValue($field, $value);
509 if ( !is_array($values) ){
510 throw new Exception(
"setValues() expects 1st parameter to be an array but received a '".get_class($values).
"' ",E_USER_WARNING);
512 foreach ( $values as $key=>$value){
532 $this->_initValues();
535 if ( !array_key_exists(
$fieldname, $this->_values ) ){
537 $tables = $this->_relationship->getDestinationTables();
541 $tables = array($dt);
544 throw new Exception(
"Domain table doesn't have field $fieldname");
546 foreach ( array_keys($tables) as $tkey){
552 throw new Exception(
"Attempt to get value for fieldname '$fieldname' that does not exist in related record of relationship '".$this->_relationshipName.
"'. Acceptable values include {".implode(
', ', array_keys($this->_values)).
"}.\n<br>", E_USER_ERROR);
577 $table =& $parent->_table->getTableTableForField($this->_relationshipName.
'.'.
$fieldname);
579 throw new Exception(
$table->toString(), E_USER_ERROR);
581 $delegate =&
$table->getDelegate();
583 if ( $delegate !== null and method_exists( $delegate, $rel_fieldname.
'__toString') ){
584 $value = call_user_func( array(&$delegate, $rel_fieldname.
'__toString'), $value);
588 if ( is_array($value) ){
592 $value = implode(
', ', $value);
599 $evt->field =&
$table->getField($rel_fieldname);
600 $evt->value = $value;
601 $evt->type =
$table->getType($rel_fieldname);
602 $table->app->fireEvent(
'after_getValueAsString', $evt);
603 $value = $evt->value;
619 $table =& $parent->_table->getTableTableForField($this->_relationshipName.
'.'.
$fieldname);
621 throw new Exception(
$table->toString(), E_USER_ERROR);
627 $field = $record->table()->getField(
$fieldname);
628 if ( !@$field[
'passthru'] and $record->escapeOutput) $val = nl2br(htmlspecialchars($val));
630 $del =& $record->table()->getDelegate();
631 if ( $del and method_exists($del,
'no_access_link') ){
632 $link = $del->no_access_link($record, array(
'field'=>
$fieldname));
633 return '<a href="'.htmlspecialchars($link).
'">'.$val.
'</a>';
639 $oldSecure = $record->secureDisplay;
640 $record->secureDisplay =
false;
642 $record->secureDisplay = $oldSecure;
660 foreach (
$keys as $key){
704 $this->_initValues();
705 return $this->_values;
744 foreach ( $this->
getValues() as $key=>$value){
745 if ( !isset($this->_absoluteColumnNames[$key]) ){
752 $tablename = $this->_relationship->getTable($key)->tablename;
753 $this->_absoluteColumnNames[$key] =
$tablename.
'.'.$key;
755 $absVals[ $this->_absoluteColumnNames[$key] ] = $value;
773 if ( !isset($sql) ) $sql_index = 0;
774 else $sql_index = $sql;
775 if ( isset($this->cache[__FUNCTION__][$sql_index]) ){
776 return $this->cache[__FUNCTION__][$sql_index];
778 $fkeys = $this->_relationship->getForeignKeyValues();
781 $out = $this->_relationship->getForeignKeyValues($absVals, $sql, $this->
getParent());
782 $this->cache[__FUNCTION__][$sql_index] =
$out;
798 $fkCols = $tmp->getForeignKeyValues($sql);
801 throw new Exception($fkCols->getMessage(), $fkCols->getCode());
805 $unconstrainedFields = array();
806 $cols = $this->_relationship->fields();
808 foreach ($cols as $col){
809 $field = $this->_relationship->getField($col);
819 if ( $this->_relationship->isNullForeignKey($fkCols[$tablename][
$fieldname]) ){
821 if ( $furthestField != $absFieldname ){
831 if ( @$field[
'grafted'] && !@$field[
'transient'] )
continue;
832 $unconstrainedFields[] = $col;
836 return $unconstrainedFields;
865 foreach ($cols as $col){
866 $field = $this->_relationship->getField($col);
867 $tables[$field[
'tablename']] = 1;
869 return array_keys($tables);
900 if ( isset($this->cache[__FUNCTION__][
$fieldname]) ){
901 return $this->cache[__FUNCTION__][
$fieldname];
904 $table =& $parent->_table->getTableTableForField($this->_relationshipName.
'.'.$fieldname);
906 throw new Exception(
"Error loading table while displaying $fieldname because ".
$table->getMessage(), E_USER_ERROR);
911 if ( !
$table->isBlob($fieldname) ){
913 if ( $this->secureDisplay and $this->
checkPermission(
'view', array(
'field'=>$fieldname)) ){
915 $oldSecure = $record->secureDisplay;
916 $record->secureDisplay =
false;
917 $out = $record->display($fieldname);
918 $record->secureDisplay = $oldSecure;
920 $out = $record->display($fieldname);
929 foreach (
$keys as $key){
930 $qstr .=
"&$key".
"=".$this->
strval($key);
932 $out = DATAFACE_SITE_HREF.
"?-action=getBlob&-table=".
$table->tablename.
"&-field=$fieldname$qstr";
956 $out = substr($strval, 0, $maxlength);
957 if ( strlen($strval)>$maxlength) {
997 $table =& $parent->_table->getTableTableForField($this->_relationshipName.
'.'.
$fieldname);
999 throw new Exception(
$table->toString(), E_USER_ERROR);
1034 if ( isset($this->cache[__FUNCTION__]) ){
1035 return $this->cache[__FUNCTION__];
1037 $parentid = $this->_record->getId();
1038 list(
$tablename, $querystr) = explode(
'?',$parentid);
1039 $id =
$tablename.
'/'.$this->_relationshipName.
'?'.$querystr;
1040 $keys = array_keys($this->_relationship->keys());
1042 foreach (
$keys as $key){
1043 $params[] = urlencode($this->_relationshipName.
'::'.$key).
'='.urlencode($this->
strval($key));
1045 $out = $id.
'&'.implode(
'&',$params);
1046 $this->cache[__FUNCTION__] =
$out;
1060 $method =
'rel_'.$this->_relationshipName.
'__getTitle';
1061 $del = $this->_record->table()->getDelegate();
1063 if ( isset($del) and method_exists($del, $method) ){
1064 return $del->$method($this);
1070 $oldSecureDisplay = $record->secureDisplay;
1071 $record->secureDisplay =
false;
1072 $out = $record->getTitle();
1073 $record->secureDisplay = $oldSecureDisplay;
1076 return $record->getTitle();
1112 if ( !is_array($params) ){
1113 $params = array(
'message'=> &$params);
1117 error_log(
$table->toString().implode(
"\n",
$table->getBacktrace()));
1118 throw new Exception(
"Failed to get table for field $fieldname. See error log for details", E_USER_ERROR);
1121 throw new Exception(
"Could not load table for field $fieldname .", E_USER_ERROR);
1125 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'])){
1129 $params[
'message'] =
"$fieldname is a required field.";
1135 $delegate =&
$table->getDelegate();
1136 if ( $delegate !== null and method_exists($delegate,
$fieldname.
"__validate") ){
1143 $res = $delegate->$methodname($this,$value,$params);
1162 function save($lang=null, $secure=
false){
1165 foreach (array_keys($recs) as $i){
1167 $res = $recs[$i]->save($lang, $secure);
1188 if ( isset($params[
'field']) ){
1189 if ( strpos($params[
'field'],
'.') !==
false ){
1190 list($junk,
$fieldname) = explode(
'.', $params[
'field']);
1194 $t =& $this->_relationship->getTable(
$fieldname);
1195 $rec = $this->
toRecord($t->tablename);
1198 $perms = $rec->getPermissions(array(
'field'=>
$fieldname,
'nobubble'=>1));
1199 if ( !$perms ) $perms = array();
1204 $rfperms = $this->_record->getPermissions(array(
'relationship'=>$this->_relationshipName,
'field'=>
$fieldname,
'nobubble'=>1));
1207 foreach ($rfperms as $k=>$v){
1212 unset($params[
'field']);
1216 foreach ($perms as $k=>$v){
1223 $domainTable = $this->_relationship->getDomainTable();
1224 $destinationTables = $this->_relationship->getDestinationTables();
1225 $isManyToMany = $this->_relationship->isManyToMany();
1227 if ( !@$targetTable ){
1228 if ( $isManyToMany ){
1229 foreach ($destinationTables as $candidateTable){
1230 if ( strcmp($candidateTable->tablename, $domainTable) !== 0 ){
1231 $targetTable = $candidateTable->tablename;
1237 if ( !@$targetTable ){
1238 $targetTable = $domainTable;
1241 $parentPerms = $this->_record->getPermissions(array(
'relationship'=>$this->_relationshipName));
1242 $domainRecord = $this->
toRecord($targetTable);
1245 $isDomainTable = (strcmp($domainTable, $targetTable) === 0 );
1248 $perms = $domainRecord->getPermissions();
1249 if ( $isManyToMany ){
1250 if ( @$parentPerms[
'add new related record'] ){
1252 }
else if ( @$parentPerms[
'add existing related record'] and !$isDomainTable ){
1254 }
else if ( $isDomainTable and isset($parentPerms[
'add new related record']) and !@$parentPerms[
'add new related record'] ){
1256 }
else if ( isset($parentPerms[
'add existing related record']) and !@$parentPerms[
'add existing related record'] ){
1260 if ( @$parentPerms[
'delete related record'] ){
1261 $perms[
'delete'] = 1;
1262 }
else if ( $isDomainTable and isset($parentPerms[
'delete related record']) and !@$parentPerms[
'delete related record'] ){
1263 $perms[
'delete'] = 0;
1264 }
else if ( !$isDomainTable and @$parentPerms[
'remove related record'] ){
1265 $perms[
'delete'] = 1;
1266 }
else if ( !$isDomainTable and isset($parentPerms[
'remove related record']) and !@$parentPerms[
'remove related record'] ){
1267 $perms[
'delete'] = 0;
1270 if ( !$isDomainTable ){
1271 if ( @$parentPerms[
'edit related records'] ){
1273 }
else if ( isset($parentPerms[
'edit related records']) and !@$parentPerms[
'edit related records'] ){
1277 if ( @$parentPerms[
'link related records'] ){
1279 }
else if ( isset($parentPerms[
'link related records']) and !@$parentPerms[
'link related records'] ){
1286 if ( @$parentPerms[
'add new related record'] ){
1288 }
else if ( isset($parentPerms[
'add new related record']) and !@$parentPerms[
'add new related record'] ){
1292 if ( @$parentPerms[
'delete related record'] ){
1293 $perms[
'delete'] = 1;
1294 }
else if ( isset($parentPerms[
'delete related record']) and !@$parentPerms[
'delete related record'] ){
1295 $perms[
'delete'] = 0;
1297 if ( @$parentPerms[
'edit related records'] ){
1299 }
else if ( isset($parentPerms[
'edit related records']) and !@$parentPerms[
'edit related records'] ){
1302 if ( @$parentPerms[
'link related records'] ){
1304 }
else if ( isset($parentPerms[
'link related records']) and !@$parentPerms[
'link related records'] ){
1311 if ( @$parentPerms[
'view related records'] ){
1313 }
else if ( isset($parentPerms[
'view related records']) and !@$parentPerms[
'view related records'] ){
1316 if ( @$parentPerms[
'find related records'] ){
1318 }
else if ( isset($parentPerms[
'find related records']) and !@$parentPerms[
'find related records'] ){
1358 return @$perms[$perm]?1:0;