+ /**
+ * autoJoin - using the links.ini file, it builds a query with all the joins
+ * usage:
+ * $x = DB_DataObject::factory('mytable');
+ * $x->autoJoin();
+ * $x->get(123);
+ * will result in all of the joined data being added to the fetched object..
+ *
+ * $x = DB_DataObject::factory('mytable');
+ * $x->autoJoin();
+ * $ar = $x->fetchAll();
+ * will result in an array containing all the data from the table, and any joined tables..
+ *
+ * $x = DB_DataObject::factory('mytable');
+ * $jdata = $x->autoJoin();
+ * $x->selectAdd(); //reset..
+ * foreach($_REQUEST['requested_cols'] as $c) {
+ * if (!isset($jdata[$c])) continue; // ignore columns not available..
+ * $x->selectAdd( $jdata[$c] . ' as ' . $c);
+ * }
+ * $ar = $x->fetchAll();
+ * will result in only the columns requested being fetched...
+ *
+ *
+ *
+ * @param array Configuration
+ * exclude Array of columns to exclude from results (eg. modified_by_id)
+ * links The equivilant links.ini data for this table eg.
+ * array( 'person_id' => 'person:id', .... )
+ * include Array of columns to include
+ * distinct Array of distinct columns.
+ *
+ * @return array info about joins
+ * cols => map of resulting {joined_tablename}.{joined_table_column_name}
+ * join_names => map of resulting {join_name_as}.{joined_table_column_name}
+ * count => the column to count on.
+ * @access public
+ */
+ function autoJoin($cfg = array())
+ {
+ //var_Dump($cfg);exit;
+ $pre_links = $this->links();
+ if (!empty($cfg['links'])) {
+ $this->links(array_merge( $pre_links , $cfg['links']));
+ }
+ $map = $this->links( );
+
+
+ //print_r($map);
+ $tabdef = $this->table();
+
+ // we need this as normally it's only cleared by an empty selectAs call.
+
+
+ $keys = array_keys($tabdef);
+ if (!empty($cfg['exclude'])) {
+ $keys = array_intersect($keys, array_diff($keys, $cfg['exclude']));
+ }
+ if (!empty($cfg['include'])) {
+
+ $keys = array_intersect($keys, $cfg['include']);
+ }
+
+ $selectAs = array();
+
+ if (!empty($keys)) {
+ $selectAs = array(array( $keys , '%s', false));
+ }
+
+ $ret = array(
+ 'cols' => array(),
+ 'join_names' => array(),
+ 'count' => false,
+ );
+
+
+
+ $has_distinct = false;
+ if (!empty($cfg['distinct']) && $keys) {
+
+ // reset the columsn?
+ $cols = array();
+
+ //echo '<PRE>' ;print_r($xx);exit;
+ foreach($keys as $c) {
+ //var_dump($c);
+
+ if ( $cfg['distinct'] == $c) {
+ $has_distinct = 'DISTINCT( ' . $this->tableName() .'.'. $c .') as ' . $c;
+ $ret['count'] = 'DISTINCT ' . $this->tableName() .'.'. $c .'';
+ continue;
+ }
+ // cols is in our filtered keys...
+ $cols = $c;
+
+ }
+ // apply our filtered version, which excludes the distinct column.
+
+ $selectAs = empty($cols) ? array() : array(array(array( $cols) , '%s', false)) ;
+
+
+
+ }
+
+ foreach($keys as $k) {
+ $ret['cols'][$k] = $this->tableName(). '.' . $k;
+ }
+
+
+
+ foreach($map as $ocl=>$info) {
+
+ list($tab,$col) = explode(':', $info);
+ // what about multiple joins on the same table!!!
+ $xx = DB_DataObject::factory($tab);
+ if (!is_object($xx) || !is_a($xx, 'DB_DataObject')) {
+ continue;
+ }
+ // skip columns that are excluded.
+
+ // we ignore include here... - as
+
+ // this is borked ... for multiple jions..
+ $this->joinAdd($xx, 'LEFT', 'join_'.$ocl.'_'. $col, $ocl);
+
+ if (!empty($cfg['exclude']) && in_array($ocl, $cfg['exclude'])) {
+ continue;
+ }
+
+ $tabdef = $xx->table();
+ $table = $xx->tableName();
+
+ $keys = array_keys($tabdef);
+
+
+ if (!empty($cfg['exclude'])) {
+ $keys = array_intersect($keys, array_diff($keys, $cfg['exclude']));
+
+ foreach($keys as $k) {
+ if (in_array($ocl.'_'.$k, $cfg['exclude'])) {
+ $keys = array_diff($keys, $k); // removes the k..
+ }
+ }
+
+ }
+
+ if (!empty($cfg['include'])) {
+ // include will basically be BASECOLNAME_joinedcolname
+ $nkeys = array();
+ foreach($keys as $k) {
+ if (in_array( sprintf($ocl.'_%s', $k), $cfg['include'])) {
+ $nkeys[] = $k;
+ }
+ }
+ $keys = $nkeys;
+ }
+
+ if (empty($keys)) {
+ continue;
+ }
+ // got distinct, and not yet found it..
+ if (!$has_distinct && !empty($cfg['distinct'])) {
+ $cols = array();
+ foreach($keys as $c) {
+ $tn = sprintf($ocl.'_%s', $c);
+
+ if ( $tn == $cfg['distinct']) {
+
+ $has_distinct = 'DISTINCT( ' . 'join_'.$ocl.'_'.$col.'.'.$c .') as ' . $tn ;
+ $ret['count'] = 'DISTINCT join_'.$ocl.'_'.$col.'.'.$c;
+ // var_dump($this->countWhat );
+ continue;
+ }
+ $cols[] = $c;
+
+ }
+
+ if (!empty($cols)) {
+ $selectAs[] = array($cols, $ocl.'_%s', 'join_'.$ocl.'_'. $col);
+ }
+
+ } else {
+ $selectAs[] = array($keys, $ocl.'_%s', 'join_'.$ocl.'_'. $col);
+ }
+
+ foreach($keys as $k) {
+ $ret['cols'][sprintf('%s_%s', $ocl, $k)] = $tab.'.'.$k;
+ $ret['join_names'][sprintf('%s_%s', $ocl, $k)] = sprintf('join_%s_%s.%s',$ocl, $col, $k);
+ }
+
+ }
+
+ // fill in the select details..
+ $this->selectAdd();
+
+ if ($has_distinct) {
+ $this->selectAdd($has_distinct);
+ }
+
+ foreach($selectAs as $ar) {
+ $this->selectAs($ar[0], $ar[1], $ar[2]);
+ }
+ // restore links..
+ $this->links( $pre_links );
+
+ return $ret;
+
+ }
+
+ /**
+ * Factory method for calling DB_DataObject_Cast
+ *
+ * if used with 1 argument DB_DataObject_Cast::sql($value) is called
+ *
+ * if used with 2 arguments DB_DataObject_Cast::$value($callvalue) is called
+ * valid first arguments are: blob, string, date, sql
+ *
+ * eg. $member->updated = $member->sqlValue('NOW()');
+ *
+ *
+ * might handle more arguments for escaping later...
+ *
+ *
+ * @param string $value (or type if used with 2 arguments)
+ * @param string $callvalue (optional) used with date/null etc..
+ */
+
+ function sqlValue($value)
+ {
+ $method = 'sql';
+ if (func_num_args() == 2) {
+ $method = $value;
+ $value = func_get_arg(1);
+ }
+ require_once 'DB/DataObject/Cast.php';
+ return call_user_func(array('DB_DataObject_Cast', $method), $value);
+
+ }
+
+