public function run_handler($topic, array $args = array()) { if (is_object($topic)) { $component = $topic->component; } else { $component = $topic; $topic = $this->get_component_node($component); } $context = new midcom_core_context(null, $topic); $context->set_current(); $context->set_key(MIDCOM_CONTEXT_URI, midcom_connection::get_url('self') . $topic->name . '/' . implode('/', $args) . '/'); // Parser Init: Generate arguments and instantiate it. $context->parser = midcom::get('serviceloader')->load('midcom_core_service_urlparser'); $context->parser->parse($args); $handler = $context->get_handler($topic); $context->set_key(MIDCOM_CONTEXT_CONTENTTOPIC, $topic); $this->assertTrue(is_a($handler, 'midcom_baseclasses_components_interface'), $component . ' found no handler for ./' . implode('/', $args) . '/'); $result = $handler->handle(); $this->assertTrue($result !== false, $component . ' handle returned false on ./' . implode('/', $args) . '/'); $data =& $handler->_context_data[$context->id]['handler']->_handler['handler'][0]->_request_data; if (is_object($result) && $result instanceof midcom_response) { $data['__openpsa_testcase_response'] = $result; } $data['__openpsa_testcase_handler'] = $handler->_context_data[$context->id]['handler']->_handler['handler'][0]; $data['__openpsa_testcase_handler_method'] = $handler->_context_data[$context->id]['handler']->_handler['handler'][1]; // added to simulate http uri composition $_SERVER['REQUEST_URI'] = $context->get_key(MIDCOM_CONTEXT_URI); return $data; }
/** * This is a helper to execute any given Script in the current MidCOM * context. All files have to be in $component_dir/exec directly, otherwise * the script will not execute. * * The script's name is taken from the current argv[0]. * * The script file is executed in the cache's live mode to allow for long running * scripts (just produce any output regularly, or Apache will kill you after ~ 2 mins.). * * The remaining arguments will be placed into the globals $argc/argv. * * @param string $component The component to look in ("midcom" uses core scripts) * @see midcom_services_cache_module_content::enable_live_mode() */ private function _process_exec($component) { // Sanity checks if ($this->_context->parser->argc < 1) { throw new midcom_error_notfound("Script exec path invalid, need exactly one argument."); } // Build the path if ($component == 'midcom') { $path = MIDCOM_ROOT . '/midcom/exec/'; } else { $componentloader = midcom::get('componentloader'); if (!$componentloader->is_installed($component)) { throw new midcom_error_notfound('The requested component is not installed'); } $componentloader->load($component); $this->_context->set_key(MIDCOM_CONTEXT_COMPONENT, $component); $path = $componentloader->path_to_snippetpath($component) . '/exec/'; } $path .= $this->_context->parser->argv[0]; if (is_dir($path) && isset($this->_context->parser->argv[1])) { $path .= '/' . $this->_context->parser->argv[1]; } if (is_dir($path)) { throw new midcom_error_notfound("Path is a directory."); } if (!file_exists($path)) { throw new midcom_error_notfound("File not found."); } // collect remaining arguments and put them to global vars. $GLOBALS['argc'] = $this->_context->parser->argc--; $GLOBALS['argv'] = $this->_context->parser->argv; array_shift($GLOBALS['argv']); midcom::get('cache')->content->enable_live_mode(); midcom::get()->set_status(MIDCOM_STATUS_CONTENT); // We seem to be in a valid place. Exec the file with the current permissions. require $path; // Exit midcom::get()->finish(); _midcom_stop_request(''); }
/** * Dynamically execute a subrequest and insert its output in place of the * function call. * * <b>Important Note</b> As with the Midgard Parser, dynamic_load strips a * trailing .html from the argument list before actually parsing it. * * It tries to load the component referenced with the URL $url and executes * it as if it was used as primary component. Additional configuration parameters * can be appended through the parameter $config. * * This is only possible if the system is in the Page-Style output phase. It * cannot be used within code-init or during the output phase of another * component. * * Example code, executed on a site's homepage, it will load the news listing from * the given URL and display it using a substyle of the node style that is assigned * to the loaded one: * * <code> * $blog = '/blog/latest/3/'; * $substyle = 'homepage'; * midcom::get()->dynamic_load("/midcom-substyle-{$substyle}/{$blog}"); * </code> * * Results of dynamic_loads are cached, by default with the system cache strategy * but you can specify separate cache strategy for the DL in the config array like so * <code> * midcom::get()->dynamic_load("/midcom-substyle-{$substyle}/{$newsticker}", array('cache_module_content_caching_strategy' => 'public')) * </code> * * You can use only less specific strategy than the global strategy, ie basically you're limited to 'memberships' and 'public' as * values if the global strategy is 'user' and to 'public' the global strategy is 'memberships', failure to adhere to this * rule will result to weird cache behavior. * * @param string $url The URL, relative to the Midgard Page, that is to be requested. * @param Array $config A key=>value array with any configuration overrides. * @return int The ID of the newly created context. */ public function dynamic_load($url, $config = array(), $pass_get = false) { debug_add("Dynamic load of URL {$url}"); if (substr($url, -5) == '.html') { $url = substr($url, 0, -5); } if ($this->_status < MIDCOM_STATUS_CONTENT) { throw new midcom_error("dynamic_load content request called before content output phase."); } // Determine new Context ID and set currentcontext, // enter that context and prepare its data structure. $oldcontext = midcom_core_context::get(); $context = new midcom_core_context(null, $oldcontext->get_key(MIDCOM_CONTEXT_ROOTTOPIC)); if ($pass_get) { // Include GET parameters into cache URL $context->set_key(MIDCOM_CONTEXT_URI, midcom_connection::get_url('self') . $url . '?GET=' . serialize($_GET)); } else { $context->set_key(MIDCOM_CONTEXT_URI, midcom_connection::get_url('self') . $url); } $context->set_current(); /* "content-cache" for DLs, check_hit */ if (midcom::get('cache')->content->check_dl_hit($context->id, $config)) { // The check_hit method serves cached content on hit $oldcontext->set_current(); return $context->id; } // Parser Init: Generate arguments and instantiate it. $context->parser = midcom::get('serviceloader')->load('midcom_core_service_urlparser'); $argv = $context->parser->tokenize($url); $context->parser->parse($argv); $this->_process($context); if ($this->_status == MIDCOM_STATUS_ABORT) { debug_add("Dynamic load _process() phase ended up with 404 Error. Aborting...", MIDCOM_LOG_ERROR); // Leave Context $oldcontext->set_current(); return; } // Start another buffer for caching DL results ob_start(); midcom::get('style')->enter_context($context->id); debug_add("Entering Context {$context->id} (old Context: {$oldcontext->id})"); $this->_output(); midcom::get('style')->leave_context(); debug_add("Leaving Context {$context->id} (new Context: {$oldcontext->id})"); $dl_cache_data = ob_get_contents(); ob_end_flush(); /* Cache DL the content */ midcom::get('cache')->content->store_dl_content($context->id, $config, $dl_cache_data); unset($dl_cache_data); // Leave Context $oldcontext->set_current(); midcom::get('style')->enter_context($oldcontext->id); return $context->id; }