/** * Displays a login form on {@link SecurityException}. * * @param \ICanBoogie\Exception\RescueEvent $event * @param SecurityException $target */ public static function on_security_exception_rescue(\ICanBoogie\Exception\RescueEvent $event, SecurityException $target) { global $core; $request = $event->request; if ($request->context->dispatcher instanceof \ICanBoogie\Operation\Dispatcher && $request->is_xhr) { return; } if ($target instanceof PermissionRequired || \ICanBoogie\Routing\decontextualize($request->normalized_path) != '/admin/') { \ICanBoogie\log_error($target->getMessage()); } $block = $core->modules['users']->getBlock('connect'); $document = new \Icybee\DocumentDecorator(new \Icybee\AdminDecorator($block)); $document->body->add_class('page-slug-authenticate'); $event->response = new Response((string) $document, $target->getCode(), ['Content-Type' => 'text/html; charset=utf-8']); $event->stop(); }
/** * Redirects the request to the first available website to the user if the request matches * none. * * Only online websites are used if the user is a guest or a member. * * @param Dispatcher\BeforeDispatchEvent $event * @param Dispatcher $target */ public static function before_http_dispatcher_dispatch(Dispatcher\BeforeDispatchEvent $event, Dispatcher $target) { global $core; if ($core->site_id) { return; } $request = $event->request; if (!in_array($request->method, array(Request::METHOD_ANY, Request::METHOD_GET, Request::METHOD_HEAD))) { return; } $path = \ICanBoogie\normalize_url_path(\ICanBoogie\Routing\decontextualize($request->path)); if (strpos($path, '/api/') === 0) { return; } try { $query = $core->models['sites']->order('weight'); $user = $core->user; if ($user->is_guest || $user instanceof \Icybee\Modules\Members\Member) { $query->filter_by_status(Site::STATUS_OK); } $site = $query->one; if ($site) { $request_url = \ICanBoogie\normalize_url_path($core->site->url . $request->path); $location = \ICanBoogie\normalize_url_path($site->url . $path); # # we don't redirect if the redirect location is the same as the request URL. # if ($request_url != $location) { $query_string = $request->query_string; if ($query_string) { $location .= '?' . $query_string; } $event->response = new RedirectResponse($location, 302, array('Icybee-Redirected-By' => __CLASS__ . '::' . __FUNCTION__)); return; } } } catch (\Exception $e) { } \ICanBoogie\log_error('You are on a dummy website. You should check which websites are available or create one if none are.'); }
/** * Creates an operation instance from a request. * * An operation can be defined as a route, in which case the path of the request starts with * "/api/". An operation can also be defined using the request parameters, in which case * the {@link DESTINATION}, {@link NAME} and optionally {@link KEY} parameters are defined * within the request parameters. * * When the operation is defined as a route, the method searches for a matching route. * * If a matching route is found, the captured parameters of the matching route are merged * with the request parameters and the method tries to create an Operation instance using the * route. * * If no matching route could be found, the method tries to extract the {@link DESTINATION}, * {@link NAME} and optional {@link KEY} parameters from the route using the * `/api/:destination(/:key)/:name` pattern. If the route matches this pattern, captured * parameters are merged with the request parameters and the operation decoding continues as * if the operation was defined using parameters instead of the REST API. * * Finally, the method searches for the {@link DESTINATION}, {@link NAME} and optional * {@link KEY} parameters within the request parameters to create the Operation instance. * * If no operation was found in the request, the method returns null. * * * Instancing using the matching route * ----------------------------------- * * The matching route must define either the class of the operation instance (by defining the * `class` key) or a callback that would create the operation instance (by defining the * `callback` key). * * If the route defines the instance class, it is used to create the instance. Otherwise, the * callback is used to create the instance. * * * Instancing using the request parameters * --------------------------------------- * * The operation destination (specified by the {@link DESTINATION} parameter) is the id of the * destination module. The class and the operation name (specified by the {@link NAME} * parameter) are used to search for the corresponding operation class to create the instance: * * ICanBoogie\<normalized_module_id>\<normalized_operation_name>Operation * * The inheritance of the module class is used the find a suitable class. For example, * these are the classes tried for the "articles" module and the "save" operation: * * ICanBoogie\Modules\Articles\SaveOperation * ICanBoogie\Modules\Contents\SaveOperation * ICanBoogie\Modules\Nodes\SaveOperation * * An instance of the found class is created with the request arguments and returned. If the * class could not be found to create the operation instance, an exception is raised. * * @param Request $request The request parameters. * * @throws \BadMethodCallException when the destination module or the operation name is * not defined for a module operation. * * @throws NotFound if the operation is not found. * * @return Operation|null The decoded operation or null if no operation was found. */ protected static function from_request(Request $request) { $path = \ICanBoogie\Routing\decontextualize($request->path); $extension = $request->extension; if ($extension == 'json') { $path = substr($path, 0, -5); $request->headers['Accept'] = 'application/json'; $request->headers['X-Requested-With'] = 'XMLHttpRequest'; // FIXME-20110925: that's not very nice } else { if ($extension == 'xml') { $path = substr($path, 0, -4); $request->headers['Accept'] = 'application/xml'; $request->headers['X-Requested-With'] = 'XMLHttpRequest'; // FIXME-20110925: that's not very nice } } $path = rtrim($path, '/'); if (substr($path, 0, self::RESTFUL_BASE_LENGTH) == self::RESTFUL_BASE) { $operation = static::from_route($request, $path); if ($operation) { return $operation; } if ($request->is_patch) { preg_match('#^([^/]+)/(\\d+)$#', substr($path, self::RESTFUL_BASE_LENGTH), $matches); if (!$matches) { throw new NotFound(format('Unknown operation %operation.', ['operation' => $path])); } list(, $module_id, $operation_key) = $matches; $operation_name = 'patch'; } else { # # We could not find a matching route, we try to extract the DESTINATION, NAME and # optional KEY from the URI. # preg_match('#^([a-z\\.\\-]+)/(([^/]+)/)?([a-zA-Z0-9_\\-]+)$#', substr($path, self::RESTFUL_BASE_LENGTH), $matches); if (!$matches) { throw new NotFound(format('Unknown operation %operation.', ['operation' => $path])); } list(, $module_id, , $operation_key, $operation_name) = $matches; } if (empty(\ICanBoogie\app()->modules->descriptors[$module_id])) { throw new NotFound(format('Unknown operation %operation.', ['operation' => $path])); } if ($operation_key) { $request[self::KEY] = $operation_key; } return static::from_module_request($request, $module_id, $operation_name); } $module_id = $request[self::DESTINATION]; $operation_name = $request[self::NAME]; if (!$module_id && !$operation_name) { return null; } else { if (!$module_id) { throw new \BadMethodCallException("The operation's destination is required."); } else { if (!$operation_name) { throw new \BadMethodCallException("The operation's name is required."); } } } return static::from_module_request($request, $module_id, $operation_name); }