106 $this->_name = $relationshipName;
108 $this->_schema = array();
109 $res = $this->
_init($values);
111 throw new Exception($res->getMessage());
114 if ( !isset($this->_schema[
'permissions']) ){
118 $this->_permissions =& $this->_schema[
'permissions'];
131 function &
fields($includeAll=
false, $includeTransient=
false){
134 return $this->_schema[
'columns'];
136 if ( !isset($this->_cache[__FUNCTION__][intval($includeAll)][intval($includeTransient)]) ){
139 $used_names = array();
140 foreach ( array_keys($tables) as $i ){
141 foreach ( $tables[$i]->
fields(
false,
true, $includeTransient) as $fld ){
142 if ( @$fld[
'grafted'] and @$used_names[$fld[
'Field']] )
continue;
145 $out[] = $tables[$i]->tablename.
'.'.$fld[
'Field'];
146 $used_names[ $fld[
'Field'] ] = 1;
149 $this->_cache[__FUNCTION__][intval($includeAll)][intval($includeTransient)] =
$out;
151 return $this->_cache[__FUNCTION__][intval($includeAll)][intval($includeTransient)];
157 if ( isset($this->_schema[
'__cardinality__']) ){
158 return $this->_schema[
'__cardinality__'];
192 if (in_array(
$fieldname, $this->_schema[
'short_columns'] ) )
return true;
193 if ( ($checkAll or $includeTransient) and preg_grep(
'/\.'.preg_quote(
$fieldname,
'/').
'$/', $this->
fields($checkAll, $includeTransient))){
221 foreach ($rel_values as $key=>$value){
222 if ( strpos($key,
":") !==
false ){
223 $path = explode(
":", $key);
228 for ($i=0; $i<$len; $i++ ){
230 if ( $i == $len -1 ) $val[
$path[$i]] = $value;
232 if ( !isset($val[$path[$i]]) ) {
233 $val[$path[$i]] = array();
237 $val =& $valTemp[$path[$i]];
245 if ( isset($rel_values[
'__cardinality__']) ) $r[
'__cardinality__'] = $rel_values[
'__cardinality__'];
247 if ( array_key_exists(
'__sql__', $rel_values ) ){
249 $r[
'sql'] = $rel_values[
'__sql__'];
252 $parser =
new SQL_Parser();
253 $struct = $parser->parse($r[
'sql']);
255 error_log($struct->toString().
"\n".implode(
"\n", $struct->getBacktrace()));
256 throw new Exception(
"Failed to parse relationship SQ. See error log for details.", E_USER_ERROR);
260 $parser_wrapper->fixColumns();
261 $r[
'parsed_sql'] =& $struct;
262 $r[
'tables'] = $struct[
'table_names'];
263 $r[
'columns'] = $struct[
'column_names'];
264 foreach ($struct[
'columns'] as $colstruct){
265 if ( $colstruct[
'type'] ==
'ident' and @$colstruct[
'alias'] ){
266 $r[
'aliases'][$colstruct[
'value']] = $colstruct[
'alias'];
270 foreach ( $r[
'columns'] as $column ){
271 $col = $parser_wrapper->resolveColumnName($column);
272 if (preg_match(
'/\.$/', $col) ){
277 $r[
'columns'] = $temp;
290 if ( array_key_exists(
'__select__', $rel_values ) ){
292 $select = $rel_values[
'__select__'];
306 foreach ( $rel_values as $c1 => $c2 ){
309 if ( in_array( $c1, array(
'__sql__',
'__select__',
'__sort__',
'__domain__',
'__cardinality__') ) )
continue;
311 if ( strpos( $c1,
":" ) !==
false )
continue;
319 $p1 = explode(
'.', $c1);
320 $p2 = explode(
'.', $c2);
322 if ( count( $p1 ) == 1 ){
324 array_unshift( $p1, $this->_sourceTable->tablename );
326 if ( count($p2) ==1 ){
328 array_unshift( $p2, $this->_sourceTable->tablename );
332 if ( !in_array( $p1[0], $tables ) && $p1[0] != $this->_sourceTable->tablename) $tables[] = $p1[0];
333 if ( !in_array( $p2[0], $tables ) && $p2[0] != $this->_sourceTable->tablename) $tables[] = $p2[0];
336 if( $p1[0] == $this->_sourceTable->tablename ){
339 $lhs =
"$p1[0].$p1[1]";
342 if ( $p2[0] == $this->_sourceTable->tablename ){
343 if ( strpos($p2[1],
'$')===0){
348 $rhs =
"'".$var.$p2[1].
"'";
350 $rhs =
"$p2[0].$p2[1]";
354 $where .= strlen($where) > 6 ?
' and ' :
'';
355 $where .=
"$lhs=$rhs";
360 foreach ($tables as
$table){
361 $from .= $table.
', ';
364 $from = substr( $from, 0, strlen($from)-2);
366 $r[
'sql'] =
"select $select $from $where";
371 $parser =
new SQL_Parser(null,
'MySQL');
373 $struct = $parser->parse($r[
'sql']);
375 $parser_wrapper->fixColumns();
376 $r[
'parsed_sql'] =& $struct;
377 $r[
'tables'] = $struct[
'table_names'];
378 $r[
'columns'] = $struct[
'column_names'];
380 foreach ( $r[
'columns'] as $column ){
381 $col = $parser_wrapper->resolveColumnName($column);
382 if (preg_match(
'/\.$/', $col) ){
387 $r[
'columns'] = $temp;
394 $r[
'short_columns'] = array();
395 foreach ($r[
'columns'] as $col ){
396 list(
$table,$col) = explode(
'.', $col);
397 $r[
'short_columns'][] = $col;
411 $tables =& $rel[
'tables'];
412 $selected_tables = array();
413 $rel[
'selected_tables'] =& $selected_tables;
416 $len =
sizeof($rel[
'columns']);
417 for ($i=0; $i<
sizeof($rel[
'columns']); $i++){
421 if ( preg_match(
'/^(\w+\.){0,1}\*$/', $rel[
'columns'][$i], $matches) ){
423 if ( isset( $matches[1]) ){
426 $temp_tables = array();
429 $temp_tables = $tables;
431 $temp_columns = array();
434 foreach ($temp_tables as
$table){
438 $table_table->addUserInfo(
"Failed to load table for table '$table'");
442 $fields = array_keys($table_table->fields());
443 for ($j=0; $j<count(
$fields); $j++){
447 $temp_columns = array_merge($temp_columns,
$fields);
448 if ( !in_array( $table, $selected_tables ) ){
449 $selected_tables[] =
$table;
457 $rel[
'columns'] = array_merge( $temp_columns, array_slice( $rel[
'columns'], 1, $len-1) );
460 }
else if ( $i==$len-1 ){
461 $rel[
'columns'] = array_merge( $rel[
'columns'], $temp_columns );
462 $len =
sizeof($rel[
'columns']);
469 $rel[
'columns'] = array_merge( array_slice( $rel[
'columns'], 0, $i),
471 array_slice( $rel[
'columns'], $i+1, $len-$i-1) );
472 $len =
sizeof($rel[
'columns']);
473 $i = $i +
sizeof($temp_columns) -1;
481 }
else if ( preg_match(
'/^(\w+)\.(\w+)$/', $rel[
'columns'][$i], $matches) ) {
484 $column = $matches[2];
487 $table_table->addUserInfo(
"Failed to load table for table '$table'");
488 error_log($table_table->toString().
"\n".implode(
"\n", $table_table->getBacktrace()));
489 throw new Exception(
"Failed to validate column ".$rel[
'columns'][$i].
". See error log for details.", E_USER_ERROR);
493 $selected_tables[] =
$table;
501 $name->addUserInfo(
"Failed get absolute field name for '".$rel[
'columns'][$i].
"'");
505 $rel[
'columns'][$i] = $name;
508 if ( preg_match(
'/(\w+)\.(\w+)/', $name, $matches)){
509 $selected_tables[] = $matches[1];
511 PEAR::raiseError(Dataface_SCHEMA_PARSE_ERROR,null,null,null,
"Error parsing table name from '$name' ");
516 $this->_schema[
'selected_tables'] = array_unique($this->_schema[
'selected_tables']);
542 function getSQL($getBlobs=
false, $where=0, $sort=0, $preview=1){
543 $start = microtime_float();
544 import(
'SQL/Compiler.php');
545 import(
'SQL/Parser/wrapper.php');
546 $loadParserTime = microtime_float() - $start;
547 if ( isset($this->_sql_generated[$where][$sort][$preview]) and $this->_sql_generated[$where][$sort][$preview] ){
553 return $this->_schema[
'sql_with_blobs'][$where][$sort][$preview];
556 return $this->_schema[
'sql_without_blobs'][$where][$sort][$preview];
562 $this->_sql_generated[$where][$sort][$preview] =
true;
563 if ( !isset( $this->_schema[
'sql_without_blobs'] ) ){
564 $this->_schema[
'sql_without_blobs'] = array();
566 if ( !isset($this->_schema[
'sql_with_blobs']) ){
567 $this->_schema[
'sql_with_blobs'] = array();
570 if ( defined(
'DATAFACE_USE_CACHE') and DATAFACE_USE_CACHE ){
571 $cache_key_blobs =
'tables/'.$this->_sourceTable->tablename.
'/relationships/'.$this->_name.
'/sql/withblobs';
572 $cache_key_noblobs =
'tables/'.$this->_sourceTable->tablename.
'/relationships/'.$this->_name.
'/sql/withoutblobs';
574 import(
'Dataface/Cache.php');
576 $this->_schema[
'sql_with_blobs'] = $cache->get($cache_key_blobs);
577 $this->_schema[
'sql_without_blobs'] = $cache->get($cache_key_noblobs);
583 if ( !isset($this->_schema[
'sql_without_blobs'][$where][$sort][$preview]) or !isset($this->_schema[
'sql_with_blobs'][$where][$sort][$preview])){
588 $parsed = unserialize(serialize($this->_schema[
'parsed_sql']));
589 $parsed[
'column_names'] = array();
590 $parsed[
'column_aliases'] = array();
591 $parsed[
'columns'] = array();
595 $tableAliases = array();
598 foreach ( array_keys($parsed[
'tables']) as $tkey ){
599 if ( $parsed[
'tables'][$tkey][
'type'] ==
'ident' ){
601 $proxyView =
$table->getProxyView();
603 if ( isset($tsql) and !$proxyView){
604 $parsed[
'tables'][$tkey][
'type'] =
'compiled_subselect';
605 $parsed[
'tables'][$tkey][
'value'] = $tsql;
606 if ( !$parsed[
'tables'][$tkey][
'alias'] ) $parsed[
'tables'][$tkey][
'alias'] =
$table->tablename;
607 }
else if ( $proxyView ){
608 $parsed[
'tables'][$tkey][
'value'] = $proxyView;
609 if ( !$parsed[
'tables'][$tkey][
'alias'] ) $parsed[
'tables'][$tkey][
'alias'] =
$table->tablename;
611 $tableAliases[
$table->tablename] = $parsed[
'tables'][$tkey][
'alias'];
618 foreach ( $this->
fields(
true) as $colname){
622 list(
$tablename, $col) = explode(
'.',$colname);
628 if ( isset($done[$col]) ) $dups[$col] =
$tablename;
636 $colname = $alias.
'.'.$col;
640 if (
$table->isPassword($col) ){
645 if (
$table->isBlob($col) ){
646 $blobCols[] = $colname;
655 $colFull =
'`'.$tableAlias.
'`.`'.$col.
'`';
659 $colFull =
'`'.$col.
'`';
663 $rfieldProps = array();
664 if ( isset($this->_schema[
'field']) and isset($this->_schema[
'field'][$col])){
665 $rfieldProps = $this->_schema[
'field'][$col];
669 if ( @$rfieldProps[
'max_length'] ){
670 $maxlen = intval($rfieldProps[
'max_length']);
673 if ( in_array(strtolower(
$table->getType($col)), array(
'timestamp',
'datetime')) ){
675 $parsed[
'columns'][] = array(
'type'=>
'compiled_func',
'table'=>null,
'value'=>
"ifnull(convert_tz(".$colFull.
",'SYSTEM','".addslashes(df_tz_or_offset()).
"'), ".$colFull.
")",
'alias'=>$col);
676 }
else if ( $preview and
$table->isText($col) and !@
$field[
'struct'] and !
$table->isXML($col)){
677 $parsed[
'columns'][] = array(
'type'=>
'compiled_func',
'table'=>null,
'value'=>
"SUBSTRING($colFull, 1, $maxlen)",
'alias'=>$col);
680 $parsed[
'columns'][] = array(
'type'=>
'ident',
'table'=>$tableAlias,
'value'=>$col,
'alias'=>null);
692 $whereClause = $where;
694 foreach ( $dups as $dcolname=>$dtablename ){
695 $whereClause = preg_replace(
'/([^.]|^) *`'.preg_quote($dcolname).
'`/',
'$1 `'.$dtablename.
'`.`'.$dcolname.
'`', $whereClause);
697 $wrapper->addWhereClause($whereClause);
701 foreach ( $dups as $dcolname=>$dtablename ){
702 $sortClause = preg_replace(
'/([^.]|^) *`'.preg_quote($dcolname).
'`/',
'$1 `'.$dtablename.
'`.`'.$dcolname.
'`', $sortClause);
704 $wrapper->setSortClause($sortClause);
708 $compiler =& SQL_Compiler::newInstance(
'mysql');
709 $compiler->version = 2;
710 $this->_schema[
'sql_with_blobs'][$where][$sort][$preview] = $compiler->compile($parsed);
713 foreach ($blobCols as $blobCol){
714 $wrapper->removeColumn($blobCol);
716 $this->_schema[
'sql_without_blobs'][$where][$sort][$preview] = $compiler->compile($parsed);
718 if ( defined(
'DATAFACE_USE_CACHE') and DATAFACE_USE_CACHE){
719 $cache->set($cache_key_blobs, $this->_schema[
'sql_with_blobs']);
720 $cache->set($cache_key_noblobs, $this->_schema[
'sql_without_blobs']);
731 $timeToGenerate = microtime_float()-$start;
732 if ( DATAFACE_DEBUG ){
733 $this->app->addDebugInfo(
"Time to generate sql for relationship {$this->name} : $timeToGenerate");
735 return $this->
getSQL($getBlobs, $where, $sort);
754 $action = $this->_sourceTable->getRelationshipsAsActions(array(), $this->_name);
755 return $action[
'label'];
768 $action = $this->_sourceTable->getRelationshipsAsActions(array(), $this->_name);
769 if ( !isset($action[
'singular_label']) ){
772 $action[
'singular_label'] = df_singularize($label);
777 return $action[
'singular_label'];
791 if ( !isset($this->addNew) ){
792 $this->addNew = !( isset( $this->_schema[
'actions'][
'addnew'] ) and !$this->_schema[
'actions'][
'addnew'] );
804 if ( !isset($this->addExisting) ){
805 $this->addExisting=
true;
807 if ( count($fkeys) == 1 ){
808 $this->addExisting =
false;
826 if ( isset( $this->_schema[
'actions'][
'addexisting'] ) and !$this->_schema[
'actions'][
'addexisting'] ){
827 $this->addExisting =
false;
829 else if ( isset( $this->_schema[
'actions'][
'addexisting'] ) and $this->_schema[
'actions'][
'addexisting'] ) {
830 $this->addExisting =
true;
843 if (isset( $this->_schema[
'actions'][
'remove'] ) and !$this->_schema[
'actions'][
'remove'] )
return false;
849 return ( @$this->_schema[
'prefs'][
'addnew'][
'show_tabs'] !==
'0' );
865 if ( !isset($this->_keys) ){
866 $this->_keys = array();
868 foreach ( array_keys($destTables) as $x ){
869 $table =& $destTables[$x];
870 $tkeys = array_keys(
$table->keys());
871 foreach ($tkeys as $tkey){
872 $this->_keys[$tkey] =
$table->getField($tkey);
884 if ( !isset( $this->_destinationTables ) ){
885 $this->_destinationTables = array();
886 $this->_fieldTableLookup = array();
887 $columns =& $this->_schema[
'columns'];
900 $this->_destinationTables = array();
902 foreach ( array_keys($tables) as $tableIndex ){
903 if ( @$found[$tables[$tableIndex]->tablename] )
continue;
905 $found[$tables[$tableIndex]->tablename] =
true;
906 $this->_destinationTables[] =& $tables[$tableIndex];
920 if ( strpos(
$field,
'.') !==
false ){
926 if ( isset($this->_fieldTableLookup[
$field]) )
return $this->_fieldTableLookup[
$field];
928 $fields = preg_grep(
'/\.'.preg_quote($field,
'/').
'$/', $this->
fields(
true,
true));
936 return $this->_fieldTableLookup[
$field];
947 if ( !isset($this->_schema) || !isset($this->_schema[
'parsed_sql']) || !is_array($this->_schema[
'parsed_sql'][
'table_names']) )
return null;
948 $idx = array_search($tableName, $this->_schema[
'parsed_sql'][
'table_names']);
949 if ( $idx !==
false ){
950 return $this->_schema[
'parsed_sql'][
'table_aliases'][$idx];
965 if ( !isset($this->_cache[__FUNCTION__][
$fieldname]) ){
966 if ( strpos($fieldname,
'.') !==
false ){
967 list(
$tablename, $sfieldname) = explode(
'.', $fieldname);
974 $f =& $domainTable->getField($fieldname);
979 $fields = preg_grep(
'/\.'.preg_quote($fieldname,
'/').
'$/', $this->
fields(
true));
984 list(
$tablename, $sfieldname) = explode(
'.',$lfieldname);
995 return $this->_cache[__FUNCTION__][
$fieldname];
1014 if ( !isset( $relationship[
'domain_sql'] ) ){
1015 import(
'SQL/Compiler.php');
1017 import(
'SQL/Parser/wrapper.php');
1019 $compiler =
new SQL_Compiler();
1021 $parsed_sql = unserialize(serialize($relationship[
'parsed_sql']));
1028 $wrapper->removeWhereClausesWithTable( $this->_sourceTable->tablename);
1029 $wrapper->removeJoinClausesWithTable( $this->_sourceTable->tablename);
1034 $wrapper->removeWhereClausesWithPattern(
'/\$\w+/' );
1035 $wrapper->removeJoinClausesWithPattern(
'/\$\w+/' );
1043 $uselessTables = array();
1045 $fkTables = array_keys($fkVals);
1048 foreach ($fkVals as $fkTable => $fkFields){
1052 foreach ($fkFields as $fieldVal){
1061 if ( is_scalar($fieldVal) and strpos($fieldVal,
'$') === 0 ){
1069 $uselessTables[] = $fkTable;
1076 foreach ($uselessTables as $table_name){
1078 $wrapper->removeWhereClausesWithTable( $table_name );
1079 $wrapper->removeJoinClausesWithTable( $table_name );
1080 $wrapper->removeColumnsFromTable( $table_name );
1083 $domain_tables = array_diff($relationship[
'selected_tables'], $uselessTables);
1084 if ( !$domain_tables ) $domain_tables = $relationship[
'selected_tables'];
1086 $table_ranks = array();
1087 foreach ($this->_schema[
'columns'] as $col){
1088 list($tname) = explode(
'.',$col);
1089 if ( !isset($table_ranks[$tname]) ) $table_ranks[$tname] = 0;
1090 $table_ranks[$tname]++;
1095 foreach ( $domain_tables as $dt ){
1096 if ( $table_ranks[$dt] > $high_score ){
1098 $high_score = $table_ranks[$dt];
1101 $domain_tables = array($high);
1104 if ( count($domain_tables) !== 1 ){
1105 return PEAR::raiseError(
"Error calculating domain tables for relationship '".$this->_name.
"'. Selected tables are {".implode(
',',$relationship[
'selected_tables']).
"} and Useless tables are {".implode(
',', $uselessTables).
"}.",null,null,null,1);
1107 $relationship[
'domain_table'] = array_pop($domain_tables);
1110 $wrapper->packTables();
1116 $relationship[
'domain_sql'] = $compiler->compile($parsed_sql);
1118 return $relationship[
'domain_sql'];
1131 if ( !isset($this->domainTable) ){
1136 $this->domainTable = $this->_schema[
'domain_table'];
1138 return $this->domainTable;
1158 if ( is_object($record) ) $record_id = $record->getId();
1159 if ( !isset($values) and !isset($sql) and !isset($record) and isset($this->_cache[__FUNCTION__]) ){
1160 return $this->_cache[__FUNCTION__];
1162 if ( !isset($values) and !isset($sql) and is_object($record) and isset($this->_cache[__FUNCTION__.$record_id]) ){
1163 return $this->_cache[__FUNCTION__.$record_id];
1195 if ( $sql !== null ){
1198 if ( is_string($sql) ) {
1199 $parser =
new SQL_Parser(null,
'MySQL');
1200 $sql = $parser->parse($sql);
1205 $select =& $relationship[
'parsed_sql'];
1216 if ( is_array($values) ){
1217 foreach ($values as $field_name => $field_value ){
1219 if ( !$field_value )
continue;
1223 if ( isset( $labels[$field_name] ) ) $label = $labels[$field_name];
1225 $label = $field_name;
1226 $labels[$field_name] = $label;
1230 $vals[$label] = $field_value;
1240 foreach ( $labels as $field_name=>$label ){
1241 if ( !isset( $vals[$label] ) ){
1243 $table_auto_increment = null;
1244 foreach ( $labels as $auto_field_name=>$auto_label ){
1245 if ( $auto_label == $label ){
1247 if ( $auto_field[
'Extra'] ==
'auto_increment' ){
1248 list($table_auto_increment) = explode(
'.', $auto_field_name);
1255 if ( isset($table_auto_increment) ){
1257 $vals[$label] =
"__".$table_auto_increment.
"__auto_increment__";
1265 $table_cols = array();
1266 foreach ( $labels as $field_name=>$label){
1270 if ( !isset( $table_cols[
$table] ) ) $table_cols[
$table] = array();
1271 $table_cols[
$table][
$field] = ( is_scalar(@$vals[$label]) and $record !== null and !preg_match(
'/(blob|binary)/', strtolower($fieldArr[
'Type'])) ) ? $record->parseString(@$vals[$label]) : @$vals[$label];
1276 foreach ( $table_cols as
$table=>$cols ){
1278 foreach ( array_keys($tableObject->mandatoryFields()) as $key ){
1279 if ( !isset( $cols[$key] ) ){
1283 unset($tableObject);
1287 if ( !isset($values) and !isset($sql) and !isset($record) ){
1288 $this->_cache[__FUNCTION__] = $table_cols;
1290 if ( !isset($values) and !isset($sql) and is_object($record) ){
1291 $this->_cache[__FUNCTION__.$record_id] = $table_cols;
1299 return is_a($val,
'Dataface_Relationship_ForeignKey');
1313 if ( !isset($fkeys[
$table]) )
return 999;
1314 foreach ( $fkeys[$table] as $key=>$value ){
1315 if ( is_scalar($value) and strlen($value) > 0 and $value{0} ==
'$' )
return 1;
1322 $this->_addExistingFilters = null;
1323 if ( !isset($this->_addExistingFilters) ){
1324 $this->_addExistingFilters = array();
1326 if ( count($fkeys) == 1 ){
1328 $this->_addExistingFilters[$fname] =
'=';
1332 return $this->_addExistingFilters;
1348 $tkey_names = array_keys($t->keys());
1349 if ( !is_a($record,
'Dataface_Record') ){
1350 throw new Exception(
"Attempt to call getAddableValues() without providing a Dataface_Record as context.", E_USER_ERROR);
1353 if ( ( $res = $record->callDelegateFunction($this->_name.
'__'.__FUNCTION__) ) !== null ){
1357 if ( isset( $this->_schema[
'vocabulary'][
'existing'] ) ){
1360 $options_temp = $t->getValuelist($r[
'vocabulary'][
'existing']);
1362 foreach (array_keys($options_temp) as $optkey){
1363 if ( strpos($optkey,
'=') ===
false ){
1364 $options[$tkey_names[0].
'='.urlencode($optkey)] = $options_temp[$optkey];
1366 $options[$optkey] = $options_temp[$optkey];
1374 if ( isset( $fkeys[
$table] ) ){
1376 foreach ($query as $key=>$val){
1377 if ( $this->
isNullForeignKey($val) or strpos($val,
'$')===0 or $val ==
'__'.$table.
'__auto_increment__'){
1378 unset($query[$key]);
1384 $query = array_merge($filter, $query);
1386 $options = $qt->getTitles(
true,
false,
true);
1407 if ( isset( $sql_data[
'where_clause'] ) and is_array( $sql_data[
'where_clause'] )){
1408 $roots[] =& $sql_data[
'where_clause'];
1410 if ( isset( $sql_data[
'table_join_clause'] ) and is_array( $sql_data[
'table_join_clause']) ){
1411 foreach ( $sql_data[
'table_join_clause'] as $clause ){
1412 if ( is_array($clause) ){
1418 foreach ($roots as $root){
1437 if ( isset( $root[
'op'] ) ){
1438 if ( $root[
'op'] ==
'=' ){
1442 $existingLabels = 0;
1445 foreach ( array(
'arg_1',
'arg_2') as $arg ){
1446 switch ($root[$arg][
'type']){
1449 $parser_wrapper->resolveColumnName($root[$arg][
'value']),
1450 $parser_wrapper->_data[
'table_names']
1453 if ( !is_string($field_name) ){
1454 echo
"Field name is not a string.";
1455 echo get_class($field_name);
1456 if ( is_a($field_name,
'PEAR_Error') ) echo $field_name->toString();
1461 if ( isset( $labels[$field_name] ) ) {
1463 if ( $existingLabels > 1 ){
1467 $label = $labels[$field_name];
1475 $value = $root[$arg][
'value'];
1484 $label = ( $label ? $label :
$fields[0] );
1487 if ( !isset( $labels[$field] ) ) $labels[$field] = $label;
1491 if ( $oldLabel !== null ){
1492 foreach ( $labels as $field_name=>$field_label ) {
1493 if ( $field_label == $oldLabel ){
1494 $labels[$field_name] = $label;
1500 if ( $value !== null ){
1501 $values[$label] = $value;
1506 foreach ( $root as $key=>$value ){
1507 if ( is_array($value) ){
1536 $order_col = ( ( isset( $this->_schema[
'metafields'][
'order']) and $this->_schema[
'metafields'][
'order'] ) ? $this->_schema[
'metafields'][
'order'] : null );
1537 if ( !isset($order_col) ){
1538 return PEAR::isError(
'Attempt to sort relationship "'.$this->_name.
'" but no order column was defined.');
1555 return ( isset( $this->_schema[
'meta'][
'class']) and strtolower($this->_schema[
'meta'][
'class']) ==
'parent');
1570 return ( isset($this->_schema[
'meta'][
'class']) and strtolower($this->_schema[
'meta'][
'class']) ==
'children');
1587 if ( isset($this->_cache[__FUNCTION__]) )
return $this->_cache[__FUNCTION__];
1589 return $this->_cache[__FUNCTION__];
1608 if ( $cardinality ==
'*' )
return 0;
1609 else if ( $cardinality ==
'+' )
return 1;
1610 else if ( strpos($cardinality,
'..') !==
false ){
1611 list($min,$max) = array_map(
'trim',explode(
'..', $cardinality));
1612 $min = intval($min);
1622 if ( $cardinality ==
'*' )
return 0;
1623 else if ( $cardinality ==
'+' )
return 1;
1624 else if ( strpos($cardinality,
'..') !==
false ){
1625 list($min,$max) = array_map(
'trim',explode(
'..', $cardinality));
1626 if ( $max ==
'*' )
return 0;
1627 return intval($max);
1643 return ($min === 0 and $max === 1);
1653 if ( isset($params[
'field']) ){
1654 if ( strpos($params[
'field'],
'.') !==
false ){
1655 list($junk,
$fieldname) = explode(
'.', $params[
'field']);
1663 $perms = $t->getPermissions(array(
'field'=>
$fieldname,
'nobubble'=>1));
1664 if ( !$perms ) $perms = array();
1669 $rfperms = $this->_sourceTable->getPermissions(array(
'relationship'=>$this->
getName(),
'field'=>
$fieldname,
'nobubble'=>1));
1672 foreach ($rfperms as $k=>$v){
1677 unset($params[
'field']);
1681 foreach ($perms as $k=>$v){
1692 if ( !@$targetTable ){
1693 if ( $isManyToMany ){
1694 foreach ($destinationTables as $candidateTable){
1695 if ( strcmp($candidateTable->tablename, $domainTable) !== 0 ){
1696 $targetTable = $candidateTable->tablename;
1702 if ( !@$targetTable ){
1703 $targetTable = $domainTable;
1706 $parentPerms = $this->_sourceTable->getPermissions(array(
'relationship'=>$this->
getName()));
1711 $isDomainTable = (strcmp($domainTable, $targetTable) === 0 );
1714 $perms = $targetTableObj->getPermissions();
1715 if ( $isManyToMany ){
1716 if ( @$parentPerms[
'add new related record'] ){
1718 }
else if ( @$parentPerms[
'add existing related record'] and !$isDomainTable ){
1720 }
else if ( $isDomainTable and isset($parentPerms[
'add new related record']) and !@$parentPerms[
'add new related record'] ){
1722 }
else if ( isset($parentPerms[
'add existing related record']) and !@$parentPerms[
'add existing related record'] ){
1726 if ( @$parentPerms[
'delete related record'] ){
1727 $perms[
'delete'] = 1;
1728 }
else if ( $isDomainTable and isset($parentPerms[
'delete related record']) and !@$parentPerms[
'delete related record'] ){
1729 $perms[
'delete'] = 0;
1730 }
else if ( !$isDomainTable and @$parentPerms[
'remove related record'] ){
1731 $perms[
'delete'] = 1;
1732 }
else if ( !$isDomainTable and isset($parentPerms[
'remove related record']) and !@$parentPerms[
'remove related record'] ){
1733 $perms[
'delete'] = 0;
1736 if ( !$isDomainTable ){
1737 if ( @$parentPerms[
'edit related records'] ){
1739 }
else if ( isset($parentPerms[
'edit related records']) and !@$parentPerms[
'edit related records'] ){
1743 if ( @$parentPerms[
'link related records'] ){
1745 }
else if ( isset($parentPerms[
'link related records']) and !@$parentPerms[
'link related records'] ){
1752 if ( $parentPerms[
'add new related record'] ){
1754 }
else if ( isset($parentPerms[
'add new related record']) and !@$parentPerms[
'add new related record'] ){
1758 if ( @$parentPerms[
'delete related record'] ){
1759 $perms[
'delete'] = 1;
1760 }
else if ( isset($parentPerms[
'delete related record']) and !@$parentPerms[
'delete related record'] ){
1761 $perms[
'delete'] = 0;
1763 if ( @$parentPerms[
'edit related records'] ){
1765 }
else if ( isset($parentPerms[
'edit related records']) and !@$parentPerms[
'edit related records'] ){
1768 if ( @$parentPerms[
'link related records'] ){
1770 }
else if ( isset($parentPerms[
'link related records']) and !@$parentPerms[
'link related records'] ){
1777 if ( @$parentPerms[
'view related records'] ){
1779 }
else if ( isset($parentPerms[
'view related records']) and !@$parentPerms[
'view related records'] ){
1782 if ( @$parentPerms[
'find related records'] ){
1784 }
else if ( isset($parentPerms[
'find related records']) and !@$parentPerms[
'find related records'] ){
1809 return @$perms[$perm]?1:0;
1833 foreach ( $labels as
$field=>$l ){
1834 if ( $l==$label ) $this->fields[] =
$field;
1861 foreach ($this->fields as
$field){
1862 list(
$table) = explode(
'.', $field);
1863 $td = $this->relationship->getDistance(
$table);