/** * application アプリケーションXMLをパースする * * 基本情報 * ======================================================================== * <app name="アプリケーションの名前" summary="アプリケーションのサマリ"> * <description> * アプリケーションの説明 * </description> * </app> * ======================================================================== * * アプリケーションの順次処理を行う場合 * ======================================================================== * <app> * <invoke class="org.rhaco.net.xml.Feed" method="do_read"> * <arg value="http://ameblo.jp/nakagawa-shoko/" /> * <arg value="http://ameblo.jp/kurori1985/" /> * </invoke> * <invoke class="org.rhaco.net.xml.FeedConverter" method="strip_tags" /> * <invoke method="output" /> * </app> * ======================================================================== * * URLマッピングでアプリケーションを作成する * ======================================================================== * <app> * <handler> * <map url="/hello" class="FlowSampleHello" method="hello" template="display.html" summary="ハローワールド" name="hello_world" /> * </handler> * </app> * ======================================================================== * * @param string $file アプリケーションXMLのファイルパス * @param boolean $get_meta 詳細な情報を取得する * @return string{} */ public static function parse_app($file, $get_meta = true) { $apps = array(); $handler_multiple = false; $app_nomatch_redirect = $app_nomatch_template = null; if (Tag::setof($tag, Tag::uncomment(File::read($file)), 'app')) { $app_ns = $tag->in_param('ns'); $app_nomatch_redirect = File::path_slash($tag->in_param('nomatch_redirect'), false, null); $app_nomatch_template = File::path_slash($tag->in_param('nomatch_template'), false, null); $handler_multiple = $tag->in_param('multiple', false) === "true"; $handler_count = 0; $invoke_count = 0; foreach ($tag->in(array('invoke', 'handler')) as $handler) { switch (strtolower($handler->name())) { case 'handler': if ($handler->in_param(App::mode(), "true") === "true") { if ($handler->is_param('class')) { $class = Lib::import($handler->in_param('class')); $maps = new Tag('maps'); $maps->add('class', $handler->in_param('class')); $ref = new ReflectionClass($class); $url = File::path_slash($handler->in_param('url', strtolower(substr($ref->getName(), 0, 1)) . substr($ref->getName(), 1)), false, false); $handler->param('url', $url); $var = new Tag('var'); $handler->add($var->add('name', 'module_url')->add('value', $url)); foreach ($ref->getMethods() as $method) { if ($method->isPublic() && is_subclass_of($method->getDeclaringClass()->getName(), __CLASS__)) { if (!$method->isStatic()) { $url = $method->getName() == 'index' && $method->getNumberOfParameters() == 0 ? '' : $method->getName() . str_repeat("/(.+)", $method->getNumberOfRequiredParameters()); for ($i = 0; $i <= $method->getNumberOfParameters() - $method->getNumberOfRequiredParameters(); $i++) { $map = new Tag('map'); $map->add('url', $url); $map->add('method', $method->getName()); $maps->add($map); $url .= '/(.+)'; } } } } $handler->add($maps); } $handler_name = empty($app_ns) ? str_replace(App::path(), '', $file) . $handler_count++ : $app_ns; $maps = $modules = $vars = array(); $handler_url = File::path_slash(App::branch(), false, true) . File::path_slash($handler->in_param('url'), false, true); $map_index = 0; $base_path = File::path_slash($handler->in_param("template_path"), false, false); foreach ($handler->in(array('maps', 'map', 'var', 'module')) as $tag) { switch (strtolower($tag->name())) { case 'map': $url = File::path_slash($handler_url . File::path_slash($tag->in_param('url'), false, false), false, false); $maps[$url] = self::parse_map($tag, $url, $base_path, $handler_name, null, null, null, $map_index++, $get_meta); break; case 'maps': $maps_map = $maps_module = array(); $maps_base_path = File::path_slash($base_path, false, true) . File::path_slash($tag->in_param('template_path'), false, false); foreach ($tag->in(array('map', 'module')) as $m) { if ($m->name() == 'map') { $url = File::path_slash($handler_url . File::path_slash($tag->in_param('url'), false, true) . File::path_slash($m->in_param('url'), false, false), false, false); $map = self::parse_map($m, $url, $maps_base_path, $handler_name, $tag->in_param('class'), $tag->in_param('secure'), $tag->in_param('update'), $map_index++, $get_meta); $maps_map[$url] = $map; } else { $maps_module[] = self::parse_module($m); } } if (!empty($maps_module)) { foreach ($maps_map as $k => $v) { $maps_map[$k]['modules'] = array_merge($maps_map[$k]['modules'], $maps_module); } } $maps = array_merge($maps, $maps_map); break; case 'var': $vars[] = self::parse_var($tag); break; case 'module': $modules[] = self::parse_module($tag); break; } } $verify_maps = array(); foreach ($maps as $m) { if (!empty($m['name'])) { if (isset($verify_maps[$m['name']])) { Exceptions::add(new RuntimeException("name `" . $m['name'] . "` with this map already exists.")); } $verify_maps[$m['name']] = true; } } Exceptions::validation(); $urls = $maps; krsort($urls); $sort_maps = $surls = array(); foreach (array_keys($urls) as $url) { $surls[$url] = strlen(preg_replace("/[\\W]/", "", $url)); } arsort($surls); krsort($surls); foreach (array_keys($surls) as $url) { $sort_maps[$url] = $maps[$url]; } $apps[] = array('type' => 'handle', 'maps' => $sort_maps, 'modules' => $modules, 'vars' => $vars, 'on_error' => array('status' => $handler->in_param('error_status', 403), 'template' => $handler->in_param('error_template'), 'redirect' => $handler->in_param('error_redirect'))); } break; case 'invoke': $targets = $methods = $args = $modules = array(); if ($handler->is_param('method')) { $targets[] = $handler->add('name', $handler->in_param('method')); } else { $targets = $handler->in_all('method'); } foreach ($targets as $method_tag) { foreach ($method_tag->in(array('arg', 'result')) as $arg) { $args[] = array('type' => $arg->name(), 'value' => $arg->in_param('value', Text::plain($arg->value()))); } $methods[] = array('method' => $method_tag->in_param('name'), 'args' => empty($args) && $handler->is_param('class') && $invoke_count > 0 ? array(array('type' => 'result', 'value' => null)) : $args); } foreach ($handler->in('module') as $m) { $modules[] = self::parse_module($m); } $apps[] = array('type' => 'invoke', 'class' => $handler->in_param('class'), 'methods' => $methods, 'modules' => $modules); $invoke_count++; break; } } } return array("nomatch_redirect" => $app_nomatch_redirect, "nomatch_template" => $app_nomatch_template, "handler_multiple" => $handler_multiple, "apps" => $apps); }
private final function save_verify() { foreach ($this->self_columns() as $name => $column) { $type = $this->a($name, "type"); $value = $this->{$name}; if ($this->a($name, "require") === true && ($value === "" || $value === null)) { Exceptions::add(new Exception($name . " required")); } if ($this->a($name, "unique") === true) { $q = array(Q::eq($name, $value)); foreach ($this->primary_columns() as $column) { if (null !== ($value = $this->{$column->name()}())) { $q[] = Q::neq($column->name(), $this->{$column->name()}()); } } if (0 < call_user_func_array(array(C($this), "find_count"), $q)) { Exceptions::add(new Exception($name . " unique")); } } } foreach ($this->self_columns() as $column) { if (!$this->{"is" . ucfirst($column->name())}()) { Exceptions::add(new Exception("verify fail")); } } $this->__save_verify__(); Exceptions::validation(); }