Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
asset_management.inc
1 <?php
17 require_once SQ_FUDGE_PATH.'/db_extras/db_extras.inc';
18 
33 {
34 
38  var $_pm;
39 
43  var $_am;
44 
48  var $_db;
49 
67  var $vars = Array();
68 
81  var $components = Array();
82 
83 
88  function Asset_Management(&$pm)
89  {
90 
91  if ((get_class($this) !== __CLASS__) && (get_parent_class($this) !== __CLASS__)) {
92  trigger_localised_error('SYS0274', E_USER_ERROR, get_class($this));
93  }
94 
95 
96  $this->_pm = $pm;
97  $this->_am = $GLOBALS['SQ_SYSTEM']->am;
98  $this->_db = MatrixDAL::getDb();
99 
100  }//end constructor
101 
102 
113  function getAssetType()
114  {
115  $class = get_class($this);
116  return strtolower(substr($class, 0, strlen($class) - 11));
117 
118  }//end getAssetType()
119 
120 
127  function update()
128  {
129  $type_code = $this->getAssetType();
130 
131  // OK, first thing we are going to do is check that the parent type of this asset is the same between the
132  // asset.xml, actual asset class and the edit fns class
133 
134  $asset_dir = SQ_SYSTEM_ROOT.'/'.$this->_pm->getTypeInfo($type_code,'dir');
135  require_once $asset_dir.'/'.$type_code.'.inc';
136  require_once $asset_dir.'/'.$type_code.'_edit_fns.inc';
137 
138  $asset_xml_parent_type = $this->_pm->getTypeInfo($type_code, 'parent_type');
139  $asset_parent_type = strtolower(get_parent_class($type_code));
140  $asset_edit_fns_parent_type = preg_replace('/_edit_fns$/', '', strtolower(get_parent_class($type_code.'_edit_fns')));
141 
142  if (($asset_xml_parent_type != $asset_parent_type) || ($asset_xml_parent_type != $asset_edit_fns_parent_type)) {
143  trigger_localised_error('SYS0254', E_USER_WARNING, $type_code, $type_code, $type_code);
144  return false;
145  }
146 
147  // if the parent asset type hasn't been installed, abort
148  if ($asset_xml_parent_type != 'asset' && !$this->_am->installed($asset_xml_parent_type)) {
149  trigger_localised_error('SYS0253', E_USER_WARNING, $type_code, $asset_xml_parent_type);
150  return false;
151  }
152 
153  // if the asset manager knows about it - it is installed, so upgrade...
154  if ($this->_am->installed($type_code)) {
155  if (!$this->_upgrade($this->_am->getTypeInfo($type_code, 'version'))) {
156  return false;
157  }
158  } else {
159  if (!$this->_install()) return false;
160  }
161 
162  $this->_installDALQueries();
163 
164  if (!$this->_updateFiles()) return false;
165 
166  // save a copy of an icon we can use to represent this asset
167  // if no icon is directly available, the parents icon will be used
168  $from_icon_path = SQ_SYSTEM_ROOT.'/'.$this->_pm->getTypeInfo($type_code,'dir').'/icon.png';
169  $to_icon_path = SQ_DATA_PATH.'/public/asset_types/'.$type_code.'/icon.png';
170  if (!is_file($from_icon_path)) {
171  // copy the icon from our parent
172  $parent_type = $this->_pm->getTypeInfo($type_code, 'parent_type');
173  if ($parent_type == 'asset') {
174  // we are a top level asset so we need to copy our icon from the include dir
175  $from_icon_path = SQ_INCLUDE_PATH.'/asset_edit/icon.png';
176  } else {
177  // our parent should already have gone through all this and have
178  // an icon we can borrow
179  $from_icon_path = SQ_DATA_PATH.'/public/asset_types/'.$parent_type.'/icon.png';
180  }
181  }
182 
183  if (!is_file($from_icon_path)) {
184  trigger_localised_error('CORE0068', E_USER_WARNING, $type_code);
185  } else {
186  if (!copy_file($from_icon_path, $to_icon_path)) {
187  return false;
188  }
189  }
190 
191  return true;
192 
193  }//end update()
194 
195 
202  function _updateFiles()
203  {
204  // get a list of files to copy
205  $file_list = $this->_getFileList();
206  if (empty($file_list)) return true;
207 
208  require_once SQ_FUDGE_PATH.'/general/file_system.inc';
209 
210  $to_dir_path = SQ_DATA_PATH.'/public/asset_types/'.$this->getAssetType();
211  $from_dir_path = SQ_SYSTEM_ROOT.'/'.$this->_pm->getTypeInfo($this->getAssetType(),'dir');
212 
213  // create the directory to store these files if it doesnt exist
214  // NOTE: The create_direcotyr function of file_system.inc handles this for us
215  create_directory($to_dir_path);
216 
217  // for each file, copy it over
218  for (reset($file_list); null !== ($k = key($file_list)); next($file_list)) {
219  $file = $file_list[$k];
220  $from = $from_dir_path.'/'.$file;
221  $to = $to_dir_path.'/'.$file;
222 
223  // the copy_file function of file_system.inc will create the
224  // directory strucutre before copying
225  if (!copy_file($from, $to)) return false;
226  }
227 
228  return true;
229 
230  }//end _updateFiles()
231 
232 
239  function _install()
240  {
241  $type_code = $this->getAssetType();
242 
243  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
244  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
245 
246  // get how deep we are in the heirarchy
247  $level = count($this->_pm->getTypeAncestors($type_code));
248  $info = $this->_pm->getTypeInfo($type_code);
249 
250  $db = MatrixDAL::getDb();
251 
252  $sql = 'INSERT INTO sq_ast_typ
253  (type_code, version, name, description, instantiable, allowed_access, parent_type, lvl, dir, customisation)
254  VALUES
255  (:type_code, :version, :name, :description, :instantiable, :allowed_access, :parent_type, :lvl, :dir, :customisation)';
256 
257  try {
258  $query = MatrixDAL::preparePdoQuery($sql);
259  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
260  MatrixDAL::bindValueToPdo($query, 'version', $info['version'], PDO::PARAM_STR);
261  MatrixDAL::bindValueToPdo($query, 'name', $info['name'], PDO::PARAM_STR);
262  MatrixDAL::bindValueToPdo($query, 'description', $info['description'], PDO::PARAM_STR);
263  MatrixDAL::bindValueToPdo($query, 'instantiable', $info['instantiable'], PDO::PARAM_STR);
264  MatrixDAL::bindValueToPdo($query, 'allowed_access', $info['allowed_access'], PDO::PARAM_STR);
265  MatrixDAL::bindValueToPdo($query, 'parent_type', $info['parent_type'], PDO::PARAM_STR);
266  MatrixDAL::bindValueToPdo($query, 'lvl', $level, PDO::PARAM_INT);
267  MatrixDAL::bindValueToPdo($query, 'dir', $info['dir'], PDO::PARAM_STR);
268  MatrixDAL::bindValueToPdo($query, 'customisation', 0, PDO::PARAM_INT);
269  $result = MatrixDAL::execPdoQuery($query);
270  } catch (DALException $e) {
271  throw new Exception('Unable to add information for new asset type "'.$type_code.'" due to database error: '.$e->getMessage());
272  }
273 
274  // now inform the asset manager that this asset is available for use
275  $this->_am->refreshAssetType($type_code);
276 
277  // now add the attributes
278  $all_vars = $this->_getAllVars();
279  for (reset($all_vars); null !== ($k = key($all_vars)); next($all_vars)) {
280  $name = $all_vars[$k];
281  if (!$this->_addAttribute($name)) return false;
282  }
283 
284  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
285  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
286 
287  return true;
288 
289  }//end _install()
290 
291 
300  function _upgrade($current_version)
301  {
302  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
303  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
304 
305  $db = MatrixDAL::getDb();
306  $asset_type = $this->getAssetType();
307 
308  // get how deep we are in the heirarchy
309  $level = count($this->_pm->getTypeAncestors($asset_type));
310  $info = $this->_pm->getTypeInfo($asset_type);
311 
312  $sql = 'UPDATE sq_ast_typ
313  SET
314  version = :version,
315  name = :name,
316  description = :description,
317  instantiable = :instantiable,
318  allowed_access = :allowed_access,
319  parent_type = :parent_type,
320  lvl = :lvl,
321  dir = :dir
322  WHERE
323  type_code = :type_code';
324 
325  try {
326  $query = MatrixDAL::preparePdoQuery($sql);
327  MatrixDAL::bindValueToPdo($query, 'version', $info['version'], PDO::PARAM_STR);
328  MatrixDAL::bindValueToPdo($query, 'name', $info['name'], PDO::PARAM_STR);
329  MatrixDAL::bindValueToPdo($query, 'description', $info['description'], PDO::PARAM_STR);
330  MatrixDAL::bindValueToPdo($query, 'instantiable', $info['instantiable'], PDO::PARAM_STR);
331  MatrixDAL::bindValueToPdo($query, 'allowed_access', $info['allowed_access'], PDO::PARAM_STR);
332  MatrixDAL::bindValueToPdo($query, 'parent_type', $info['parent_type'], PDO::PARAM_STR);
333  MatrixDAL::bindValueToPdo($query, 'lvl', $level, PDO::PARAM_INT);
334  MatrixDAL::bindValueToPdo($query, 'dir', $info['dir'], PDO::PARAM_STR);
335  MatrixDAL::bindValueToPdo($query, 'type_code', $asset_type, PDO::PARAM_STR);
336  DAL::execPdoQuery($query);
337  } catch (Exception $e) {
338  throw new Exception('Unable to update type details while upgrading asset type "'.$asset_type.'" to version '.$current_version.', due to database error: ', $e->getMessage());
339  }
340 
341  // now inform the asset manager that this asset is available for use
342  $this->_am->refreshAssetType($asset_type);
343 
344  // now update the attributes
345  $sql = 'SELECT name
346  FROM sq_ast_attr
347  WHERE type_code = :type_code';
348 
349  try {
350  $query = MatrixDAL::preparePdoQuery($sql);
351  MatrixDAL::bindValueToPdo($query, 'type_code', $asset_type);
352  $current_vars = MatrixDAL::executePdoAssoc($query, 0);
353  } catch (Exception $e) {
354  throw new Exception('Unable to get current attributes while upgrading asset type "'.$asset_type.'" to version '.$current_version.', due to database error: ', $e->getMessage());
355  }
356 
357  $all_vars = $this->_getAllVars();
358 
359  foreach ($all_vars as $name) {
360  // if we already have this attribute installed, then let's update it
361  if (in_array($name, $current_vars)) {
362  if (!$this->_updateAttribute($name, $current_version)) {
363  return false;
364  }
365  } else {
366  if (!$this->_addAttribute($name)) return FALSE;
367  }
368  }//end for
369 
370  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
371  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
372 
373  return true;
374 
375  }//end _upgrade()
376 
377 
385  function _getAllVars()
386  {
387  $db = MatrixDAL::getDb();
388 
389  $type_code = $this->getAssetType();
390  $sql = 'SELECT DISTINCT atr.name
391  FROM sq_ast_typ_inhd i, sq_ast_attr atr
392  WHERE i.type_code = :type_code_1
393  AND i.inhd_type_code <> :type_code_2
394  AND i.inhd_type_code = atr.type_code';
395 
396  try {
397  $query = MatrixDAL::preparePdoQuery($sql);
398  MatrixDAL::bindValueToPdo($query, 'type_code_1', $type_code, PDO::PARAM_STR);
399  MatrixDAL::bindValueToPdo($query, 'type_code_2', $type_code, PDO::PARAM_STR);
400  $parent_vars = MatrixDAL::executePdoAssoc($query, 0);
401  } catch (Exception $e) {
402  throw new Exception('Unable to get attribute list for asset type "'.$asset_type.'" due to database error: '.$e->getMessage());
403  }
404 
405  // array_values() to get proper indexed array
406  $vars = array_values(array_unique(array_merge($parent_vars, array_keys($this->vars))));
407  return $vars;
408 
409  }//end _getAllVars()
410 
411 
418  function _getFileList()
419  {
420  return Array();
421 
422  }//end _getFileList()
423 
424 
431  function getEventList()
432  {
433  return Array();
434 
435  }//end getEventList()
436 
437 
446  function _addAttribute($name)
447  {
448  $type_code = $this->getAssetType();
449 
450  $attr_info = Array();
451 
452  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
453  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
454  $db = MatrixDAL::getDb();
455 
456  // See if any other our parents have an attribute with this name
457  $sql = 'SELECT COUNT(*) as count, MIN(at.lvl) as min, MAX(at.lvl) as max
458  FROM sq_ast_typ_inhd i, sq_ast_attr atr, sq_ast_typ at
459  WHERE i.type_code = :type_code
460  AND i.inhd_type_code <> :inhd_type_code
461  AND i.inhd_type_code = atr.type_code
462  AND atr.name = :name
463  AND atr.type_code = at.type_code';
464 
465  try {
466  $query = MatrixDAL::preparePdoQuery($sql);
467  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
468  MatrixDAL::bindValueToPdo($query, 'inhd_type_code', $type_code, PDO::PARAM_STR); // not needed for baked DAL?
469  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
470  $result = MatrixDAL::executePdoAll($query);
471  $parent_info = $result[0];
472  unset($result);
473  } catch (Exception $e) {
474  echo 'Unable to search for matching parent attribute while adding attribute "'.$name.'" to asset type "'.$type_code.'", due to database error: '.$e->getMessage();
475  throw new Exception('Unable to search for matching parent attribute while adding attribute "'.$name.'" to asset type "'.$type_code.'", due to database error: '.$e->getMessage());
476  }
477 
478  // if none of our parent types have an attribute with this name
479  if (empty($parent_info['count'])) {
480 
481  // check children to see if any of them have an attribute with this name
482  $sql = 'SELECT a.type_code, a.type, a.attrid
483  FROM sq_ast_typ_inhd i, sq_ast_attr a
484  WHERE i.inhd_type_code = :type_code
485  AND i.type_code <> :inhd_type_code
486  AND i.type_code = a.type_code
487  AND a.name = :name';
488  try {
489  $query = MatrixDAL::preparePdoQuery($sql);
490  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
491  MatrixDAL::bindValueToPdo($query, 'inhd_type_code', $type_code, PDO::PARAM_STR); // not needed for baked DAL?
492  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
493  $children = MatrixDAL::executePdoAll($query);
494  } catch (Exception $e) {
495  throw new Exception('Unable to search for matching child attribute while adding attribute "'.$name.'" to asset type "'.$type_code.'", due to database error: '.$e->getMessage());
496  }
497 
498  // if children have this attribute, we'll try to change the owner type code to us
499  if (!empty($children)) {
500  echo '*** Attribute "'.$name.'" is being moved from child types:'."\n";
501  foreach ($children as $child) {
502  // if attribute types don't match - cannot upgrade - fail
503  if ($child['type'] != $this->vars[$name]['type']) {
504  trigger_localised_error('SYS0233', E_USER_WARNING, $name, $type_code, implode('","', $children));
505  return false;
506  }
507 
508  echo '* '.$child['type_code']."\n";
509  $temp_attr_ids[] = MatrixDAL::quote($child['attrid']);
510  }
511  $temp_attr_ids = implode(', ', $temp_attr_ids);
512 
513  // now, let's mark the attribute as being owned by this asset type
514  $sql = 'UPDATE sq_ast_attr
515  SET owning_type_code = :type_code
516  WHERE attrid IN ('.$temp_attr_ids.')';
517  try {
518  $query = MatrixDAL::preparePdoQuery($sql);
519  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
520  DAL::execPdoQuery($query);
521  } catch (Exception $e) {
522  throw new Exception('Unable to update attribute\'s owning type while adding attribute "'.$name.'" to asset type "'.$type_code.'", due to database error: '.$e->getMessage());
523  }
524 
525  echo '*** Done'."\n\n";
526 
527  }
528 
529  $attr_info['owning_type_code'] = $type_code;
530  $attr_info['type'] = $this->vars[$name]['type'];
531  $attr_info['default_type_code'] = $type_code;
532  $attr_info['default_val'] = $this->vars[$name]['default'];
533  $attr_info['uniq'] = empty($this->vars[$name]['uniq']) ? 0 : 1;
534  $attr_info['is_admin'] = isset($this->vars[$name]['is_admin']) ? (int) $this->vars[$name]['is_admin'] : 1;
535  $attr_info['is_contextable'] = isset($this->vars[$name]['is_contextable']) ? (int) $this->vars[$name]['is_contextable'] : 0;
536  $attr_info['parameters_type_code'] = $type_code;
537 
538  if (isset($this->vars[$name]['parameters'])) {
539  $attr_info['parameters'] = $this->vars[$name]['parameters'];
540  } else {
541  $attr_info['parameters'] = Array();
542  }
543 
544  $attr_info['description'] = empty($this->vars[$name]['description']) ? '' : $this->vars[$name]['description'];
545 
546 
547  // else one of our parents has defined the an attribute of this type before
548  // so we are really just overriding the default value for this asset type
549  } else {
550 
551  // OK, what's happening is that the asset type that is represented by the min level
552  // is the owner of the attribute, so from there we get all the attribute information
553  // except for the default value, because this might have been overridden by an asset type
554  // further down the line, this is where the max level come in. The Max Level is really our parent
555  // asset type and from here we get the current default value and the what that default value
556  // was set by (the default_type_code). From these values we can se-up the attribute correctly
557 
558  // Find the parents with an attribute of this name
559  $sql = 'SELECT atr.type_code, atr.owning_type_code, atr.type, atr.uniq, atr.parameters_val,
560  atr.parameters_type_code, atr.default_type_code, atr.default_val, atr.description, atr.is_admin, atr.is_contextable
561  FROM sq_ast_typ_inhd i, sq_ast_attr atr, sq_ast_typ at
562  WHERE i.type_code = :type_code
563  AND i.inhd_type_code <> :inhd_type_code
564  AND i.inhd_type_code = atr.type_code
565  AND atr.name = :name
566  AND atr.type_code = at.type_code
567  AND at.lvl = ';
568 
569  $min_sql = $sql.':min';
570 
571  try {
572  $query = MatrixDAL::preparePdoQuery($min_sql);
573  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
574  MatrixDAL::bindValueToPdo($query, 'inhd_type_code', $type_code, PDO::PARAM_STR); // not needed for baked DAL?
575  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
576  MatrixDAL::bindValueToPdo($query, 'min', $parent_info['min'], PDO::PARAM_INT);
577  $result = MatrixDAL::executePdoAll($query);
578  $attr_owner = $result[0];
579  unset($result);
580  } catch (Exception $e) {
581  throw new Exception('Unable to search for matching parent attribute while adding attribute "'.$name.'" to asset type "'.$type_code.'", due to database error: '.$e->getMessage());
582  }
583 
584  $attr_info['owning_type_code'] = $attr_owner['owning_type_code'];
585  $attr_info['type'] = $attr_owner['type'];
586  $attr_info['uniq'] = $attr_owner['uniq'];
587  $attr_info['is_admin'] = (int) $attr_owner['is_admin'];
588  $attr_info['is_contextable'] = (int) $attr_owner['is_contextable'];
589  $attr_info['description'] = $attr_owner['description'];
590 
591  // if we have set our own default value, then we are overriding the default
592  if (isset($this->vars[$name]['default'])) {
593  $attr_info['default_type_code'] = $type_code;
594  $attr_info['default_val'] = $this->vars[$name]['default'];
595  } else {
596  // else we want to inherit the default value
597  $max_sql = $sql.':max';
598  try {
599  $query = MatrixDAL::preparePdoQuery($max_sql);
600  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
601  MatrixDAL::bindValueToPdo($query, 'inhd_type_code', $type_code, PDO::PARAM_STR); // not needed for baked DAL?
602  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
603  MatrixDAL::bindValueToPdo($query, 'max', $parent_info['max'], PDO::PARAM_INT);
604  $result = MatrixDAL::executePdoAll($query);
605  $attr_default = $result[0];
606  unset($result);
607  } catch (Exception $e) {
608  throw new Exception('Unable to search for matching parent attribute while adding attribute "'.$name.'" to asset type "'.$type_code.'", due to database error: '.$e->getMessage());
609  }
610 
611  $attr_info['default_type_code'] = $attr_default['default_type_code'];
612  $attr_info['default_val'] = $attr_default['default_val'];
613  }
614 
615  // if we have set our own parameters value, then we are overriding the default
616  if (isset($this->vars[$name]['parameters'])) {
617  $attr_info['parameters_type_code'] = $type_code;
618  $attr_info['parameters'] = $this->vars[$name]['parameters'];
619  } else {
620  // else we want to inherit the default value
621  $max_sql = $sql.':max';
622  try {
623  $query = MatrixDAL::preparePdoQuery($max_sql);
624  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
625  MatrixDAL::bindValueToPdo($query, 'inhd_type_code', $type_code, PDO::PARAM_STR); // not needed for baked DAL?
626  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
627  MatrixDAL::bindValueToPdo($query, 'max', $parent_info['max'], PDO::PARAM_INT);
628  $result = MatrixDAL::executePdoAll($query);
629  $attr_default = $result[0];
630  unset($result);
631  } catch (Exception $e) {
632  throw new Exception('Unable to search for matching parent attribute while adding attribute "'.$name.'" to asset type "'.$type_code.'", due to database error: '.$e->getMessage());
633  }
634 
635  $attr_info['parameters_type_code'] = $attr_default['parameters_type_code'];
636  $attr_info['parameters'] = unserialize($attr_default['parameters_val']);
637  }
638 
639  }//end if parents using this name
640 
641  // make sure this is a valid attribute type
642  if (!$this->_am->validAttributeType($attr_info['type'])) {
643  trigger_localised_error('SYS0096', E_USER_WARNING, $attr_info['type'], $this->getAssetType());
644  return false;
645  }//end if
646 
647  if (!$this->_validateAttributeDefault($attr_info['default_val'], $attr_info['type'], $attr_info['parameters'])) {
648  trigger_localised_error('SYS0130', E_USER_WARNING, $name, $this->getAssetType());
649  return false;
650  }
651 
652  // OK, all seems fine, let's add the attribute
653  try {
654  $bind_vars = Array(
655  'type_code' => $type_code,
656  'owning_type_code' => $attr_info['owning_type_code'],
657  'name' => $name,
658  'type' => $attr_info['type'],
659  'uniq' => $attr_info['uniq'],
660  'parameters_type_code' => $attr_info['parameters_type_code'],
661  'default_type_code' => $attr_info['default_type_code'],
662  'default_val' => $attr_info['default_val'],
663  'parameters_val' => serialize($attr_info['parameters']),
664  'is_admin' => $attr_info['is_admin'] ? 1 : 0,
665  'is_contextable' => $attr_info['is_contextable'] ? 1 : 0,
666  'description' => $attr_info['description'],
667  );
668  MatrixDAL::executeQuery('core', 'insertAssetAttribute', $bind_vars);
669  } catch (DALException $e) {
670  throw new Exception('Unable to add attribute "'.$name.'" to asset type "'.$type_code.'", due to database error: '.$e->getMessage());
671  }
672 
673  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
674  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
675 
676  return TRUE;
677 
678  }//end _addAttribute()
679 
680 
692  function _deleteAttribute($name)
693  {
694  $type_code = $this->getAssetType();
695 
696  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
697  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
698 
699  // find the attributeid
700  $sql = 'SELECT attrid FROM sq_ast_attr WHERE owning_type_code = :type_code AND name = :name';
701  $query = MatrixDAL::preparePdoQuery($sql);
702  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code);
703  MatrixDAL::bindValueToPdo($query, 'name', $name);
704  $attributeid = MatrixDAL::executePdoOne($query);
705 
706  if (is_null($attributeid)) {
707  trigger_localised_error('SYS0050', E_USER_WARNING, $typecode, $name);
708  return false;
709  }
710 
711  // delete the attribute values
712  $sql = 'DELETE FROM sq_ast_attr_val WHERE attrid = :attrid';
713  $query = MatrixDAL::preparePdoQuery($sql);
714  MatrixDAL::bindValueToPdo($query, 'attrid', $attributeid);
715  MatrixDAL::execPdoQuery($query);
716 
717  // delete the attribute
718  $sql = 'DELETE FROM sq_ast_attr WHERE attrid = :attrid';
719  $query = MatrixDAL::preparePdoQuery($sql);
720  MatrixDAL::bindValueToPdo($query, 'attrid', $attributeid);
721  MatrixDAL::execPdoQuery($query);
722 
723  // get rid of it in our array
724  if (isset($this->vars[$name])) {
725  unset($this->vars[$name]);
726  }
727 
728  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
729  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
730 
731  return true;
732 
733  }//end _deleteAttribute()
734 
735 
745  function _updateAttribute($name, $current_version)
746  {
747  $type_code = $this->getAssetType();
748 
749  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
750  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
751 
752  // if they have defined an update fn for this, then we don't need to do anything
753  if (!empty($this->vars[$name]['update_fn'])) {
754  $fn = $this->vars[$name]['update_fn'];
755  if (!$this->$fn($current_version)) return false;
756 
757  } else {
758  // load this attribute info
759  $sql = 'SELECT
760  attrid, type_code, owning_type_code, name, type, uniq, parameters_val, parameters_type_code, default_type_code, default_val
761  FROM
762  sq_ast_attr
763  WHERE
764  type_code = :type_code
765  AND name = :name';
766 
767  try {
768  $query = MatrixDAL::preparePdoQuery($sql);
769  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
770  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
771  $result = MatrixDAL::executePdoAll($query);
772  $curr_attr = $result[0];
773  unset($result);
774  } catch (Exception $e) {
775  throw new Exception('Unable to load attribute info for attribute "'.$name.'" of asset type "'.$type_code.'", due to database error: '.$e->getMessage());
776  }
777 
778  // determine the parent of the asset being upgraded.
779  if (!isset($this->_tmp['parent_asset_type'])) {
780  $parents = $this->_pm->getTypeAncestors($type_code);
781  $this->_tmp['parent_asset_type'] = array_shift($parents);
782  }
783  $parent = $this->_tmp['parent_asset_type'];
784 
785  // see if there is a parent type with the same name
786  $sql = 'SELECT attrid, owning_type_code
787  FROM sq_ast_attr
788  WHERE type_code = :type_code
789  AND name = :name';
790 
791  try {
792  $query = MatrixDAL::preparePdoQuery($sql);
793  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
794  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
795  $result = MatrixDAL::executePdoAll($query);
796  $parent_check_data = $result[0];
797  unset($result);
798  } catch (Exception $e) {
799  throw new Exception('Unable to load parent type attribute info for attribute "'.$name.'" of asset type "'.$type_code.'", due to database error: '.$e->getMessage());
800  }
801 
802  // fix owning type code if:
803  // - there is a parent with this attribute and our owning_type_code is not the same as theirs
804  // - there is NO parent with this attribute and our owning_type_code is not the same as OUR type_code
805  $owning_type_code = null;
806  if (!empty($parent_check_data) && ($parent_check_data['owning_type_code'] != $curr_attr['owning_type_code'])) {
807  $owning_type_code = $parent_check_data['owning_type_code'];
808  } else if (empty($parent_check_data) && ($curr_attr['owning_type_code'] != $type_code)) {
809  $owning_type_code = $type_code;
810  }
811 
812  if (!empty($owning_type_code)) {
813  echo '* Fixing invalid owner definition of attribute "'.$name.'"'."\n";
814 
815  $sql = 'UPDATE sq_ast_attr
816  SET owning_type_code = :owning_type_code
817  WHERE type_code = :type_code AND name = :name';
818 
819  try {
820  $query = MatrixDAL::preparePdoQuery($sql);
821  MatrixDAL::bindValueToPdo($query, 'owning_type_code', $owning_type_code, PDO::PARAM_STR);
822  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
823  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
824  DAL::execPdoQuery($query);
825  } catch (Exception $e) {
826  throw new Exception('Unable to update owning type code info for attribute "'.$name.'" of asset type "'.$type_code.'", due to database error: '.$e->getMessage());
827  }
828 
829  $curr_attr['owning_type_code'] = $owning_type_code;
830  }
831  // end fixing owning type code
832 
833  // if this asset type owns this var, we can change it how ever we want
834  if ($curr_attr['owning_type_code'] == $type_code) {
835  if (!$this->_updateOwnedAttribute($name, $curr_attr)) {
836  return false;
837  }
838 
839  // if we have set the params or default value in the vars
840  } else {
841 
842  // we have removed our customisation of parameters
843  // so get our parent's parameters and set to that
844  $sql = 'SELECT owning_type_code, parameters_type_code, parameters_val, default_type_code, default_val
845  FROM sq_ast_attr
846  WHERE type_code = :type_code
847  AND name = :name';
848 
849  try {
850  $query = MatrixDAL::preparePdoQuery($sql);
851  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
852  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
853  $result = MatrixDAL::executePdoAll($query);
854  $parent_attr = $result[0];
855  unset($result);
856  } catch (Exception $e) {
857  throw new Exception('Unable to load parent type attribute info for attribute "'.$name.'" of asset type "'.$type_code.'", due to database error: '.$e->getMessage());
858  }
859 
860 
862 
863  // if this asset type has overidden, use it's values
864  if (isset($this->vars[$name]['parameters'])) {
865  $parameters_value = serialize($this->vars[$name]['parameters']);
866  $parameters_type_code = $type_code;
867 
868  // otherwise reset to inherit from parents
869  } else if (!empty($parent_attr)) {
870  $parameters_value = $parent_attr['parameters_val'];
871  $parameters_type_code = $parent_attr['parameters_type_code'];
872 
873  // no parent ? set to blank for ourselves
874  } else {
875  $parameters_value = serialize(Array());
876  $parameters_type_code = $type_code;
877  }
878 
879  if ($parameters_type_code != $curr_attr['parameters_type_code'] || $parameters_value != $curr_attr['parameters_val']) {
880  if (!$this->_updateCustomAttribute($curr_attr['attrid'], $name, 'parameters', $curr_attr['parameters_type_code'], $parameters_type_code, $parameters_value)) {
881  return false;
882  }
883  }
884 
885 
887 
888  // if this asset type has overidden, use it's values
889  if (isset($this->vars[$name]['default'])) {
890  $default_value = $this->vars[$name]['default'];
891  $default_type_code = $type_code;
892 
893  $parameters = unserialize($parameters_value);
894  if (!$this->_validateAttributeDefault($default_value, $curr_attr['type'], $parameters)) {
895  trigger_localised_error('SYS0130', E_USER_WARNING, $name, $this->getAssetType());
896  return false;
897  }
898 
899  // otherwise reset to inherit from parents
900  } else if (!empty($parent_attr)) {
901  $default_value = $parent_attr['default_val'];
902  $default_type_code = $parent_attr['default_type_code'];
903 
904  // no parent ? set to blank for ourselves
905  } else {
906  $default_value = '';
907  $default_type_code = $type_code;
908  }
909 
910  if ($default_type_code != $curr_attr['default_type_code'] || $default_value != $curr_attr['default_val']) {
911  if (!$this->_updateCustomAttribute($curr_attr['attrid'], $name, 'default', $curr_attr['default_type_code'], $default_type_code, $default_value)) {
912  return false;
913  }
914  }
915 
916  } // end if
917 
918  }//end if
919 
920  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
921  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
922 
923  return true;
924 
925  }//end _updateAttribute()
926 
927 
937  function _updateOwnedAttribute($name, $curr_attr)
938  {
939  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
940  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
941  $db = MatrixDAL::getDb();
942 
943  $type_code = $this->getAssetType();
944 
945  // make sure this is a valid attribute type
946  if (!$this->_am->validAttributeType($this->vars[$name]['type'])) {
947  trigger_localised_error('SYS0096', E_USER_WARNING, $this->vars[$name]['type'], $this->getAssetType());
948  return false;
949  }//end if
950 
951  $description = empty($this->vars[$name]['description']) ? '' : $this->vars[$name]['description'];
952 
953  // update all the attributes that we own
954  $sql = 'UPDATE sq_ast_attr
955  SET type = :type,
956  uniq = :uniq,
957  is_admin = :is_admin,
958  is_contextable = :is_contextable,
959  description = :description
960  WHERE owning_type_code = :owning_type_code
961  AND name = :name';
962 
963 
964  try {
965  $query = MatrixDAL::preparePdoQuery($sql);
966  MatrixDAL::bindValueToPdo($query, 'type', $this->vars[$name]['type'], PDO::PARAM_STR);
967  MatrixDAL::bindValueToPdo($query, 'uniq', empty($this->vars[$name]['uniq']) ? 0 : 1, PDO::PARAM_INT);
968  MatrixDAL::bindValueToPdo($query, 'is_admin', isset($this->vars[$name]['is_admin']) ? (int) $this->vars[$name]['is_admin'] : 1, PDO::PARAM_INT);
969  MatrixDAL::bindValueToPdo($query, 'is_contextable', isset($this->vars[$name]['is_contextable']) ? (int) $this->vars[$name]['is_contextable'] : 0, PDO::PARAM_INT);
970  MatrixDAL::bindValueToPdo($query, 'description', $description, PDO::PARAM_STR);
971  MatrixDAL::bindValueToPdo($query, 'owning_type_code', $type_code, PDO::PARAM_STR);
972  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
973  DAL::execPdoQuery($query);
974  } catch (Exception $e) {
975  throw new Exception('Unable to update owned attribute info for attribute "'.$name.'" of asset type "'.$type_code.'", due to database error: '.$e->getMessage());
976  }
977 
978  if (!$this->_validateAttributeDefault($this->vars[$name]['default'], $this->vars[$name]['type'], (empty($this->vars[$name]['parameters']) ? Array() : $this->vars[$name]['parameters']))) {
979  trigger_localised_error('SYS0130', E_USER_WARNING, $name, $this->getAssetType());
980  return false;
981  }
982 
983  // update all the attributes that are still using our default
984  $sql = 'UPDATE sq_ast_attr
985  SET default_val = :val
986  WHERE default_type_code = :type_code
987  AND name = :name';
988 
989 
990  try {
991  $query = MatrixDAL::preparePdoQuery($sql);
992  MatrixDAL::bindValueToPdo($query, 'val', $this->vars[$name]['default'], PDO::PARAM_STR);
993  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
994  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
995  DAL::execPdoQuery($query);
996  } catch (Exception $e) {
997  throw new Exception('Unable to update attribute defaults for attribute "'.$name.'" of asset type "'.$type_code.'", due to database error: '.$e->getMessage());
998  }
999 
1000  if (!empty($this->vars[$name]['parameters'])) {
1001  // update all the attributes that are still using our parameters
1002  $sql = 'UPDATE sq_ast_attr
1003  SET parameters_val = :val
1004  WHERE parameters_type_code = :type_code
1005  AND name = :name';
1006 
1007  try {
1008  $query = MatrixDAL::preparePdoQuery($sql);
1009  MatrixDAL::bindValueToPdo($query, 'val', serialize($this->vars[$name]['parameters']), PDO::PARAM_STR);
1010  MatrixDAL::bindValueToPdo($query, 'type_code', $type_code, PDO::PARAM_STR);
1011  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
1012  DAL::execPdoQuery($query);
1013  } catch (Exception $e) {
1014  throw new Exception('Unable to update attribute parameter info for attribute "'.$name.'" of asset type "'.$type_code.'", due to database error: '.$e->getMessage());
1015  }
1016  }
1017 
1018  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
1019  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1020 
1021  return true;
1022 
1023  }//end _updateOwnedAttribute()
1024 
1025 
1036  function _updateCustomAttribute($attributeid, $name, $field, $old_type_code, $new_type_code, $new_value)
1037  {
1038  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
1039  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
1040  $db = MatrixDAL::getDb();
1041 
1042  // OK, the reason that we are setting the default type code for the attributes
1043  // is so that if this is the first time that we are setting the default value
1044  // then all the asset types below us that were inheriting the default value from the
1045  // the same asset type as we used to be will be converted to using our default value
1046  $sql = 'UPDATE sq_ast_attr
1047  SET '.$field.'_type_code = :new_type_code,
1048  '.$field.'_val = :value
1049  WHERE attrid = :attrid
1050  OR attrid IN (
1051  SELECT atr.attrid
1052  FROM sq_ast_typ_inhd i, sq_ast_attr atr
1053  WHERE i.inhd_type_code = :new_type_code_1
1054  AND i.type_code <> :new_type_code_2
1055  AND i.type_code = atr.type_code
1056  AND atr.'.$field.'_type_code = :old_type_code
1057  AND atr.name = :name
1058  )';
1059 
1060  try {
1061  $query = MatrixDAL::preparePdoQuery($sql);
1062  MatrixDAL::bindValueToPdo($query, 'new_type_code', $new_type_code, PDO::PARAM_STR);
1063  MatrixDAL::bindValueToPdo($query, 'new_type_code_1', $new_type_code, PDO::PARAM_STR);
1064  MatrixDAL::bindValueToPdo($query, 'new_type_code_2', $new_type_code, PDO::PARAM_STR);
1065  MatrixDAL::bindValueToPdo($query, 'old_type_code', $old_type_code, PDO::PARAM_STR);
1066  MatrixDAL::bindValueToPdo($query, 'name', $name, PDO::PARAM_STR);
1067  MatrixDAL::bindValueToPdo($query, 'value', $new_value, PDO::PARAM_STR);
1068  MatrixDAL::bindValueToPdo($query, 'attrid', $attributeid, PDO::PARAM_STR);
1069  DAL::execPdoQuery($query);
1070  } catch (Exception $e) {
1071  throw new Exception('Unable to update custom attribute value info for attribute "'.$name.'" of asset type "'.$type_code.'", due to database error: '.$e->getMessage());
1072  }
1073 
1074  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
1075  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1076 
1077  return true;
1078 
1079  }//end _updateCustomAttribute()
1080 
1081 
1094  function _validateAttributeDefault(&$default, $attr_type, $parameters)
1095  {
1096  // check that the default value is valid
1097  require_once SQ_ATTRIBUTES_PATH.'/'.$attr_type.'/'.$attr_type.'.inc';
1098  $class = 'Asset_Attribute_'.$attr_type;
1099  $attr = new $class();
1100  foreach ($parameters as $k => $v) {
1101  $attr->_params[$k] = $v;
1102  }
1103  return $attr->validateValue($default);
1104 
1105  }//end _validateAttributeDefault()
1106 
1107 
1118  function getAssetInfo($file)
1119  {
1120  // OK, now because this can be called without the need to have an instance of the class
1121  // we need to store our tmp stuff in a global array
1122  if (!isset($GLOBALS['SQ_ASSET_MANAGEMENT_ASSET_INFO'])) {
1123  $GLOBALS['SQ_ASSET_MANAGEMENT_ASSET_INFO'] = Array();
1124  }
1125 
1126  if (!isset($GLOBALS['SQ_ASSET_MANAGEMENT_ASSET_INFO'][$file])) {
1127 
1128  try {
1129  $info = new SimpleXMLElement($file, NULL, TRUE);
1130  } catch (Exception $e) {
1131  throw new Exception('Could not parse asset definition file "'.$file.'": '.$e->getMessage());
1132  }
1133 
1134  $GLOBALS['SQ_ASSET_MANAGEMENT_ASSET_INFO'][$file] = Array(
1135  'type_code' => strtolower((string)$info->type_code),
1136  'package' => (string)$info->package,
1137  'name' => (string)$info->name,
1138  'version' => (string)$info->version,
1139  'description' => (string)$info->description,
1140  'instantiable' => ((string)$info->instantiable === 'yes') ? 1 : 0,
1141  'allowed_access' => (string)$info->allowed_access,
1142  'parent_type' => (string)$info->parent_type,
1143  'flash_menu_path' => (isset($info->flash_menu_path)) ? (string)$info->flash_menu_path : '',
1144  );
1145 
1146  }//end if
1147 
1148  return $GLOBALS['SQ_ASSET_MANAGEMENT_ASSET_INFO'][$file];
1149 
1150  }//end getAssetInfo()
1151 
1152 
1160  {
1161  $name = $this->getAssetType();
1162  $old_path = ini_get('include_path');
1163  ini_set('include_path', SQ_LIB_PATH);
1164  require_once SQ_LIB_PATH.'/MatrixDAL/MatrixDALBaker.inc';
1165  $queries_found = MatrixDALBaker::addAssetTypeQueries($name);
1166  if ($queries_found) {
1168  }
1169  ini_set('include_path', $old_path);
1170 
1171  }//end _installDALQueries()
1172 
1173 
1174 }//end class
1175 
1176 ?>