/** * * @param mixed $object * @param CollectionInterface $config * @return array */ public function getChildren($object, CollectionInterface $collection) { $config = $collection->getConfig(); if (empty($config['parentfield'])) { throw new \midcom_error('parentfield was not defined in config'); } $parentfield = $config['parentfield']; // if storage is not defined, we assume it's the same as object if (empty($config['storage'])) { $storage = get_class($object); } else { $storage = $config['storage']; } $reflector = new \midgard_reflection_property(\midcom_helper_reflector::resolve_baseclass($storage)); if (!$reflector->is_link($parentfield)) { throw new \midcom_error('could not determine storage class'); } $qb = call_user_func(array($storage, 'new_query_builder')); $qb->add_constraint($parentfield, '=', $object->id); // order the children by their score values $qb->add_order('score', 'ASC'); return $qb->execute(); }
/** * Resolve MgdSchema object from guid or miscellaneous extended object * * @param mixed &$object MgdSchema object, GUID or ID * @param string $class MgdSchema class for resolving ID * @return mixed MgdSchema object or false on failure */ public static function resolve_object(&$object, $class = null) { // Check the type of the requested parent switch (true) { case is_object($object): break; case mgd_is_guid($object): $object = midcom::get('dbfactory')->get_object_by_guid($object); break; case $class: $id = (int) $object; $object = new $class($id); // Bulletproof the attempt if (!$object->guid) { return false; } break; default: return false; } $object_class = midcom_helper_reflector::resolve_baseclass(get_class($object)); // This is an original MgdSchema class if ($object_class === get_class($object)) { return $object; } // Get the initial MgdSchema class $object = new $object_class($object->guid); return $object; }
/** * @dataProvider providerResolve_baseclass */ public function testResolve_baseclass($classname1, $result) { $this->assertEquals($result, midcom_helper_reflector::resolve_baseclass($classname1)); }
/** * Generates, loads and prepares the schema database. * * The operations are done on all available schemas within the DB. */ public function create($type, $include_fields) { if ($type != null) { $dba_type = $type; if (!midcom::get('dbclassloader')->is_midcom_db_object($type)) { $dba_type = midcom::get('dbclassloader')->get_midcom_class_name_for_mgdschema_object($type); } $dummy_object = new $dba_type(); $type_fields = $dummy_object->get_properties(); } else { $type = get_class($this->_object); if (!midcom::get('dbclassloader')->is_midcom_db_object($type)) { $this->_object = midcom::get('dbfactory')->convert_midgard_to_midcom($this->_object); } $type_fields = $this->_object->get_properties(); } if (empty($include_fields)) { $include_fields = null; } else { if (is_string($include_fields)) { $include_fields = array($include_fields); } } //This is an ugly little workaround for unittesting $template = midcom_helper_datamanager2_schema::load_database('file:/midgard/admin/asgard/config/schemadb_default.inc'); $empty_db = clone $template['object']; $this->_schemadb = array('object' => $empty_db); //workaround end $this->_reflector = new midgard_reflection_property(midcom_helper_reflector::resolve_baseclass($type)); // Iterate through object properties unset($type_fields['metadata']); if (!extension_loaded('midgard2')) { // Midgard1 returns properties is random order so we need to sort them heuristically usort($type_fields, array($this, 'sort_schema_fields')); } foreach ($type_fields as $key) { if (in_array($key, $this->_config->get('object_skip_fields'))) { continue; } // Skip the fields that aren't requested, if inclusion list has been defined if ($include_fields && !in_array($key, $include_fields)) { continue; } // Only hosts have lang field that we will actually display if ($key == 'lang' && !is_a($this->_object, 'midcom_db_host')) { continue; } // Skip topic symlink field because it is a special field not meant to be touched directly if ($key == 'symlink' && is_a($this->_object, 'midcom_db_topic')) { continue; } // Linked fields should use chooser if ($this->_reflector->is_link($key)) { $this->_add_linked_field($key); // Skip rest of processing continue; } $field_type = $this->_reflector->get_midgard_type($key); switch ($field_type) { case MGD_TYPE_GUID: case MGD_TYPE_STRING: if ($key == 'component' && is_a($this->_object, 'midcom_db_topic')) { $this->_add_component_dropdown($key); break; } // Special name handling, start by checking if given type is same as $this->_object and if not making a dummy copy (we're probably in creation mode then) if (midcom::get('dbfactory')->is_a($this->_object, $type)) { $name_obj = $this->_object; } else { $name_obj = new $type(); } if ($key === midcom_helper_reflector::get_name_property($name_obj)) { $this->_add_name_field($key, $name_obj); break; } unset($name_obj); // Special page treatment if ($key === 'info' && $type === 'midcom_db_page') { $this->_add_info_field_for_page($key); break; } if ($key === 'info' && $type === 'midcom_db_pageelement') { $this->_schemadb['object']->append_field($key, array('title' => $key, 'storage' => $key, 'type' => 'select', 'type_config' => array('options' => array('' => 'not inherited', 'inherit' => 'inherited')), 'widget' => 'select')); break; } $this->_schemadb['object']->append_field($key, array('title' => $key, 'storage' => $key, 'type' => 'text', 'widget' => 'text')); break; case MGD_TYPE_LONGTEXT: $this->_add_longtext_field($key, $type); break; case MGD_TYPE_INT: case MGD_TYPE_UINT: $this->_add_int_field($key); break; case MGD_TYPE_FLOAT: $this->_schemadb['object']->append_field($key, array('title' => $key, 'storage' => $key, 'type' => 'number', 'widget' => 'text')); break; case MGD_TYPE_BOOLEAN: $this->_schemadb['object']->append_field($key, array('title' => $key, 'storage' => $key, 'type' => 'boolean', 'widget' => 'checkbox')); break; case MGD_TYPE_TIMESTAMP: $this->_schemadb['object']->append_field($key, array('title' => $key, 'storage' => $key, 'type' => 'date', 'widget' => 'jsdate')); break; } } $this->_add_rcs_field(); if ($this->add_copy_fields) { $this->_add_copy_fields(); } return $this->_schemadb; }
/** * Copy handler * * @param mixed $handler_id The ID of the handler. * @param Array $args The argument list. * @param Array &$data The local request data. * @return boolean Indicating success. */ public function _handler_copy($handler_id, array $args, array &$data) { // Get the object that will be copied $this->_load_object($args[0]); midcom::get('auth')->require_user_do('midgard.admin.asgard:manage_objects', null, 'midgard_admin_asgard_plugin'); static $targets = array(); $mgdschema_class = midcom_helper_reflector::resolve_baseclass(get_class($this->_object)); // Get the target details if (in_array($mgdschema_class, $targets)) { $target = $targets[$mgdschema_class]; } else { $target = midcom_helper_reflector_copy::get_target_properties($this->_object); } // Load the schemadb for searching the parent object $this->_load_schemadb($target['class'], $target['parent'], true); // Change the name for the parent field $this->_schemadb['object']->fields[$target['parent']]['title'] = $this->_l10n->get('choose the target'); // Load the nullstorage controller $this->_controller = midcom_helper_datamanager2_controller::create('nullstorage'); $this->_controller->schemadb =& $this->_schemadb; if (!$this->_controller->initialize()) { throw new midcom_error('Failed to initialize the controller'); } $this->_prepare_request_data(); // Process the form switch ($this->_controller->process_form()) { case 'save': $new_object = $this->_process_copy($target); // Relocate to the newly created object return new midcom_response_relocate("__mfa/asgard/object/{$this->_request_data['default_mode']}/{$new_object->guid}/"); case 'cancel': return new midcom_response_relocate("__mfa/asgard/object/{$this->_request_data['default_mode']}/{$args[0]}/"); } // Add Thickbox midcom::get('head')->add_jsfile(MIDCOM_STATIC_URL . '/midgard.admin.asgard/object_browser.js'); midcom::get('head')->add_jsfile(MIDCOM_STATIC_URL . '/jQuery/thickbox/jquery-thickbox-3.1.pack.js'); $this->add_stylesheet(MIDCOM_STATIC_URL . '/jQuery/thickbox/thickbox.css', 'screen'); midcom::get('head')->add_jscript('var tb_pathToImage = "' . MIDCOM_STATIC_URL . '/jQuery/thickbox/loadingAnimation.gif"'); // Add jQuery file for the checkbox operations midcom::get('head')->add_jsfile(MIDCOM_STATIC_URL . '/midgard.admin.asgard/jquery-copytree.js'); midcom::get('head')->add_jscript('jQuery(document).ready(function(){jQuery("#midgard_admin_asgard_copytree").tree_checker();})'); // Common hooks for Asgard midgard_admin_asgard_plugin::bind_to_object($this->_object, $handler_id, $data); // Set the page title switch ($handler_id) { case '____mfa-asgard-object_copy_tree': $data['page_title'] = sprintf($this->_l10n->get('copy %s and its descendants'), $this->_object->{$target}['label']); break; default: $data['page_title'] = sprintf($this->_l10n->get('copy %s'), $this->_object->{$target}['label']); } $data['target'] = $target; }
/** * Creates a QB instance for _get_child_objects_type and _count_child_objects_type */ public function &_child_objects_type_qb(&$schema_type, &$for_object, $deleted) { if (empty($schema_type)) { debug_add('Passed schema_type argument is empty, this is fatal', MIDCOM_LOG_ERROR); $x = false; return $x; } if (!is_object($for_object)) { debug_add('Passed for_object argument is not object, this is fatal', MIDCOM_LOG_ERROR); $x = false; return $x; } if ($deleted) { $qb = new midgard_query_builder($schema_type); } else { $qb = false; // Figure correct MidCOM DBA class to use and get midcom QB $midcom_dba_classname = midcom::get('dbclassloader')->get_midcom_class_name_for_mgdschema_object($schema_type); if (empty($midcom_dba_classname)) { debug_add("MidCOM DBA does not know how to handle {$schema_type}", MIDCOM_LOG_ERROR); return $qb; } if (!midcom::get('dbclassloader')->load_component_for_class($midcom_dba_classname)) { debug_add("Failed to load the handling component for {$midcom_dba_classname}, cannot continue.", MIDCOM_LOG_ERROR); return $qb; } $qb_callback = array($midcom_dba_classname, 'new_query_builder'); if (!is_callable($qb_callback)) { debug_add("Static method {$midcom_dba_classname}::new_query_builder() is not callable", MIDCOM_LOG_ERROR); return $qb; } $qb = call_user_func($qb_callback); } // Sanity-check if (!$qb) { debug_add("Could not get QB for type '{$schema_type}'", MIDCOM_LOG_ERROR); $x = false; return $x; } // Deleted constraints if ($deleted) { $qb->include_deleted(); $qb->add_constraint('metadata.deleted', '<>', 0); } // Figure out constraint(s) to use to get child objects $ref = new midgard_reflection_property($schema_type); $multiple_links = false; $linkfields = array(); $linkfields['up'] = midgard_object_class::get_property_up($schema_type); $linkfields['parent'] = midgard_object_class::get_property_parent($schema_type); $object_baseclass = midcom_helper_reflector::resolve_baseclass(get_class($for_object)); foreach ($linkfields as $link_type => $field) { if (empty($field)) { // No such field for the object unset($linkfields[$link_type]); continue; } $linked_class = $ref->get_link_name($field); if (empty($linked_class) && $ref->get_midgard_type($field) === MGD_TYPE_GUID) { // Guid link without class specification, valid for all classes continue; } if ($linked_class != $object_baseclass) { // This link points elsewhere unset($linkfields[$link_type]); continue; } } if (count($linkfields) === 0) { debug_add("Class '{$schema_type}' has no valid link properties pointing to class '" . get_class($for_object) . "', this should not happen here", MIDCOM_LOG_ERROR); $x = false; return $x; } if (count($linkfields) > 1) { $multiple_links = true; $qb->begin_group('OR'); } foreach ($linkfields as $link_type => $field) { $field_type = $ref->get_midgard_type($field); $field_target = $ref->get_link_target($field); if (empty($field_target) && $field_type === MGD_TYPE_GUID) { $field_target = 'guid'; } if (!$field_target || !isset($for_object->{$field_target})) { if ($multiple_links) { $qb->end_group(); } // Why return false ??? $x = false; return $x; } switch ($field_type) { case MGD_TYPE_STRING: case MGD_TYPE_GUID: $qb->add_constraint($field, '=', (string) $for_object->{$field_target}); break; case MGD_TYPE_INT: case MGD_TYPE_UINT: if ($link_type == 'up') { $qb->add_constraint($field, '=', (int) $for_object->{$field_target}); } else { $qb->begin_group('AND'); $qb->add_constraint($field, '=', (int) $for_object->{$field_target}); // make sure we don't accidentally find other objects with the same id $qb->add_constraint($field . '.guid', '=', (string) $for_object->guid); $qb->end_group(); } break; default: debug_add("Do not know how to handle linked field '{$field}', has type {$field_type}", MIDCOM_LOG_INFO); if ($multiple_links) { $qb->end_group(); } // Why return false ??? $x = false; return $x; } } if ($multiple_links) { $qb->end_group(); } return $qb; }
private function _prepare_qb() { $query = $this->_request["term"]; $wildcard_query = $this->_add_wildcards($query); $qb = @call_user_func(array($this->_request['class'], 'new_query_builder')); if (!$qb) { debug_add("use midgard_query_builder"); $qb = new midgard_query_builder($class); } if (!empty($this->_request['constraints']) && is_array($this->_request['constraints'])) { $constraints = $this->_request['constraints']; ksort($constraints); reset($constraints); foreach ($constraints as $key => $data) { if (!array_key_exists('value', $data) || empty($data['field']) || empty($data['op'])) { debug_add("Constraint #{$key} is not correctly defined, skipping", MIDCOM_LOG_WARN); continue; } $qb->add_constraint($data['field'], $data['op'], $data['value']); } } if (preg_match('/^%+$/', $query)) { debug_add('$query is all wildcards, don\'t waste time in adding LIKE constraints'); } else { $reflector = new midgard_reflection_property(midcom_helper_reflector::resolve_baseclass($this->_request['class'])); $qb->begin_group('OR'); foreach ($this->_request['searchfields'] as $field) { $field_type = $reflector->get_midgard_type($field); $operator = 'LIKE'; if (strpos($field, '.')) { //TODO: This should be resolved properly $field_type = MGD_TYPE_STRING; } switch ($field_type) { case MGD_TYPE_GUID: case MGD_TYPE_STRING: case MGD_TYPE_LONGTEXT: debug_add("adding search (ORed) constraint: {$field} LIKE '{$wildcard_query}'"); $qb->add_constraint($field, 'LIKE', $wildcard_query); break; case MGD_TYPE_INT: case MGD_TYPE_UINT: case MGD_TYPE_FLOAT: debug_add("adding search (ORed) constraint: {$field} = {$query}'"); $qb->add_constraint($field, '=', $query); break; default: debug_add("can't handle field type " . $field_type, MIDCOM_LOG_WARN); break; } } $qb->end_group(); } if (!empty($this->_request['orders']) && is_array($this->_request['orders'])) { ksort($this->_request['orders']); reset($this->_request['orders']); foreach ($this->_request['orders'] as $data) { foreach ($data as $field => $order) { $qb->add_order($field, $order); } } } return $qb; }