/** * Sets the constraints for QB for articles, supports article links etc.. * * @param midgard_query_builder $qb reference to the QB object * @param array $data reference to the request_data array */ public static function article_qb_constraints(&$qb, &$data, $handler_id) { $config =& $data['config']; // GUIDs of topics to list articles from. $guids_array = array(); $guids_array[] = $data['content_topic']->guid; // Resolve any other topics we may need $list_from_folders = $config->get('list_from_folders'); if ($list_from_folders) { // We have specific folders to list from, therefore list from them and current node $guids = explode('|', $config->get('list_from_folders')); foreach ($guids as $guid) { if (!$guid || !mgd_is_guid($guid)) { // Skip empty and broken guids continue; } $guids_array[] = $guid; } } /** * Ref #1776, expands GUIDs before adding them as constraints, should save query time */ $topic_ids = array(); $topic_ids[] = $data['content_topic']->id; if (!empty($guids_array)) { $mc = midcom_db_topic::new_collector('metadata.deleted', false); $mc->add_constraint('guid', 'IN', $guids_array); $topic_ids = $mc->get_values('id'); unset($mc); } // Include the article links to the indexes if enabled if ($config->get('enable_article_links')) { $mc = net_nehmer_blog_link_dba::new_collector('topic', $data['content_topic']->id); $mc->add_constraint('topic', '=', $data['content_topic']->id); $mc->add_order('metadata.published', 'DESC'); $mc->set_limit((int) $config->get('index_entries')); // Get the results $mc->execute(); $links = $mc->get_values('article'); $qb->begin_group('OR'); $qb->add_constraint('id', 'IN', $links); $qb->add_constraint('topic', 'IN', $topic_ids); $qb->end_group(); } else { $qb->add_constraint('topic', 'IN', $topic_ids); } if (count($topic_ids) > 1 && ($list_from_folders_categories = $config->get('list_from_folders_categories'))) { // TODO: check schema storage to get fieldname $multiple_categories = true; if (isset($data['schemadb']['default']) && isset($data['schemadb']['default']->fields['list_from_folders_categories']) && array_key_exists('allow_multiple', $data['schemadb']['default']->fields['list_from_folders_categories']['type_config']) && !$data['schemadb']['default']->fields['list_from_folders_categories']['type_config']['allow_multiple']) { $multiple_categories = false; } debug_add("multiple_categories={$multiple_categories}"); $qb->begin_group('OR'); $list_from_folders_categories = explode(',', $list_from_folders_categories); $is_content_topic = true; foreach ($topic_ids as $topic_id) { if ($is_content_topic) { $qb->add_constraint('topic', '=', $topic_id); $is_content_topic = false; continue; } $qb->begin_group('AND'); $qb->add_constraint('topic', '=', $topic_id); $qb->begin_group('OR'); foreach ($list_from_folders_categories as $category) { if ($category = trim($category)) { if ($multiple_categories) { $qb->add_constraint('extra1', 'LIKE', "%|{$category}|%"); } else { $qb->add_constraint('extra1', '=', $category); } } } $qb->end_group(); $qb->end_group(); } $qb->end_group(); } // Hide the articles that have the publish time in the future and if // the user is not administrator if ($config->get('enable_scheduled_publishing') && !midcom::get('auth')->admin) { // Show the article only if the publishing time has passed or the viewer // is the author $qb->begin_group('OR'); $qb->add_constraint('metadata.published', '<', gmdate('Y-m-d H:i:s')); if (midcom::get('auth')->user && isset(midcom::get('auth')->user->guid)) { $qb->add_constraint('metadata.authors', 'LIKE', '|' . midcom::get('auth')->user->guid . '|'); } $qb->end_group(); } $qb->add_constraint('up', '=', 0); }
function list_watchers() { $topic = new midcom_db_topic($this->topic); // Get list of people watching this page $watchers = array(); $qb = new midgard_query_builder('midgard_parameter'); $qb->add_constraint('domain', '=', 'net.nemein.wiki:watch'); $qb->begin_group('OR'); // List people watching the whole wiki $qb->add_constraint('parentguid', '=', $topic->guid); // List people watching this particular page $qb->add_constraint('parentguid', '=', $this->guid); $qb->end_group(); $watcher_params = $qb->execute(); foreach ($watcher_params as $parameter) { if (in_array($parameter->name, $watchers)) { // We found this one already, skip continue; } $watchers[] = $parameter->name; } return $watchers; }
/** * Find event with arbitrary GUID either in externalGuid or guid */ function search_vCal_uid($uid) { //TODO: MidCOM DBAize $qb = new midgard_query_builder('org_openpsa_event'); $qb->begin_group('OR'); $qb->add_constraint('guid', '=', $uid); $qb->add_constraint('externalGuid', '=', $uid); $qb->end_group(); $ret = @$qb->execute(); if ($ret && count($ret) > 0) { //It's unlikely to have more than one result and this should return an object (or false) return $ret[0]; } else { return false; } }
public function get_node_by_component($component) { if (isset(midgardmvc_core_providers_hierarchy_node_midgard2::$nodes_by_component[$component])) { return midgardmvc_core_providers_hierarchy_node_midgard2::$nodes_by_component[$component]; } $qb = new midgard_query_builder('midgardmvc_core_node'); $qb->add_constraint('component', '=', $component); $qb->begin_group('OR'); $qb->add_constraint('up', 'INTREE', self::$root_node_id); $qb->add_constraint('id', '=', self::$root_node_id); $qb->end_group(); $qb->set_limit(1); $nodes = $qb->execute(); if (count($nodes) == 0) { return null; } return midgardmvc_core_providers_hierarchy_node_midgard2::get_instance($nodes[0]); }
private function _list_related() { if (!$this->wiki) { return false; } // The depth of relation looked depends on object type if (is_subclass_of($this->target, 'midgard_person')) { $this->_list_related_guids_of_a_person($this->target); } else { if (is_subclass_of($this->target, 'midgard_group')) { // Include notes about members of the group $qb = midcom::get('dbfactory')->new_query_builder('midcom_db_member'); $qb->add_constraint('gid', '=', $this->target->id); $members = $qb->execute(); foreach ($members as $member) { try { $person = new midcom_db_person($member->uid); $this->_list_related_guids_of_a_person($person); } catch (midcom_error $e) { $e->log(); } } // And the group itself $this->_related_guids[$this->target->guid] = true; } else { $this->_related_guids[$this->target->guid] = true; } } if (count($this->_related_guids) > 0) { if (class_exists('org_openpsa_qbpager_direct')) { $qb = new org_openpsa_qbpager_direct('midgard_parameter', 'related_notes'); $qb->results_per_page = 10; $this->_paged_qb =& $qb; } else { $qb = new midgard_query_builder('midgard_parameter'); } $qb->begin_group('OR'); foreach ($this->_related_guids as $guid => $related) { $qb->add_constraint('name', '=', $guid); } $qb->end_group(); $qb->add_constraint('domain', '=', 'net.nemein.wiki:related_to'); $ret = @$qb->execute(); if (is_array($ret) && count($ret) > 0) { foreach ($ret as $related_to) { try { $wikipage = new net_nemein_wiki_wikipage($related_to->parentguid); $this->related[$wikipage->guid] = $wikipage; } catch (midcom_error $e) { $e->log(); } } } } }
/** * Generates an URL for given route_id with given arguments * * @param string $route_id the id of the route to generate a link for * @param array $args associative arguments array * @return string url */ public function generate_url($route_id, array $args, midgardmvc_core_node $page = null, $component = null) { static $pages_for_component = array(); if (is_null($page) && !is_null($component)) { if (!isset($pages_for_component[$component])) { // Find a page matching the requested component $qb = new midgard_query_builder('midgardmvc_core_node'); $qb->add_constraint('component', '=', $component); $qb->begin_group('OR'); $qb->add_constraint('up', 'INTREE', $this->midgardmvc->context->root_page->id); $qb->add_constraint('id', '=', $this->midgardmvc->context->root_page->id); $qb->end_group(); $qb->set_limit(1); $pages = $qb->execute(); if (empty($pages)) { throw new OutOfBoundsException("No page matching component {$component} found"); } $pages_for_component[$component] = $pages[0]; } $page = $pages_for_component[$component]; } if (!is_null($page)) { $this->midgardmvc->context->create(); $request = new midgardmvc_core_helpers_request(); $request->set_page($page); $request->populate_context(); $this->initialize($request); } $route_definitions = $this->get_routes(); if (!isset($route_definitions[$route_id])) { throw new OutOfBoundsException("route_id '{$route_id}' not found in routes configuration in context " . $this->midgardmvc->context->get_current_context()); } $route = $route_definitions[$route_id]['route']; $link = $route; foreach ($args as $key => $value) { if (is_array($value)) { $value_array = array(); foreach ($value as $part) { if (empty($part)) { continue; } $value_array[] = $part; } $value = implode('.', $value_array); // This is a token replacement, add the type hint $key = "token:{$key}"; } $link = str_replace("{\${$key}}", $value, $link); } if (preg_match_all('%\\{$(.+?)\\}%', $link, $link_matches)) { throw new UnexpectedValueException("Missing arguments matching route '{$route_id}' of {$this->midgardmvc->core->component}: " . implode(', ', $link_remaining_args)); } if (!is_null($page)) { $url = preg_replace('%/{2,}%', '/', $this->midgardmvc->context->uri . $link); $this->midgardmvc->context->delete(); return $url; } return preg_replace('%/{2,}%', '/', $this->midgardmvc->context->uri . $link); }
/** * Get closest items * * @param string $class MidCOM DBA class to query * @param midgardmvc_helper_location_spot $spot Center position * @param integer $limit How many results to return * @return Array Array of MidCOM DBA objects sorted by proximity */ static function get_closest($class, midgardmvc_helper_location_spot $spot, $limit, $modifier = 0.15) { $classname = midgardmvc_helper_location_utils::get_positioning_class($class); if ($classname != $class) { $direct = false; } else { $direct = true; } $qb = new midgard_query_builder($classname); if (!$direct) { // We're querying a regular DBA object through a location object $qb->add_constraint('parentclass', '=', $class); } static $rounds = 0; $rounds++; $from['latitude'] = $spot->latitude + $modifier; if ($from['latitude'] > 90) { $from['latitude'] = 90; } $from['longitude'] = $spot->longitude - $modifier; if ($from['longitude'] < -180) { $from['longitude'] = -180; } $to['latitude'] = $spot->latitude - $modifier; if ($to['latitude'] < -90) { $to['latitude'] = -90; } $to['longitude'] = $spot->longitude + $modifier; if ($to['longitude'] > 180) { $to['longitude'] = 180; } if (!isset($current_locale)) { $current_locale = setlocale(LC_NUMERIC, '0'); setlocale(LC_NUMERIC, 'C'); } $qb->begin_group('AND'); $qb->add_constraint('latitude', '<', (double) $from['latitude']); $qb->add_constraint('latitude', '>', (double) $to['latitude']); $qb->end_group(); $qb->begin_group('AND'); $qb->add_constraint('longitude', '>', (double) $from['longitude']); $qb->add_constraint('longitude', '<', (double) $to['longitude']); $qb->end_group(); $result_count = $qb->count(); //echo "<br />Round {$rounds}, lat1 {$from['latitude']} lon1 {$from['longitude']}, lat2 {$to['latitude']} lon2 {$to['longitude']}: {$result_count} results\n"; if ($result_count < $limit) { if ($from['latitude'] == 90 && $from['longitude'] == -180 && $to['latitude'] == -90 && $to['longitude'] == 180) { // We've queried the entire globe so we return whatever we got $results = $qb->execute(); $closest = array(); foreach ($results as $result) { $result_spot = new midgardmvc_helper_location_spot($result); $distance = sprintf("%05d", round(midgardmvc_helper_location_utils::get_distance($spot, $result_spot))); if (!$direct) { // Instantiate the real object as the result $result = new $class($result->parent); $result->spot = $result_spot; $result->latitude = $result_spot->latitude; $result->longitude = $result_spot->longitude; } $closest[$distance . $result->guid] = $result; } ksort($closest); reset($closest); return $closest; } $modifier = $modifier * 1.05; setlocale(LC_NUMERIC, $current_locale); return midgardmvc_helper_location_utils::get_closest($class, $spot, $limit, $modifier); } $results = $qb->execute(); $closest = array(); foreach ($results as $result) { $result_spot = new midgardmvc_helper_location_spot($result); $distance = sprintf("%05d", round(midgardmvc_helper_location_utils::get_distance($spot, $result_spot))); if (!$direct) { // Instantiate the real object as the result $result = new $class($result->parent); $result->spot = $result_spot; $result->latitude = $result_spot->latitude; $result->longitude = $result_spot->longitude; } $closest[$distance . $result->guid] = $result; } ksort($closest); reset($closest); while (count($closest) > $limit) { array_pop($closest); } setlocale(LC_NUMERIC, $current_locale); return $closest; }
debug_add("addconstraint loop: Constraint #{$key} is not correctly defined, skipping", MIDCOM_LOG_WARN); continue; } debug_add("Adding constraint: {$data['field']} {$data['op']} " . gettype($data['value']) . " '{$data['value']}'"); $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 { $qb->begin_group('OR'); foreach ($searchfields as $field) { debug_add("adding search (ORed) constraint: {$field} LIKE '{$query}'"); $qb->add_constraint($field, 'LIKE', $query); } $qb->end_group(); } if (is_array($orders)) { ksort($orders); reset($orders); foreach ($orders as $data) { foreach ($data as $field => $order) { debug_add("adding order: {$field}, {$order}"); $qb->add_order($field, $order); } } } $results = $qb->execute(); if ($results === false) { $response->errstr = "Error when executing QB"; $response->send();
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 _qb_filter_results($results) { //Make a map for receipt filtering $results_persons = array(); $results_person_map = array(); foreach ($results as $k => $member) { $results_persons[] = $member->person; $results_person_map[$member->person] = $k; } //Get receipts for our persons if any if (count($results_persons) > 0) { // FIXME: Rewrite for collector $qb_receipts = new midgard_query_builder('org_openpsa_campaign_message_receipt'); $qb_receipts->add_constraint('message', '=', $this->id); $qb_receipts->add_constraint('orgOpenpsaObtype', '=', org_openpsa_directmarketing_campaign_messagereceipt_dba::SENT); $qb_receipts->add_constraint('person', 'IN', $results_persons); $qb_receipts->end_group(); $receipts = $qb_receipts->execute(); //Filter results array by receipts if (is_array($receipts)) { debug_add('Found ' . count($receipts) . ' send receipts for this chunk'); if (count($receipts) > 0) { foreach ($receipts as $receipt) { if (!isset($results_person_map[$receipt->person]) || !isset($results[$results_person_map[$receipt->person]])) { continue; } debug_add("Removing person {$receipt->person} from results"); unset($results[$results_person_map[$receipt->person]]); } } } } return $results; }
/** * Find out how a person prefers to get the event notification * * @param string $action Key of the event in format component:event * @param string $recipient GUID of the receiving person * @return Array options supported by user */ private static function _merge_notification_prefences($component, $action, $recipient) { // TODO: Should we sudo here to ensure getting correct prefs regardless of ACLs? $preference = 'none'; try { $recipient = new midcom_db_person($recipient); } catch (midcom_error $e) { return $preference; } // If user has preference for this message, we use that $personal_preferences = $recipient->list_parameters('org.openpsa.notifications'); if (count($personal_preferences) > 0 && array_key_exists("{$component}:{$action}", $personal_preferences)) { $preference = $personal_preferences[$action]; return $preference; } // Fall back to component defaults $customdata = midcom::get('componentloader')->get_all_manifest_customdata('org.openpsa.notifications'); if (!empty($customdata[$component][$action]['default'])) { $preference = $customdata[$component][$action]['default']; } // Seek possible preferences for this action from user's groups $qb = new midgard_query_builder('midgard_parameter'); $qb->add_constraint('domain', '=', 'org.openpsa.notifications'); $qb->add_constraint('name', '=', "{$component}:{$action}"); // Seek user's groups $member_qb = midcom_db_member::new_query_builder(); $member_qb->add_constraint('uid', '=', (int) $recipient->id); $memberships = $member_qb->execute(); $qb->begin_group('OR'); foreach ($memberships as $member) { $group = new midcom_db_group($member->gid); $qb->add_constraint('parentguid', '=', $group->guid); } $qb->end_group(); $group_preferences = $qb->execute(); if (count($group_preferences) > 0) { foreach ($group_preferences as $preference) { $preference = $preference->value; } } return $preference; }