private function _search_type_qb($dummy_object, $term) { $object_class = get_class($dummy_object); $type_fields = array_keys(get_object_vars($dummy_object)); $reflector = new midgard_reflection_property($object_class); unset($type_fields['metadata']); $qb = $this->_prepare_qb($dummy_object); if (!$qb) { return array(); } $constraints = 0; $qb->begin_group('OR'); foreach ($type_fields as $key) { $field_type = $reflector->get_midgard_type($key); switch ($field_type) { case MGD_TYPE_STRING: case MGD_TYPE_LONGTEXT: $qb->add_constraint($key, 'LIKE', "%{$term}%"); $constraints++; break; } } $qb->end_group(); if (!$constraints) { return array(); } return $qb->execute(); }
public static function object_to_text(midgard_object $object) { $text = ''; $props = get_object_vars($object); $reflectionproperty = new midgard_reflection_property(get_class($object)); foreach ($props as $property => $value) { if (!$value) { continue; } $type = $reflectionproperty->get_midgard_type($property); switch ($type) { case MGD_TYPE_STRING: case MGD_TYPE_LONGTEXT: $text .= strip_tags(str_replace('>', '> ', $object->{$property})) . "\n\n"; break; } } return $text; }
/** * * @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(); }
public static function get_property_documentation($class) { $property_docs = array(); $props = array(); $mgdschemas = midgardmvc_core::get_instance()->dispatcher->get_mgdschema_classes(); if (in_array($class, $mgdschemas)) { $dummy = new $class(); $props = get_object_vars($dummy); } elseif ($class == 'midgard_metadata') { $dummy = new midgard_person(); $props = get_object_vars($dummy->metadata); } if (empty($props)) { // Non-MgdSchema class, reflect using PHP method $reflector = new midgard_reflection_class($class); $props = $reflector->getProperties(); foreach ($props as $property) { if (!$property->isPublic()) { // No sense to document private properties continue; } $property_doc = array('name' => $property->name, 'type' => null, 'type_url' => null, 'link_url' => null, 'signature' => $property->name, 'documentation' => midgardmvc_core_helpers_documentation::render_docblock($property->getDocComment())); $property_docs[] = $property_doc; } return $property_docs; } $reflectionproperty = new midgard_reflection_property($class); foreach ($props as $property => $value) { if ($property == 'action') { continue; } $type = midgardmvc_core_helpers_documentation::get_midgard_type_signature($reflectionproperty->get_midgard_type($property)); if (!$type && $property == 'metadata') { $type = 'midgard_metadata'; } $property_doc = array('name' => $property, 'type' => $type, 'type_url' => null, 'link_url' => null, 'signature' => "{$type} {$property}", 'documentation' => $reflectionproperty->description($property)); try { // Link to the class documentation is the property is of particular type if (strpos($type, '_') !== false && class_exists($type)) { $property_doc['type_url'] = midgardmvc_core::get_instance()->dispatcher->generate_url('midcom_documentation_class', array('class' => $type)); } } catch (Exception $e) { } if ($reflectionproperty->is_link($property)) { $property_doc['link_url'] = midgardmvc_core::get_instance()->dispatcher->generate_url('midcom_documentation_class', array('class' => $reflectionproperty->get_link_name($property))); $property_doc['link'] = $reflectionproperty->get_link_name($property) . '::' . $reflectionproperty->get_link_target($property); } $property_docs[] = $property_doc; } return $property_docs; }
private function _store_links() { $mgdschema_classname = midcom::get('dbclassloader')->get_mgdschema_class_name_for_midcom_class($this->link_class); $ref = new midgard_reflection_property($mgdschema_classname); $type_map = array(); foreach ($this->link_columns as $column) { $type_map[$column] = $ref->get_midgard_type($column); } $current_selection = array(); unset($this->_storage_data['index']); foreach ($this->_storage_data as $link_row_id => $values) { if (array_key_exists($this->link_row_property, $values)) { $link_row_id = $values[$this->link_row_property]; } $current_selection[] = $link_row_id; $link_object = null; $needs_update = false; $qb = midcom::get('dbfactory')->new_query_builder($this->link_class); $qb->add_constraint($this->link_parent_field, '=', $this->storage->object->{$this->link_parent_type}); $qb->add_constraint($this->link_row_property, '=', $link_row_id); $results = $qb->execute(); if (sizeof($results) > 0) { $link_object = $results[0]; } else { $link_object = new $this->link_class(); $link_object->{$this->link_parent_field} = $this->storage->object->{$this->link_parent_type}; $link_object->{$this->link_row_property} = $link_row_id; $link_object->create(); } foreach ($type_map as $key => $type) { if ($key == $this->link_row_property) { continue; } $value = isset($values[$key]) ? $values[$key] : false; switch ($type) { case MGD_TYPE_INT: $value = (int) $value; break; case MGD_TYPE_FLOAT: $value = (double) $value; break; } if ($link_object->{$key} != $value) { $needs_update = true; $link_object->{$key} = $value; } } if ($needs_update) { $link_object->update(); } } $qb = midcom::get('dbfactory')->new_query_builder($this->link_class); $qb->add_constraint($this->link_parent_field, '=', $this->storage->object->{$this->link_parent_type}); if (count($current_selection)) { $qb->add_constraint($this->link_row_property, 'NOT IN', $current_selection); } $links_todelete = $qb->execute(); foreach ($links_todelete as $link_object) { $link_object->delete(); } }
private function _list_group_products() { $product_qb = new org_openpsa_qbpager('org_openpsa_products_product_dba', 'org_openpsa_products_product_dba'); $product_qb->results_per_page = $this->_config->get('products_per_page'); if (count($this->_request_data['linked_products']) > 0) { $product_qb->begin_group('OR'); } if ($this->_request_data['group'] && $this->_request_data['group']->orgOpenpsaObtype == org_openpsa_products_product_group_dba::TYPE_SMART) { // Smart group, query products by stored constraints $constraints = $this->_request_data['group']->list_parameters('org.openpsa.products:constraints'); if (empty($constraints)) { $product_qb->add_constraint('productGroup', '=', $this->_request_data['parent_group']); } $reflector = new midgard_reflection_property('org_openpsa_products_product'); foreach ($constraints as $constraint_string) { $constraint_members = explode(',', $constraint_string); if (count($constraint_members) != 3) { throw new midcom_error("Invalid constraint '{$constraint_string}'"); } // Reflection is needed here for safety $field_type = $reflector->get_midgard_type($constraint_members[0]); switch ($field_type) { case 4: throw new midcom_error("Invalid constraint: '{$constraint_members[0]}' is not a Midgard property"); case MGD_TYPE_INT: $constraint_members[2] = (int) $constraint_members[2]; break; case MGD_TYPE_FLOAT: $constraint_members[2] = (double) $constraint_members[2]; break; case MGD_TYPE_BOOLEAN: $constraint_members[2] = (bool) $constraint_members[2]; break; } $product_qb->add_constraint($constraint_members[0], $constraint_members[1], $constraint_members[2]); } } else { if ($this->_request_data['handler_id'] == 'list_intree') { $product_qb->add_constraint('productGroup', '=', $this->_request_data['parent_category_id']); } else { if ($this->_request_data['handler_id'] == 'listall') { $categories_qb = org_openpsa_products_product_group_dba::new_query_builder(); $categories_qb->add_constraint('up', '=', $this->_request_data['group']->id); $categories = $categories_qb->execute(); for ($i = 0; $i < count($categories); $i++) { $categories_in[$i] = $categories[$i]->id; } $product_qb->add_constraint('productGroup', 'IN', $categories_in); } else { $product_qb->add_constraint('productGroup', '=', $this->_request_data['parent_group']); } } } if (count($this->_request_data['linked_products']) > 0) { $product_qb->add_constraint('id', 'IN', $this->_request_data['linked_products']); $product_qb->end_group(); } // This should be a helper function, same functionality, but with different config-parameter is used in /handler/product/search.php foreach ($this->_config->get('products_listing_order') as $ordering) { $this->_add_ordering($product_qb, $ordering); } if ($this->_config->get('enable_scheduling')) { $product_qb->add_constraint('start', '<=', time()); $product_qb->begin_group('OR'); /* * List products that either have no defined end-of-market dates * or are still in market */ $product_qb->add_constraint('end', '=', 0); $product_qb->add_constraint('end', '>=', time()); $product_qb->end_group(); } $this->_request_data['products'] = $product_qb->execute(); $this->_request_data['products_qb'] =& $product_qb; }
public static function object_to_form($object, midgardmvc_helper_forms_group $form) { // Go through object properties $props = get_object_vars($object); $reflectionproperty = new midgard_reflection_property(get_class($object)); foreach ($props as $property => $value) { if ($property == 'action' || $property == 'guid' || $property == 'id') { // TODO: Make the list of properties to not render configurable continue; } if ($property == 'metadata') { // Metadata is to be handled as a group $metadata = $form->add_group('metadata'); $metadata->set_label('metadata'); midgardmvc_helper_forms_mgdschema::object_to_form($value, $metadata); } $type = $reflectionproperty->get_midgard_type($property); switch ($type) { case MGD_TYPE_STRING: $field = $form->add_field($property, 'text'); $field->set_value($value); $widget = $field->set_widget('text'); $widget->set_label($property); $widget->set_placeholder($reflectionproperty->description($property)); // TODO: maxlength to 255 break; case MGD_TYPE_LONGTEXT: if ($reflectionproperty->get_user_value($property, 'contenttype') == 'html') { $field = $form->add_field($property, 'html'); $widget = $field->set_widget('html'); } else { $field = $form->add_field($property, 'text'); $widget = $field->set_widget('textarea'); } $field->set_value($value); $widget->set_label($property); $widget->set_placeholder($reflectionproperty->description($property)); break; case MGD_TYPE_INT: $field = $form->add_field($property, 'integer'); $field->set_value($value); $widget = $field->set_widget('number'); $widget->set_label($property); $widget->set_placeholder($reflectionproperty->description($property)); break; case MGD_TYPE_UINT: $field = $form->add_field($property, 'integer'); $field->set_value($value); // TODO: Set minimum value to 0 $widget = $field->set_widget('number'); $widget->set_label($property); $widget->set_placeholder($reflectionproperty->description($property)); break; case MGD_TYPE_BOOLEAN: $field = $form->add_field($property, 'boolean'); $field->set_value($value); break; case MGD_TYPE_FLOAT: case MGD_TYPE_TIMESTAMP: case MGD_TYPE_GUID: break; } } }
function sort_schema_fields($first, $second) { $preferred_fields = $this->_config->get('object_preferred_fields'); $timerange_fields = $this->_config->get('object_timerange_fields'); $address_fields = $this->_config->get('object_address_fields'); $phone_fields = $this->_config->get('object_phone_fields'); $location_fields = $this->_config->get('object_location_fields'); // We handle the cases, and then their subcases if (in_array($first, $preferred_fields) && $this->_reflector->get_midgard_type($first) != MGD_TYPE_LONGTEXT) { // This is one of the preferred fields, check subcases if (in_array($second, $preferred_fields)) { return strnatcmp($first, $second); } return -1; } if ($this->_reflector->get_midgard_type($first) == MGD_TYPE_LONGTEXT) { // This is a longtext field, they come next if (in_array($second, $preferred_fields) && $this->_reflector->get_midgard_type($second) != MGD_TYPE_LONGTEXT) { return 1; } if ($this->_reflector->get_midgard_type($second) == MGD_TYPE_LONGTEXT) { return strnatcmp($first, $second); } return -1; } if ($this->_reflector->is_link($first)) { // This is a linked property, they come next if (in_array($second, $preferred_fields) || $this->_reflector->get_midgard_type($second) == MGD_TYPE_LONGTEXT) { return 1; } if ($this->_reflector->is_link($second)) { return strnatcmp($first, $second); } return -1; } if (in_array($first, $timerange_fields)) { if (in_array($second, $preferred_fields) || $this->_reflector->get_midgard_type($second) == MGD_TYPE_LONGTEXT || $this->_reflector->is_link($second)) { return 1; } if (in_array($second, $timerange_fields)) { // Both are phone fields, arrange them in proper order return array_search($first, $timerange_fields) < array_search($second, $timerange_fields) ? -1 : 1; } return -1; } if (in_array($first, $phone_fields)) { if (in_array($second, $preferred_fields) || $this->_reflector->get_midgard_type($second) == MGD_TYPE_LONGTEXT || $this->_reflector->is_link($second) || in_array($second, $timerange_fields)) { return 1; } if (in_array($second, $phone_fields)) { // Both are phone fields, arrange them in proper order return array_search($first, $phone_fields) < array_search($second, $phone_fields) ? -1 : 1; } return -1; } if (in_array($first, $address_fields)) { if (in_array($second, $preferred_fields) || $this->_reflector->get_midgard_type($second) == MGD_TYPE_LONGTEXT || $this->_reflector->is_link($second) || in_array($second, $timerange_fields) || in_array($second, $phone_fields)) { return 1; } if (in_array($second, $address_fields)) { // Both are address fields, arrange them in proper order return array_search($first, $address_fields) < array_search($second, $address_fields) ? -1 : 1; } return -1; } if (in_array($first, $location_fields)) { if (in_array($second, $preferred_fields) || $this->_reflector->get_midgard_type($second) == MGD_TYPE_LONGTEXT || $this->_reflector->is_link($second) || in_array($second, $timerange_fields) || in_array($second, $phone_fields) || in_array($second, $address_fields)) { return 1; } if (in_array($second, $location_fields)) { // Both are address fields, arrange them in proper order return array_search($first, $location_fields) < array_search($second, $location_fields) ? -1 : 1; } return -1; } if (in_array($second, $preferred_fields) || $this->_reflector->get_midgard_type($second) == MGD_TYPE_LONGTEXT || $this->_reflector->is_link($second) || in_array($second, $timerange_fields) || in_array($second, $phone_fields) || in_array($second, $address_fields) || in_array($second, $location_fields)) { // First field was not a preferred field, but second is return 1; } // Others come as they do return strnatcmp($first, $second); }
function _resolve_child_classes_links_back($property, $prospect_type, $schema_type) { if (empty($property)) { return false; } $ref = new midgard_reflection_property($prospect_type); $link_class = $ref->get_link_name($property); if (empty($link_class) && $ref->get_midgard_type($property) === MGD_TYPE_GUID) { return true; } if (midcom_helper_reflector::is_same_class($link_class, $schema_type)) { return true; } return false; }
/** * Get the GUID of the object's parent. This is done by reading up or parent * property values, which will give us the parent's ID. Since the ID => GUID relation * won't change, the corresponding GUID is then stored in an in-request static cache */ public static function get_parent_guid_uncached_static($object_guid, $class_name) { static $parent_mapping = array(); $class_name = midcom::get('dbclassloader')->get_mgdschema_class_name_for_midcom_class($class_name); $reflector = new midgard_reflection_property($class_name); $up_property = midgard_object_class::get_property_up($class_name); if (!empty($up_property)) { $target_property = $reflector->get_link_target($up_property); // Up takes precedence over parent $mc = new midgard_collector($class_name, 'guid', $object_guid); $mc->set_key_property($up_property); $mc->execute(); $link_values = $mc->list_keys(); if (!empty($link_values)) { list($link_value, $dummy) = each($link_values); unset($mc, $link_values, $dummy); if (!empty($link_value)) { if (!array_key_exists($class_name, $parent_mapping)) { $parent_mapping[$class_name] = array(); } if (array_key_exists($link_value, $parent_mapping[$class_name])) { return $parent_mapping[$class_name][$link_value]; } $mc2 = new midgard_collector($class_name, $target_property, $link_value); $mc2->set_key_property('guid'); $mc2->execute(); $guids = $mc2->list_keys(); if (!is_array($guids)) { unset($mc2, $guids, $link_value); $parent_mapping[$class_name][$link_value] = null; return $parent_mapping[$class_name][$link_value]; } list($parent_guid, $dummy) = each($guids); $parent_mapping[$class_name][$link_value] = $parent_guid; unset($mc2, $guids, $link_value, $dummy); return $parent_guid; } } else { unset($mc, $link_values); } } $parent_property = midgard_object_class::get_property_parent($class_name); if (!empty($parent_property) && $reflector->get_link_target($parent_property)) { $target_property = $reflector->get_link_target($parent_property); $target_class = $reflector->get_link_name($parent_property); $mc = new midgard_collector($class_name, 'guid', $object_guid); $mc->set_key_property($parent_property); $mc->execute(); $link_values = $mc->list_keys(); if (!empty($link_values)) { list($link_value, $dummy) = each($link_values); unset($mc, $link_values, $dummy); if (!empty($link_value)) { if (!array_key_exists($target_class, $parent_mapping)) { $parent_mapping[$target_class] = array(); } if (array_key_exists($link_value, $parent_mapping[$target_class])) { return $parent_mapping[$target_class][$link_value]; } $mc2 = new midgard_collector($target_class, $target_property, $link_value); $mc2->set_key_property('guid'); $mc2->execute(); $guids = $mc2->list_keys(); if (!is_array($guids)) { unset($mc2, $guids, $link_value); $parent_mapping[$target_class][$link_value] = null; return $parent_mapping[$target_class][$link_value]; } list($parent_guid, $dummy) = each($guids); $parent_mapping[$target_class][$link_value] = $parent_guid; unset($mc2, $guids, $link_value, $dummy); return $parent_guid; } } else { unset($mc, $link_values); } } // FIXME: Handle GUID linking return null; }
/** * Check that the id_field is replication-safe */ private function _is_replication_safe() { if ($this->id_field == 'guid' || is_a($this->_type, 'midcom_helper_datamanager2_type_mnrelation')) { return true; } switch ($this->_field['storage']['location']) { case 'parameter': case 'configuration': // Storing IDs to parameters is not replication safe debug_add("Field \"{$this->name}\" is set to store to a parameter but links via ID which is not replication-safe, aborting.", MIDCOM_LOG_WARN); midcom::get('uimessages')->add($this->_l10n->get('midcom.helper.datamanager2'), sprintf($this->_l10n->get('field %s is set to store to a parameter but links via ID which is not replication-safe, aborting'), $this->name), 'error'); return false; } // Normal field, verify that it is a link if ($this->_type->storage->object !== null && !is_a($this->_type->storage->object, 'midcom_core_temporary_object')) { // We have an object, check the link type // Note: in creation mode we do not have this so we have no way to check) $mgdschema_object = midcom::get('dbfactory')->convert_midcom_to_midgard($this->_type->storage->object); if ($mgdschema_object !== null && $this->_field['storage']['location'] !== null) { $mrp = new midgard_reflection_property(get_class($mgdschema_object)); if (($mrp->get_midgard_type($this->_field['storage']['location']) === MGD_TYPE_INT || $mrp->get_midgard_type($this->_field['storage']['location']) === MGD_TYPE_UINT) && !$mrp->is_link($this->_field['storage']['location'])) { // Storing IDs to non-linked fields is not replication safe debug_add("Field \"{$this->name}\" is set to store to property \"{$this->_field['storage']['location']}\" which is not link, making it replication-unsafe, aborting.", MIDCOM_LOG_WARN); midcom::get('uimessages')->add($this->_l10n->get('midcom.helper.datamanager2'), sprintf($this->_l10n->get('field %s is set to store to property %s but links via ID which is not replication-safe, aborting'), $this->name, $this->_field['storage']['location']), 'error'); return false; } } } return true; }
$response->send(); } } if (count($results) <= 0 || !is_array($results)) { $response->status = 2; $response->errstr = "No results found"; $response->send(); } $response->status = 1; $response->errstr = ""; $items = array(); foreach ($results as $object) { if (isset($reflector_key) && !empty($reflector_key)) { debug_add("Using reflector with key {$reflector_key}"); $reflector_type = get_class($object); $reflector = new midgard_reflection_property($reflector_type); if ($reflector->is_link($reflector_key)) { $linked_type = $reflector->get_link_name($reflector_key); $object = new $linked_type($object->{$reflector_key}); } debug_print_r('reflected object', $object); } $id = @$object->id; $guid = @$object->guid; debug_add("adding result: id={$id} guid={$guid}"); $result = array('id' => $id, 'guid' => $guid); debug_print_r('$result_headers', $result_headers); if (!is_array($result_headers) || !empty($reflector_key) && !$result_headers) { $value = @$object->get_label(); debug_add("adding header item: name=label value={$value}"); $result['label'] = "<![CDATA[{$value}]]>";
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; }
private function getChildTypes($midgard_class) { $mgdschemas = $this->getTypes(); $child_types = array(); foreach ($mgdschemas as $mgdschema) { if ($mgdschema == 'midgard_attachment' || $mgdschema == 'midgard_parameter') { continue; } $link_properties = array('parent' => \midgard_object_class::get_property_parent($mgdschema), 'up' => \midgard_object_class::get_property_up($mgdschema)); $ref = new \midgard_reflection_property($mgdschema); foreach ($link_properties as $type => $property) { $link_class = $ref->get_link_name($property); if (empty($link_class) && $ref->get_midgard_type($property) === MGD_TYPE_GUID) { $child_types[] = $mgdschema; continue; } if ($link_class == $parent_class) { $child_types[] = $mgdschema; } } } return $child_types; }