Xataface  2.0alpha2
Xataface Application Framework
 All Data Structures Namespaces Files Functions Variables Groups Pages
CopyTool.php
Go to the documentation of this file.
1 <?php
2 
4  var $warnings;
5 
6  public static function &getInstance(){
7  static $instance = 0;
8  if ( !is_object($instance) ){
9  $instance = new Dataface_CopyTool();
10  }
11  return $instance;
12  }
13 
14 
15  function evaluate($expr, $fieldname, Dataface_Record $record){
16 
17  // Check the field type first. If this is a numeric field
18  // we evaluate with math
19  // If it is a string, we evaluate with string functions
20 
21  // Chop the leading '='
22  $expr = substr($expr,1);
23 
24  $table = $record->table();
25  if ( $table->isInt($fieldname) or $table->isFloat($fieldname) ){
26  // This field is a numeric field so we treat it like
27  // a numeric operation
28  $oldval = $record->val($fieldname);
29  if ( !$oldval ) $oldval = 0;
30  $expr = preg_replace('/\$\$/', $oldval, $expr);
31  if ( preg_match('/^[\+\-\*\/]/', $expr) ){
32  // If expression begins with an operation, we apply
33  // the old value as the first operand of this
34  // operation.
35  $expr = $oldval.$expr;
36  }
37 
38  if ( !preg_match('/^[0-9\.\*\+\/\-\^\(\) ]+$/', $expr) ){
39  throw new Exception("Invalid arithmetic expression.");
40  }
41  @eval('$expr='.$expr.';');
42  return $expr;
43 
44 
45  } else if ( $table->isDate($fieldname) ){
46 
47  // This field is a date field so we treat it like a
48  // date operation
49  $oldtime = strtotime($record->strval($fieldname));
50  return date($expr, $oldtime);
51 
52  } else {
53  // We assume it is a string
54  $oldval = $record->val($fieldname);
55  $expr = preg_replace('/\$\$/', $oldval, $expr);
56  return $expr;
57 
58  }
59 
60  }
61 
62  function copy($record, $vals=array(), $force=true){
63 
64  foreach ($vals as $k=>$v){
65  if ( strpos($v,'=') === 0 ){
66  $vals[$k] = $this->evaluate($v, $k, $record);
67  }
68  }
69 
70  $del = $record->_table->getDelegate();
71  if ( isset($del) and method_exists($del, 'beforeCopy') ){
72  $res = $del->beforeCopy($record, $vals);
73  if ( PEAR::isError($res) ){
74  return $res;
75  }
76  }
77  $this->warnings = array();
78  // Step 1: Load the record - it has been passed
79  // Step 2: build sql query to copy the record
80  $query = $this->buildCopyQuery($record, $vals, $force);
81  if ( PEAR::isError($query) ){
82  return $query;
83  }
84  $res = df_query($query);
85  if ( !$res ){
86  return PEAR::raiseError("Failed to copy record '".$record->getTitle()."' due to an SQL error:".mysql_error());
87  }
88  if ( PEAR::isError($res) ) return $res;
89 
90 
91  $ret = null;
92 
93  if ( $auto_field_id = $record->_table->getAutoIncrementField()) {
94  $insert_id = df_insert_id();
95  $copied =& df_get_record($record->_table->tablename, array($auto_field_id=>$insert_id));
96  $ret = $copied;
97  } else {
98  $ret = new Dataface_Record($record->_table->tablename, array_merge($record->vals(), $vals));
99  }
100 
101  if ( isset($del) and method_exists($del, 'afterCopy')){
102  $res = $del->afterCopy($record, $ret);
103  if ( PEAR::isError($res) ){
104  return $res;
105  }
106 
107  }
108  return $ret;
109 
110  }
111 
127  function buildCopyQuery($record,$vals=array(), $force=true){
128 
129  $dummy = new Dataface_Record($record->_table->tablename, $vals);
130  if ( !$record->checkPermission('view') || !$dummy->checkPermission('edit') ){
131  return Dataface_Error::permissionDenied("Failed to copy record '".$record->getTitle()."' because of insufficient permissions.");
132  }
133 
134  $copy_fields = array_keys($record->_table->fields());
135 
136  // Go through each field and see if we have copy permission.
137  // Copy permission is two-fold: 1- make sure the source is viewable
138  // 2- make sure the destination is editable.
139  $failed = false;
140  foreach ($copy_fields as $key=>$fieldname){
141  if ( !$record->checkPermission('view', array('field'=>$fieldname))
142  || !$dummy->checkPermission('edit', array('field'=>$fieldname)) ){
143  $this->warnings[] = Dataface_Error::permissionDenied("The field '$fieldname' could not be copied for record '".$record->getTitle()."' because of insufficient permissions.");
144  unset($copy_fields[$key]);
145  $failed = true;
146  }
147  }
148 
149 
150  // If we are not forcing completion, any failures will result in cancellation
151  // of the copy.
152  if ( !$force and $failed ){
153  return Dataface_Error::permissionDenied("Failed to copy the record '".$record->getTitle()."' due to insufficient permissions on one or more of the columns.");
154  }
155 
156  // We don't copy auto increment fields.
157  $auto_inc_field = $record->_table->getAutoIncrementField();
158  if ( $auto_inc_field ){
159  $key = array_search($auto_inc_field, $copy_fields);
160  if ( $key !== false ) unset($copy_fields[$key]);
161  }
162 
163  // Now we can build the query.
164  $sql = array();
165  $sql[] = "insert into `".$record->_table->tablename."`";
166  $sql[] = "(`".implode('`,`', $copy_fields)."`)";
167 
168  $copy_values = array();
169  foreach ($copy_fields as $key=>$val){
170  if ( isset($vals[$val]) ){
171  $copy_values[$key] = "'".addslashes($dummy->getSerializedValue($val))."' as `$val`";
172  } else {
173  $copy_values[$key] = "`".$val."`";
174  }
175  }
176  $sql[] = "select ".implode(', ', $copy_values)." from `".$record->_table->tablename."`";
177  $qb = new Dataface_QueryBuilder($record->_table->tablename);
178 
179  $keys = array_keys($record->_table->keys());
180  $q = array();
181  foreach ($keys as $key_fieldname){
182  $q[$key_fieldname] = $record->strval($key_fieldname);
183  }
184  $where = $qb->_where($q);
185  $where = $qb->_secure($where);
186  $sql[] = $where;
187  return implode(' ', $sql);
188 
189 
190  }
191 }