![]() |
Xataface 2.0
Xataface Application Framework
|
00001 <?php 00002 00003 class Dataface_CopyTool { 00004 var $warnings; 00005 00006 public static function &getInstance(){ 00007 static $instance = 0; 00008 if ( !is_object($instance) ){ 00009 $instance = new Dataface_CopyTool(); 00010 } 00011 return $instance; 00012 } 00013 00014 00015 function evaluate($expr, $fieldname, Dataface_Record $record){ 00016 00017 // Check the field type first. If this is a numeric field 00018 // we evaluate with math 00019 // If it is a string, we evaluate with string functions 00020 00021 // Chop the leading '=' 00022 $expr = substr($expr,1); 00023 00024 $table = $record->table(); 00025 if ( $table->isInt($fieldname) or $table->isFloat($fieldname) ){ 00026 // This field is a numeric field so we treat it like 00027 // a numeric operation 00028 $oldval = $record->val($fieldname); 00029 if ( !$oldval ) $oldval = 0; 00030 $expr = preg_replace('/\$\$/', $oldval, $expr); 00031 if ( preg_match('/^[\+\-\*\/]/', $expr) ){ 00032 // If expression begins with an operation, we apply 00033 // the old value as the first operand of this 00034 // operation. 00035 $expr = $oldval.$expr; 00036 } 00037 00038 if ( !preg_match('/^[0-9\.\*\+\/\-\^\(\) ]+$/', $expr) ){ 00039 throw new Exception("Invalid arithmetic expression."); 00040 } 00041 @eval('$expr='.$expr.';'); 00042 return $expr; 00043 00044 00045 } else if ( $table->isDate($fieldname) ){ 00046 00047 // This field is a date field so we treat it like a 00048 // date operation 00049 $oldtime = strtotime($record->strval($fieldname)); 00050 return date($expr, $oldtime); 00051 00052 } else { 00053 // We assume it is a string 00054 $oldval = $record->val($fieldname); 00055 $expr = preg_replace('/\$\$/', $oldval, $expr); 00056 return $expr; 00057 00058 } 00059 00060 } 00061 00062 function copy($record, $vals=array(), $force=true){ 00063 00064 foreach ($vals as $k=>$v){ 00065 if ( strpos($v,'=') === 0 ){ 00066 $vals[$k] = $this->evaluate($v, $k, $record); 00067 } 00068 } 00069 00070 $del = $record->_table->getDelegate(); 00071 if ( isset($del) and method_exists($del, 'beforeCopy') ){ 00072 $res = $del->beforeCopy($record, $vals); 00073 if ( PEAR::isError($res) ){ 00074 return $res; 00075 } 00076 } 00077 $this->warnings = array(); 00078 // Step 1: Load the record - it has been passed 00079 // Step 2: build sql query to copy the record 00080 $query = $this->buildCopyQuery($record, $vals, $force); 00081 if ( PEAR::isError($query) ){ 00082 return $query; 00083 } 00084 $res = df_query($query); 00085 if ( !$res ){ 00086 return PEAR::raiseError("Failed to copy record '".$record->getTitle()."' due to an SQL error:".mysql_error()); 00087 } 00088 if ( PEAR::isError($res) ) return $res; 00089 00090 00091 $ret = null; 00092 00093 if ( $auto_field_id = $record->_table->getAutoIncrementField()) { 00094 $insert_id = df_insert_id(); 00095 $copied =& df_get_record($record->_table->tablename, array($auto_field_id=>$insert_id)); 00096 $ret = $copied; 00097 } else { 00098 $ret = new Dataface_Record($record->_table->tablename, array_merge($record->vals(), $vals)); 00099 } 00100 00101 if ( isset($del) and method_exists($del, 'afterCopy')){ 00102 $res = $del->afterCopy($record, $ret); 00103 if ( PEAR::isError($res) ){ 00104 return $res; 00105 } 00106 00107 } 00108 return $ret; 00109 00110 } 00111 00127 function buildCopyQuery($record,$vals=array(), $force=true){ 00128 00129 $dummy = new Dataface_Record($record->_table->tablename, $vals); 00130 if ( !$record->checkPermission('view') || !$dummy->checkPermission('edit') ){ 00131 return Dataface_Error::permissionDenied("Failed to copy record '".$record->getTitle()."' because of insufficient permissions."); 00132 } 00133 00134 $copy_fields = array_keys($record->_table->fields()); 00135 00136 // Go through each field and see if we have copy permission. 00137 // Copy permission is two-fold: 1- make sure the source is viewable 00138 // 2- make sure the destination is editable. 00139 $failed = false; 00140 foreach ($copy_fields as $key=>$fieldname){ 00141 if ( !$record->checkPermission('view', array('field'=>$fieldname)) 00142 || !$dummy->checkPermission('edit', array('field'=>$fieldname)) ){ 00143 $this->warnings[] = Dataface_Error::permissionDenied("The field '$fieldname' could not be copied for record '".$record->getTitle()."' because of insufficient permissions."); 00144 unset($copy_fields[$key]); 00145 $failed = true; 00146 } 00147 } 00148 00149 00150 // If we are not forcing completion, any failures will result in cancellation 00151 // of the copy. 00152 if ( !$force and $failed ){ 00153 return Dataface_Error::permissionDenied("Failed to copy the record '".$record->getTitle()."' due to insufficient permissions on one or more of the columns."); 00154 } 00155 00156 // We don't copy auto increment fields. 00157 $auto_inc_field = $record->_table->getAutoIncrementField(); 00158 if ( $auto_inc_field ){ 00159 $key = array_search($auto_inc_field, $copy_fields); 00160 if ( $key !== false ) unset($copy_fields[$key]); 00161 } 00162 00163 // Now we can build the query. 00164 $sql = array(); 00165 $sql[] = "insert into `".$record->_table->tablename."`"; 00166 $sql[] = "(`".implode('`,`', $copy_fields)."`)"; 00167 00168 $copy_values = array(); 00169 foreach ($copy_fields as $key=>$val){ 00170 if ( isset($vals[$val]) ){ 00171 $copy_values[$key] = "'".addslashes($dummy->getSerializedValue($val))."' as `$val`"; 00172 } else { 00173 $copy_values[$key] = "`".$val."`"; 00174 } 00175 } 00176 $sql[] = "select ".implode(', ', $copy_values)." from `".$record->_table->tablename."`"; 00177 $qb = new Dataface_QueryBuilder($record->_table->tablename); 00178 00179 $keys = array_keys($record->_table->keys()); 00180 $q = array(); 00181 foreach ($keys as $key_fieldname){ 00182 $q[$key_fieldname] = $record->strval($key_fieldname); 00183 } 00184 $where = $qb->_where($q); 00185 $where = $qb->_secure($where); 00186 $sql[] = $where; 00187 return implode(' ', $sql); 00188 00189 00190 } 00191 }