PK!5zzbase/endpoint/index.phpnu[controller->get_full_name()}/{id}"; } public function get_public_name() { return ''; } public function get_items( $request ) { return $this->controller->get_items( $request ); } public function get_item( $id, $request ) { return $this->controller->get_item( $request ); } public function create_items( $request ) { return $this->controller->create_items( $request ); } public function create_item( $id, $request ) { return $this->controller->create_item( $request ); } public function update_items( $request ) { return $this->controller->update_items( $request ); } public function update_item( $id, $request ) { return $this->controller->update_item( $request ); } public function delete_items( $request ) { return $this->controller->delete_items( $request ); } public function delete_item( $id, $request ) { return $this->controller->delete_item( $request ); } public function register_items_route( $methods = WP_REST_Server::READABLE, $args = [] ) { parent::register_items_route( $methods, array_merge( $this->controller->get_items_args( $methods ), $args ) ); } public function register_item_route( $methods = WP_REST_Server::READABLE, $args = [], $route = '/' ) { parent::register_item_route( $methods, array_merge( $this->controller->get_item_args( $methods ), $args ), $route ); } } PK!z4xx$base/endpoint/index/all-children.phpnu[controller->get_name() . '/index'; } /* * Retrieves a result(s) of all controller endpoint(s), items. * * Run overall endpoints of the current controller. * * Example, scenario: * 'settings' - controller * 'settings/products' - endpoint * 'settings/partners' - endpoint * Result: * [ * 'products' => [ * 0 => ... * 1 => ... * ], * 'partners' => [ * 0 => ... * 1 => ... * ], * ] */ public function get_items( $request ) { $response = []; foreach ( $this->controller->get_sub_controllers() as $controller ) { $controller_route = $this->get_controller()->get_base_route() . '/' . $controller->get_name(); $result = Manager::instance()->run_request( $controller_route ); if ( ! $result->is_error() ) { $response[ $controller->get_name() ] = $result->get_data(); } } foreach ( $this->controller->endpoints as $endpoint ) { // Skip self. if ( $endpoint === $this ) { continue; } $result = Manager::instance()->run_request( $endpoint->get_base_route() ); if ( ! $result->is_error() ) { $response[ $endpoint->get_name() ] = $result->get_data(); } } return $response; } } PK!mx*base/endpoint/index/sub-index-endpoint.phpnu[controller->get_parent()->get_name() . '/{id}/' . $this->controller->get_name() . '/{sub_id}'; } public function get_base_route() { $parent_controller = $this->controller->get_parent(); $parent_index_endpoint = $parent_controller->index_endpoint; $parent_controller_route = ''; // In case `$parent_index_endpoint` is AllChildren, it cannot support id_arg_name. if ( ! $parent_index_endpoint instanceof AllChildren ) { $parent_controller_route = "(?P<{$parent_index_endpoint->id_arg_name}>[\w]+)"; } return untrailingslashit('/' . implode( '/', array_filter( [ trim( $parent_index_endpoint->get_base_route(), '/' ), $parent_controller_route, $this->controller->get_name(), $this->get_public_name(), ] ) ) ); } } PK!>7 base/endpoint.phpnu[controller; } /** * Get current parent. * * @return \Elementor\Data\V2\Base\Controller|\Elementor\Data\V2\Base\Endpoint */ public function get_parent() { return $this->parent; } /** * Get public name. * * @return string */ public function get_public_name() { return $this->get_name(); } /** * Get full command name ( including index ). * * @return string */ public function get_full_command() { $parent = $this->get_parent(); if ( $parent instanceof Controller ) { return $this->controller->get_full_name() . '/' . $this->get_name(); } return $this->get_name_ancestry(); } /** * Get name ancestry format, example: 'alpha/beta/delta'. * * @return string */ public function get_name_ancestry() { $ancestors = $this->get_ancestors(); $ancestors_names = []; foreach ( $ancestors as $ancestor ) { $ancestors_names [] = $ancestor->get_name(); } return implode( '/', $ancestors_names ); } /** * Register sub endpoint. * * @param \Elementor\Data\V2\Base\Endpoint $endpoint * * @return \Elementor\Data\V2\Base\Endpoint */ public function register_sub_endpoint( Endpoint $endpoint ) { $command = $endpoint->get_full_command(); $format = $endpoint->get_format(); $this->sub_endpoints[ $command ] = $endpoint; Manager::instance()->register_endpoint_format( $command, $format ); return $endpoint; } /** * Get ancestors. * * @return \Elementor\Data\V2\Base\Endpoint[] */ private function get_ancestors() { $ancestors = []; $current = $this; do { if ( $current ) { $ancestors [] = $current; } $current = $current->get_parent(); } while ( $current ); return array_reverse( $ancestors ); } /** * Endpoint constructor. * * @param \Elementor\Data\V2\Base\Controller|\Elementor\Data\V2\Base\Endpoint $parent * @param string $route */ public function __construct( $parent, $route = '/' ) { $controller = $parent; $this->parent = $parent; // In case, its behave like sub-endpoint. if ( ! ( $parent instanceof Controller ) ) { $controller = $parent->get_controller(); } parent::__construct( $controller, $route ); } } PK!Hcggbase/processor.phpnu[controller = $controller; } } PK!))base/base-route.phpnu[ '/' * 'abc' => '/abc/' * '/abc' => '/abc/' * 'abc/' => '/abc/' * '/abc/' => '/abc/' * * @param string $route * * @return string */ private function ensure_slashes( $route ) { if ( '/' !== $route[0] ) { $route = '/' . $route; } return trailingslashit( $route ); } /** * Get base route. * This method should always return the base route starts with '/' and ends without '/'. * * @return string */ public function get_base_route() { $name = $this->get_public_name(); $parent = $this->get_parent(); $parent_base = $parent->get_base_route(); $route = '/'; if ( ! ( $parent instanceof Controller ) ) { $route = $parent->item_route ? $parent->item_route['route'] . '/' : $this->route; } return untrailingslashit( '/' . trim( $parent_base . $route . $name, '/' ) ); } /** * Get permission callback. * * By default get permission callback from the controller. * * @param \WP_REST_Request $request Full data about the request. * * @return boolean */ public function get_permission_callback( $request ) { return $this->controller->get_permission_callback( $request ); } /** * Retrieves a collection of items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function get_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Retrieves one item from the collection. * * @param string $id * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function get_item( $id, $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Creates multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function create_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Creates one item. * * @param string $id id of request item. * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function create_item( $id, $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Updates multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function update_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Updates one item. * * @param string $id id of request item. * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function update_item( $id, $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Delete multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function delete_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Delete one item. * * @param string $id id of request item. * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function delete_item( $id, $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Register the endpoint. * * By default: register get items route. */ protected function register() { $this->register_items_route(); } protected function register_route( $route = '', $methods = WP_REST_Server::READABLE, $args = [] ) { if ( ! in_array( $methods, self::AVAILABLE_METHODS, true ) ) { trigger_error( "Invalid method: '$methods'.", E_USER_ERROR ); // phpcs:ignore } $route = $this->get_base_route() . $route; $this->routes [] = [ 'args' => $args, 'route' => $route, ]; /** * Determine behaviour of `base_callback()` and `get_permission_callback()`: * For `base_callback()` which applying the action. * Whether it's a one item request and should call `get_item_permission_callback()` or it's mutil items request and should call `get_items_permission_callback()`. */ $is_multi = ! empty( $args['is_multi'] ); if ( $is_multi ) { unset( $args['is_multi'] ); } $callback = function ( $request ) use ( $methods, $args, $is_multi ) { return $this->base_callback( $methods, $request, $is_multi ); }; return register_rest_route( $this->controller->get_namespace(), $route, [ [ 'args' => $args, 'methods' => $methods, 'callback' => $callback, 'permission_callback' => function ( $request ) { return $this->get_permission_callback( $request ); }, ], ] ); } /** * Register items route. * * @param string $methods * @param array $args */ public function register_items_route( $methods = WP_REST_Server::READABLE, $args = [] ) { $args['is_multi'] = true; $this->register_route( '', $methods, $args ); } /** * Register item route. * * @param string $route * @param array $args * @param string $methods */ public function register_item_route( $methods = WP_REST_Server::READABLE, $args = [], $route = '/' ) { if ( ! empty( $args['id_arg_name'] ) ) { $this->id_arg_name = $args['id_arg_name']; unset( $args['id_arg_name'] ); } if ( ! empty( $args['id_arg_type_regex'] ) ) { $this->id_arg_type_regex = $args['id_arg_type_regex']; unset( $args['id_arg_type_regex'] ); } $args = array_merge( [ $this->id_arg_name => [ 'description' => 'Unique identifier for the object.', 'type' => 'string', 'required' => true, ], ], $args ); $route .= '(?P<' . $this->id_arg_name . '>' . $this->id_arg_type_regex . ')'; $this->item_route = [ 'args' => $args, 'route' => $route, ]; $this->register_route( $route, $methods, $args ); } /** * Base callback. * All reset requests from the client should pass this function. * * @param string $methods * @param \WP_REST_Request $request * @param bool $is_multi * @param array $args * * @return mixed|\WP_Error|\WP_HTTP_Response|\WP_REST_Response */ public function base_callback( $methods, $request, $is_multi = false, $args = [] ) { if ( $request ) { $json_params = $request->get_json_params(); if ( $json_params ) { $request->set_body_params( $json_params ); } } $args = wp_parse_args( $args, [ 'is_debug' => ( defined( 'WP_DEBUG' ) && WP_DEBUG ), ] ); $result = new \WP_Error( 'invalid_methods', 'route not supported.' ); $request->set_param( 'is_multi', $is_multi ); try { switch ( $methods ) { case WP_REST_Server::READABLE: $result = $is_multi ? $this->get_items( $request ) : $this->get_item( $request->get_param( 'id' ), $request ); break; case WP_REST_Server::CREATABLE: $result = $is_multi ? $this->create_items( $request ) : $this->create_item( $request->get_param( 'id' ), $request ); break; case WP_REST_Server::EDITABLE: $result = $is_multi ? $this->update_items( $request ) : $this->update_item( $request->get_param( 'id' ), $request ); break; case WP_REST_Server::DELETABLE: $result = $is_multi ? $this->delete_items( $request ) : $this->delete_item( $request->get_param( 'id' ), $request ); break; } } catch ( Data_Exception $e ) { $result = $e->to_wp_error(); } catch ( \Exception $e ) { if ( empty( $args['is_debug'] ) ) { $result = ( new Error_500() )->to_wp_error(); } else { // For frontend. $exception_mapping = [ 'trace' => $e->getTrace(), 'file' => $e->getFile(), 'line' => $e->getLine(), ]; $e->debug = $exception_mapping; $result = ( new Data_Exception( $e->getMessage(), $e->getCode(), $e ) )->to_wp_error(); } } return rest_ensure_response( $result ); } /** * Constructor. * * run `$this->register()`. * * @param \Elementor\Data\V2\Base\Controller $controller * @param string $route */ protected function __construct( Controller $controller, $route ) { $this->controller = $controller; $this->route = $this->ensure_slashes( $route ); $this->register(); } } PK!e!!base/processor/after.phpnu[parent ) { return $this->get_name(); } return $this->parent->get_name() . '/' . $this->get_name(); } /** * Get controller namespace. * * @return string */ public function get_namespace() { return $this->namespace; } /** * Get controller reset base. * * @return string */ public function get_base_route() { if ( ! $this->parent ) { return $this->rest_base; } return $this->parent->get_base_route() . '/' . $this->get_name(); } /** * Get controller route. * * @return string */ public function get_controller_route() { return $this->get_namespace() . '/' . $this->get_base_route(); } /** * Retrieves rest route(s) index for current controller. * * @return \WP_REST_Response|\WP_Error */ public function get_controller_index() { $server = rest_get_server(); $routes = $server->get_routes(); $endpoints = array_intersect_key( $server->get_routes(), $routes ); $controller_route = $this->get_controller_route(); array_walk( $endpoints, function ( &$item, $endpoint ) use ( &$endpoints, $controller_route ) { if ( ! strstr( $endpoint, $controller_route ) ) { unset( $endpoints[ $endpoint ] ); } } ); $data = [ 'namespace' => $this->get_namespace(), 'controller' => $controller_route, 'routes' => $server->get_data_for_routes( $endpoints ), ]; $response = rest_ensure_response( $data ); // Link to the root index. $response->add_link( 'up', rest_url( '/' ) ); return $response; } /** * Get items args of index endpoint. * * Is method is used when `get_collection_params()` is not enough, and need of knowing the methods is required. * * @param string $methods * * @return array */ public function get_items_args( $methods ) { if ( \WP_REST_Server::READABLE === $methods ) { return $this->get_collection_params(); } return []; } /** * Get item args of index endpoint. * * @param string $methods * * @return array */ public function get_item_args( $methods ) { return []; } /** * Get permission callback. * * Default controller permission callback. * By default endpoint will inherit the permission callback from the controller. * * @param \WP_REST_Request $request * * @return bool */ public function get_permission_callback( $request ) { $is_multi = (bool) $request->get_param( 'is_multi' ); $result = false; // The function is public since endpoint need to access it. // Utilize 'WP_REST_Controller' get_permission_check methods. switch ( $request->get_method() ) { case 'GET': $result = $is_multi ? $this->get_items_permissions_check( $request ) : $this->get_item_permissions_check( $request ); break; case 'POST': $result = $is_multi ? $this->create_items_permissions_check( $request ) : $this->create_item_permissions_check( $request ); break; case 'UPDATE': case 'PUT': case 'PATCH': $result = $is_multi ? $this->update_items_permissions_check( $request ) : $this->update_item_permissions_check( $request ); break; case 'DELETE': $result = $is_multi ? $this->delete_items_permissions_check( $request ) : $this->delete_item_permissions_check( $request ); break; } if ( $result instanceof \WP_Error ) { throw new WP_Error_Exception( $result ); } return $result; } /** * Checks if a given request has access to create items. ** * * @param \WP_REST_Request $request Full details about the request. * * @return true|\WP_Error True if the request has access to create items, WP_Error object otherwise. */ public function create_items_permissions_check( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Checks if a given request has access to update items. * * @param \WP_REST_Request $request Full details about the request. * * @return true|\WP_Error True if the request has access to update the item, WP_Error object otherwise. */ public function update_items_permissions_check( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Checks if a given request has access to delete items. * * @param \WP_REST_Request $request Full details about the request. * * @return true|\WP_Error True if the request has access to delete the item, WP_Error object otherwise. */ public function delete_items_permissions_check( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } public function get_items( $request ) { return $this->get_controller_index(); } /** * Creates multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function create_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Updates multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function update_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Delete multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function delete_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Get the parent controller. * * @return \Elementor\Data\V2\Base\Controller|null */ public function get_parent() { return $this->parent; } /** * Get sub controller(s). * * @return \Elementor\Data\V2\Base\Controller[] */ public function get_sub_controllers() { return $this->sub_controllers; } /** * Get processors. * * @param string $command * * @return \Elementor\Data\V2\Base\Processor[] */ public function get_processors( $command ) { $result = []; if ( isset( $this->processors[ $command ] ) ) { $result = $this->processors[ $command ]; } return $result; } /** * Register processors. */ public function register_processors() { } /** * Register index endpoint. */ protected function register_index_endpoint() { if ( ! $this->parent ) { $this->register_endpoint( new Endpoint\Index( $this ) ); return; } $this->register_endpoint( new Endpoint\Index\Sub_Index_Endpoint( $this ) ); } /** * Register endpoint. * * @param \Elementor\Data\V2\Base\Endpoint $endpoint * * @return \Elementor\Data\V2\Base\Endpoint */ protected function register_endpoint( Endpoint $endpoint ) { $command = $endpoint->get_full_command(); if ( $endpoint instanceof Endpoint\Index ) { $this->index_endpoint = $endpoint; } else { $this->endpoints[ $command ] = $endpoint; } $format = $endpoint->get_format(); // `$e.data.registerFormat()`. Manager::instance()->register_endpoint_format( $command, $format ); return $endpoint; } /** * Register a processor. * * That will be later attached to the endpoint class. * * @param Processor $processor * * @return \Elementor\Data\V2\Base\Processor $processor_instance */ protected function register_processor( Processor $processor ) { $command = $processor->get_command(); if ( ! isset( $this->processors[ $command ] ) ) { $this->processors[ $command ] = []; } $this->processors[ $command ] [] = $processor; return $processor; } /** * Register. * * Endpoints & processors. */ protected function register() { $this->register_index_endpoint(); $this->register_endpoints(); // Aka hooks. $this->register_processors(); } /** * Get collection params by 'additionalProperties' context. * * @param string $context * * @return array */ protected function get_collection_params_by_additional_props_context( $context ) { $result = []; $collection_params = $this->get_collection_params(); foreach ( $collection_params as $collection_param_key => $collection_param ) { if ( isset( $collection_param['additionalProperties']['context'] ) && $context === $collection_param['additionalProperties']['context'] ) { $result[ $collection_param_key ] = $collection_param; } } return $result; } /** * When `$this->get_parent_name` is extended, the controller will have a parent, and will know to behave like a sub-controller. * * @param string $parent_name */ private function act_as_sub_controller( $parent_name ) { $this->parent = Manager::instance()->get_controller( $parent_name ); if ( ! $this->parent ) { trigger_error( "Cannot find parent controller: '$parent_name'", E_USER_ERROR ); // phpcs:ignore } $this->parent->sub_controllers [] = $this; } /** * Controller constructor. * * Register endpoints on 'rest_api_init'. */ public function __construct() { $this->namespace = static::get_default_namespace() . '/v' . static::get_default_version(); $this->rest_base = $this->get_name(); add_action( 'rest_api_init', function () { $this->register(); // Because 'register' is protected. } ); /** * Since all actions were removed for custom internal REST server. * Re-add the actions. */ add_action( 'elementor_rest_api_before_init', function () { add_action( 'rest_api_init', function () { $this->register(); } ); } ); $parent_name = $this->get_parent_name(); if ( $parent_name ) { $this->act_as_sub_controller( $parent_name ); } } } PK!_#[[base/exceptions/error-404.phpnu[get_error_message(), $wp_error->get_error_code(), [ 'status' => $wp_error->get_error_code(), ] ); } } PK!Uhmm"base/exceptions/data-exception.phpnu[ '', 'data' => [], ]; public function get_code() { return 'reset-http-error'; } public function get_message() { return '501 Not Implemented'; } public function get_data() { return [ 'status' => $this->get_http_error_code(), // 'status' is used by WP to pass the http error code. ]; } public function to_wp_error() { return new \WP_Error( $this->custom_data['code'], $this->message, $this->custom_data['data'] ); } protected function get_http_error_code() { return 501; // 501 Not Implemented } protected function apply() {} public function __construct( $message = '', $code = '', $data = [] ) { $this->message = empty( $message ) ? $this->get_message() : $message; $this->custom_data['code'] = empty( $code ) ? $this->get_code() : $code; $this->custom_data['data'] = empty( $data ) ? $this->get_data() : $data; parent::__construct( $this->message, 0, null ); $this->apply(); } } PK!SJnnbase/exceptions/error-500.phpnu[controllers; } /** * @param string $name * * @return \Elementor\Data\V2\Base\Controller|false */ public function get_controller( $name ) { if ( isset( $this->controllers[ $name ] ) ) { return $this->controllers[ $name ]; } return false; } private function get_cache( $key ) { return self::get_items( $this->cache, $key ); } private function set_cache( $key, $value ) { $this->cache[ $key ] = $value; } /** * Register controller. * * @param \Elementor\Data\V2\Base\Controller $controller_instance * * @return \Elementor\Data\V2\Base\Controller */ public function register_controller( Controller $controller_instance ) { $this->controllers[ $controller_instance->get_name() ] = $controller_instance; return $controller_instance; } /** * Register endpoint format. * * @param string $command * @param string $format * */ public function register_endpoint_format( $command, $format ) { $this->command_formats[ $command ] = untrailingslashit( $format ); } /** * Find controller instance. * * By given command name. * * @param string $command * * @return false|\Elementor\Data\V2\Base\Controller */ public function find_controller_instance( $command ) { $command_parts = explode( '/', $command ); $assumed_command_parts = []; foreach ( $command_parts as $command_part ) { $assumed_command_parts [] = $command_part; foreach ( $this->controllers as $controller_name => $controller ) { $assumed_command = implode( '/', $assumed_command_parts ); if ( $assumed_command === $controller_name ) { return $controller; } } } return false; } /** * Command extract args. * * @param string $command * @param array $args * * @return \stdClass */ public function command_extract_args( $command, $args = [] ) { $result = new \stdClass(); $result->command = $command; $result->args = $args; if ( false !== strpos( $command, '?' ) ) { $command_parts = explode( '?', $command ); $pure_command = $command_parts[0]; $query_string = $command_parts[1]; parse_str( $query_string, $temp ); $result->command = untrailingslashit( $pure_command ); $result->args = array_merge( $args, $temp ); } return $result; } /** * Command to endpoint. * * Format is required otherwise $command will returned. * * @param string $command * @param string $format * @param array $args * * @return string endpoint */ public function command_to_endpoint( $command, $format, $args ) { $endpoint = $command; if ( $format ) { $formatted = $format; array_walk( $args, function ( $val, $key ) use ( &$formatted ) { $formatted = str_replace( '{' . $key . '}', $val, $formatted ); } ); // Remove remaining format if not requested via `$args`. if ( strstr( $formatted, '/{' ) ) { /** * Example: * $command = 'example/documents'; * $format = 'example/documents/{document_id}/elements/{element_id}'; * $formatted = 'example/documents/1618/elements/{element_id}'; * Result: * $formatted = 'example/documents/1618/elements'; */ $formatted = substr( $formatted, 0, strpos( $formatted, '/{' ) ); } $endpoint = $formatted; } return $endpoint; } /** * Run server. * * Init WordPress reset api. * * @return \WP_REST_Server */ public function run_server() { /** * If run_server() called means, that rest api is simulated from the backend. */ $this->is_internal = true; if ( ! $this->server ) { // Remove all 'rest_api_init' actions. remove_all_actions( 'rest_api_init' ); // Call custom reset api loader. do_action( 'elementor_rest_api_before_init' ); $this->server = rest_get_server(); // Init API. } return $this->server; } /** * Kill server. * * Free server and controllers. */ public function kill_server() { global $wp_rest_server; $this->controllers = []; $this->command_formats = []; $this->server = false; $this->is_internal = false; $this->cache = []; $wp_rest_server = false; } /** * Run processor. * * @param \Elementor\Data\V2\Base\Processor $processor * @param array $data * * @return mixed */ public function run_processor( $processor, $data ) { if ( call_user_func_array( [ $processor, 'get_conditions' ], $data ) ) { return call_user_func_array( [ $processor, 'apply' ], $data ); } return null; } /** * Run processors. * * Filter them by class. * * @param \Elementor\Data\V2\Base\Processor[] $processors * @param string $filter_by_class * @param array $data * * @return false|array */ public function run_processors( $processors, $filter_by_class, $data ) { foreach ( $processors as $processor ) { if ( $processor instanceof $filter_by_class ) { if ( Processor\Before::class === $filter_by_class ) { $this->run_processor( $processor, $data ); } elseif ( Processor\After::class === $filter_by_class ) { $result = $this->run_processor( $processor, $data ); if ( $result ) { $data[1] = $result; } } else { trigger_error( "Invalid processor filter: '\${ $filter_by_class }'" ); // phpcs:ignore break; } } } return isset( $data[1] ) ? $data[1] : false; } /** * Run request. * * Simulate rest API from within the backend. * Use args as query. * * @param string $endpoint * @param array $args * @param string $method * @param string $namespace (optional) * @param string $version (optional) * * @return \WP_REST_Response */ public function run_request( $endpoint, $args = [], $method = \WP_REST_Server::READABLE, $namespace = self::ROOT_NAMESPACE, $version = self::VERSION ) { $this->run_server(); $endpoint = '/' . $namespace . '/v' . $version . '/' . trim( $endpoint, '/' ); // Run reset api. $request = new \WP_REST_Request( $method, $endpoint ); if ( 'GET' === $method ) { $request->set_query_params( $args ); } else { $request->set_body_params( $args ); } return rest_do_request( $request ); } /** * Run endpoint. * * Wrapper for `$this->run_request` return `$response->getData()` instead of `$response`. * * @param string $endpoint * @param array $args * @param string $method * * @return array */ public function run_endpoint( $endpoint, $args = [], $method = 'GET' ) { // The method become public since it used in `Elementor\Data\V2\Base\Endpoint\Index\AllChildren`. $response = $this->run_request( $endpoint, $args, $method ); return $response->get_data(); } /** * Run ( simulated reset api ). * * Do: * Init reset server. * Run before processors. * Run command as reset api endpoint from internal. * Run after processors. * * @param string $command * @param array $args * @param string $method * * @return array|false processed result */ public function run( $command, $args = [], $method = 'GET' ) { $key = crc32( $command . '-' . wp_json_encode( $args ) . '-' . $method ); $cache = $this->get_cache( $key ); if ( $cache ) { return $cache; } $this->run_server(); $controller_instance = $this->find_controller_instance( $command ); if ( ! $controller_instance ) { $this->set_cache( $key, [] ); return []; } $extracted_command = $this->command_extract_args( $command, $args ); $command = $extracted_command->command; $args = $extracted_command->args; $format = isset( $this->command_formats[ $command ] ) ? $this->command_formats[ $command ] : false; $command_processors = $controller_instance->get_processors( $command ); $endpoint = $this->command_to_endpoint( $command, $format, $args ); $this->run_processors( $command_processors, Processor\Before::class, [ $args ] ); $response = $this->run_request( $endpoint, $args, $method ); $result = $response->get_data(); if ( $response->is_error() ) { $this->set_cache( $key, [] ); return []; } $result = $this->run_processors( $command_processors, Processor\After::class, [ $args, $result ] ); $this->set_cache( $key, $result ); return $result; } public function is_internal() { return $this->is_internal; } } PK!C8LL Validator.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a8 */ /** * Private validation class used by PEAR_PackageFile_v2 - do not use directly, its * sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a8 * @access private */ class PEAR_PackageFile_v2_Validator { /** * @var array */ var $_packageInfo; /** * @var PEAR_PackageFile_v2 */ var $_pf; /** * @var PEAR_ErrorStack */ var $_stack; /** * @var int */ var $_isValid = 0; /** * @var int */ var $_filesValid = 0; /** * @var int */ var $_curState = 0; /** * @param PEAR_PackageFile_v2 * @param int */ function validate(&$pf, $state = PEAR_VALIDATE_NORMAL) { $this->_pf = &$pf; $this->_curState = $state; $this->_packageInfo = $this->_pf->getArray(); $this->_isValid = $this->_pf->_isValid; $this->_filesValid = $this->_pf->_filesValid; $this->_stack = &$pf->_stack; $this->_stack->getErrors(true); if (($this->_isValid & $state) == $state) { return true; } if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) { return false; } if (!isset($this->_packageInfo['attribs']['version']) || ($this->_packageInfo['attribs']['version'] != '2.0' && $this->_packageInfo['attribs']['version'] != '2.1') ) { $this->_noPackageVersion(); } $structure = array( 'name', 'channel|uri', '*extends', // can't be multiple, but this works fine 'summary', 'description', '+lead', // these all need content checks '*developer', '*contributor', '*helper', 'date', '*time', 'version', 'stability', 'license->?uri->?filesource', 'notes', 'contents', //special validation needed '*compatible', 'dependencies', //special validation needed '*usesrole', '*usestask', // reserve these for 1.4.0a1 to implement // this will allow a package.xml to gracefully say it // needs a certain package installed in order to implement a role or task '*providesextension', '*srcpackage|*srcuri', '+phprelease|+extsrcrelease|+extbinrelease|' . '+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed '*changelog', ); $test = $this->_packageInfo; if (isset($test['dependencies']) && isset($test['dependencies']['required']) && isset($test['dependencies']['required']['pearinstaller']) && isset($test['dependencies']['required']['pearinstaller']['min']) && '1.10.16' != '@package' . '_version@' && version_compare('1.10.16', $test['dependencies']['required']['pearinstaller']['min'], '<') ) { $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']); return false; } // ignore post-installation array fields if (array_key_exists('filelist', $test)) { unset($test['filelist']); } if (array_key_exists('_lastmodified', $test)) { unset($test['_lastmodified']); } if (array_key_exists('#binarypackage', $test)) { unset($test['#binarypackage']); } if (array_key_exists('old', $test)) { unset($test['old']); } if (array_key_exists('_lastversion', $test)) { unset($test['_lastversion']); } if (!$this->_stupidSchemaValidate($structure, $test, '')) { return false; } if (empty($this->_packageInfo['name'])) { $this->_tagCannotBeEmpty('name'); } $test = isset($this->_packageInfo['uri']) ? 'uri' :'channel'; if (empty($this->_packageInfo[$test])) { $this->_tagCannotBeEmpty($test); } if (is_array($this->_packageInfo['license']) && (!isset($this->_packageInfo['license']['_content']) || empty($this->_packageInfo['license']['_content']))) { $this->_tagCannotBeEmpty('license'); } elseif (empty($this->_packageInfo['license'])) { $this->_tagCannotBeEmpty('license'); } if (empty($this->_packageInfo['summary'])) { $this->_tagCannotBeEmpty('summary'); } if (empty($this->_packageInfo['description'])) { $this->_tagCannotBeEmpty('description'); } if (empty($this->_packageInfo['date'])) { $this->_tagCannotBeEmpty('date'); } if (empty($this->_packageInfo['notes'])) { $this->_tagCannotBeEmpty('notes'); } if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) { $this->_tagCannotBeEmpty('time'); } if (isset($this->_packageInfo['dependencies'])) { $this->_validateDependencies(); } if (isset($this->_packageInfo['compatible'])) { $this->_validateCompatible(); } if (!isset($this->_packageInfo['bundle'])) { if (empty($this->_packageInfo['contents'])) { $this->_tagCannotBeEmpty('contents'); } if (!isset($this->_packageInfo['contents']['dir'])) { $this->_filelistMustContainDir('contents'); return false; } if (isset($this->_packageInfo['contents']['file'])) { $this->_filelistCannotContainFile('contents'); return false; } } $this->_validateMaintainers(); $this->_validateStabilityVersion(); $fail = false; if (array_key_exists('usesrole', $this->_packageInfo)) { $roles = $this->_packageInfo['usesrole']; if (!is_array($roles) || !isset($roles[0])) { $roles = array($roles); } foreach ($roles as $role) { if (!isset($role['role'])) { $this->_usesroletaskMustHaveRoleTask('usesrole', 'role'); $fail = true; } else { if (!isset($role['channel'])) { if (!isset($role['uri'])) { $this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole'); $fail = true; } } elseif (!isset($role['package'])) { $this->_usesroletaskMustHavePackage($role['role'], 'usesrole'); $fail = true; } } } } if (array_key_exists('usestask', $this->_packageInfo)) { $roles = $this->_packageInfo['usestask']; if (!is_array($roles) || !isset($roles[0])) { $roles = array($roles); } foreach ($roles as $role) { if (!isset($role['task'])) { $this->_usesroletaskMustHaveRoleTask('usestask', 'task'); $fail = true; } else { if (!isset($role['channel'])) { if (!isset($role['uri'])) { $this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask'); $fail = true; } } elseif (!isset($role['package'])) { $this->_usesroletaskMustHavePackage($role['task'], 'usestask'); $fail = true; } } } } if ($fail) { return false; } $list = $this->_packageInfo['contents']; if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) { $this->_multipleToplevelDirNotAllowed(); return $this->_isValid = 0; } $this->_validateFilelist(); $this->_validateRelease(); if (!$this->_stack->hasErrors()) { $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true); if (PEAR::isError($chan)) { $this->_unknownChannel($this->_pf->getChannel()); } else { $valpack = $chan->getValidationPackage(); // for channel validator packages, always use the default PEAR validator. // otherwise, they can't be installed or packaged $validator = $chan->getValidationObject($this->_pf->getPackage()); if (!$validator) { $this->_stack->push(__FUNCTION__, 'error', array('channel' => $chan->getName(), 'package' => $this->_pf->getPackage(), 'name' => $valpack['_content'], 'version' => $valpack['attribs']['version']), 'package "%channel%/%package%" cannot be properly validated without ' . 'validation package "%channel%/%name%-%version%"'); return $this->_isValid = 0; } $validator->setPackageFile($this->_pf); $validator->validate($state); $failures = $validator->getFailures(); foreach ($failures['errors'] as $error) { $this->_stack->push(__FUNCTION__, 'error', $error, 'Channel validator error: field "%field%" - %reason%'); } foreach ($failures['warnings'] as $warning) { $this->_stack->push(__FUNCTION__, 'warning', $warning, 'Channel validator warning: field "%field%" - %reason%'); } } } $this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error'); if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) { if ($this->_pf->getPackageType() == 'bundle') { if ($this->_analyzeBundledPackages()) { $this->_filesValid = $this->_pf->_filesValid = true; } else { $this->_pf->_isValid = $this->_isValid = 0; } } else { if (!$this->_analyzePhpFiles()) { $this->_pf->_isValid = $this->_isValid = 0; } else { $this->_filesValid = $this->_pf->_filesValid = true; } } } if ($this->_isValid) { return $this->_pf->_isValid = $this->_isValid = $state; } return $this->_pf->_isValid = $this->_isValid = 0; } function _stupidSchemaValidate($structure, $xml, $root) { if (!is_array($xml)) { $xml = array(); } $keys = array_keys($xml); reset($keys); $key = current($keys); while ($key == 'attribs' || $key == '_contents') { $key = next($keys); } $unfoundtags = $optionaltags = array(); $ret = true; $mismatch = false; foreach ($structure as $struc) { if ($key) { $tag = $xml[$key]; } $test = $this->_processStructure($struc); if (isset($test['choices'])) { $loose = true; foreach ($test['choices'] as $choice) { if ($key == $choice['tag']) { $key = next($keys); while ($key == 'attribs' || $key == '_contents') { $key = next($keys); } $unfoundtags = $optionaltags = array(); $mismatch = false; if ($key && $key != $choice['tag'] && isset($choice['multiple'])) { $unfoundtags[] = $choice['tag']; $optionaltags[] = $choice['tag']; if ($key) { $mismatch = true; } } $ret &= $this->_processAttribs($choice, $tag, $root); continue 2; } else { $unfoundtags[] = $choice['tag']; $mismatch = true; } if (!isset($choice['multiple']) || $choice['multiple'] != '*') { $loose = false; } else { $optionaltags[] = $choice['tag']; } } if (!$loose) { $this->_invalidTagOrder($unfoundtags, $key, $root); return false; } } else { if ($key != $test['tag']) { if (isset($test['multiple']) && $test['multiple'] != '*') { $unfoundtags[] = $test['tag']; $this->_invalidTagOrder($unfoundtags, $key, $root); return false; } else { if ($key) { $mismatch = true; } $unfoundtags[] = $test['tag']; $optionaltags[] = $test['tag']; } if (!isset($test['multiple'])) { $this->_invalidTagOrder($unfoundtags, $key, $root); return false; } continue; } else { $unfoundtags = $optionaltags = array(); $mismatch = false; } $key = next($keys); while ($key == 'attribs' || $key == '_contents') { $key = next($keys); } if ($key && $key != $test['tag'] && isset($test['multiple'])) { $unfoundtags[] = $test['tag']; $optionaltags[] = $test['tag']; $mismatch = true; } $ret &= $this->_processAttribs($test, $tag, $root); continue; } } if (!$mismatch && count($optionaltags)) { // don't error out on any optional tags $unfoundtags = array_diff($unfoundtags, $optionaltags); } if (count($unfoundtags)) { $this->_invalidTagOrder($unfoundtags, $key, $root); } elseif ($key) { // unknown tags $this->_invalidTagOrder('*no tags allowed here*', $key, $root); while ($key = next($keys)) { $this->_invalidTagOrder('*no tags allowed here*', $key, $root); } } return $ret; } function _processAttribs($choice, $tag, $context) { if (isset($choice['attribs'])) { if (!is_array($tag)) { $tag = array($tag); } $tags = $tag; if (!isset($tags[0])) { $tags = array($tags); } $ret = true; foreach ($tags as $i => $tag) { if (!is_array($tag) || !isset($tag['attribs'])) { foreach ($choice['attribs'] as $attrib) { if ($attrib[0] != '?') { $ret &= $this->_tagHasNoAttribs($choice['tag'], $context); continue 2; } } } foreach ($choice['attribs'] as $attrib) { if ($attrib[0] != '?') { if (!isset($tag['attribs'][$attrib])) { $ret &= $this->_tagMissingAttribute($choice['tag'], $attrib, $context); } } } } return $ret; } return true; } function _processStructure($key) { $ret = array(); if (count($pieces = explode('|', $key)) > 1) { $ret['choices'] = array(); foreach ($pieces as $piece) { $ret['choices'][] = $this->_processStructure($piece); } return $ret; } $multi = $key[0]; if ($multi == '+' || $multi == '*') { $ret['multiple'] = $key[0]; $key = substr($key, 1); } if (count($attrs = explode('->', $key)) > 1) { $ret['tag'] = array_shift($attrs); $ret['attribs'] = $attrs; } else { $ret['tag'] = $key; } return $ret; } function _validateStabilityVersion() { $structure = array('release', 'api'); $a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], ''); $a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], ''); if ($a) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $this->_packageInfo['version']['release'])) { $this->_invalidVersion('release', $this->_packageInfo['version']['release']); } if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $this->_packageInfo['version']['api'])) { $this->_invalidVersion('api', $this->_packageInfo['version']['api']); } if (!in_array($this->_packageInfo['stability']['release'], array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) { $this->_invalidState('release', $this->_packageInfo['stability']['release']); } if (!in_array($this->_packageInfo['stability']['api'], array('devel', 'alpha', 'beta', 'stable'))) { $this->_invalidState('api', $this->_packageInfo['stability']['api']); } } } function _validateMaintainers() { $structure = array( 'name', 'user', 'email', 'active', ); foreach (array('lead', 'developer', 'contributor', 'helper') as $type) { if (!isset($this->_packageInfo[$type])) { continue; } if (isset($this->_packageInfo[$type][0])) { foreach ($this->_packageInfo[$type] as $lead) { $this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>'); } } else { $this->_stupidSchemaValidate($structure, $this->_packageInfo[$type], '<' . $type . '>'); } } } function _validatePhpDep($dep, $installcondition = false) { $structure = array( 'min', '*max', '*exclude', ); $type = $installcondition ? '' : ''; $this->_stupidSchemaValidate($structure, $dep, $type); if (isset($dep['min'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/', $dep['min'])) { $this->_invalidVersion($type . '', $dep['min']); } } if (isset($dep['max'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/', $dep['max'])) { $this->_invalidVersion($type . '', $dep['max']); } } if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } foreach ($dep['exclude'] as $exclude) { if (!preg_match( '/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/', $exclude)) { $this->_invalidVersion($type . '', $exclude); } } } } function _validatePearinstallerDep($dep) { $structure = array( 'min', '*max', '*recommended', '*exclude', ); $this->_stupidSchemaValidate($structure, $dep, ''); if (isset($dep['min'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['min'])) { $this->_invalidVersion('', $dep['min']); } } if (isset($dep['max'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['max'])) { $this->_invalidVersion('', $dep['max']); } } if (isset($dep['recommended'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['recommended'])) { $this->_invalidVersion('', $dep['recommended']); } } if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } foreach ($dep['exclude'] as $exclude) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $exclude)) { $this->_invalidVersion('', $exclude); } } } } function _validatePackageDep($dep, $group, $type = '') { if (isset($dep['uri'])) { if (isset($dep['conflicts'])) { $structure = array( 'name', 'uri', 'conflicts', '*providesextension', ); } else { $structure = array( 'name', 'uri', '*providesextension', ); } } else { if (isset($dep['conflicts'])) { $structure = array( 'name', 'channel', '*min', '*max', '*exclude', 'conflicts', '*providesextension', ); } else { $structure = array( 'name', 'channel', '*min', '*max', '*recommended', '*exclude', '*nodefault', '*providesextension', ); } } if (isset($dep['name'])) { $type .= '' . $dep['name'] . ''; } $this->_stupidSchemaValidate($structure, $dep, '' . $group . $type); if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) || isset($dep['recommended']) || isset($dep['exclude']))) { $this->_uriDepsCannotHaveVersioning('' . $group . $type); } if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') { $this->_DepchannelCannotBeUri('' . $group . $type); } if (isset($dep['min'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['min'])) { $this->_invalidVersion('' . $group . $type . '', $dep['min']); } } if (isset($dep['max'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['max'])) { $this->_invalidVersion('' . $group . $type . '', $dep['max']); } } if (isset($dep['recommended'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['recommended'])) { $this->_invalidVersion('' . $group . $type . '', $dep['recommended']); } } if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } foreach ($dep['exclude'] as $exclude) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $exclude)) { $this->_invalidVersion('' . $group . $type . '', $exclude); } } } } function _validateSubpackageDep($dep, $group) { $this->_validatePackageDep($dep, $group, ''); if (isset($dep['providesextension'])) { $this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : ''); } if (isset($dep['conflicts'])) { $this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : ''); } } function _validateExtensionDep($dep, $group = false, $installcondition = false) { if (isset($dep['conflicts'])) { $structure = array( 'name', '*min', '*max', '*exclude', 'conflicts', ); } else { $structure = array( 'name', '*min', '*max', '*recommended', '*exclude', ); } if ($installcondition) { $type = ''; } else { $type = '' . $group . ''; } if (isset($dep['name'])) { $type .= '' . $dep['name'] . ''; } $this->_stupidSchemaValidate($structure, $dep, $type); if (isset($dep['min'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['min'])) { $this->_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '' : ''; if ($this->_stupidSchemaValidate($structure, $dep, $type)) { if ($dep['name'] == '*') { if (array_key_exists('conflicts', $dep)) { $this->_cannotConflictWithAllOs($type); } } } } function _validateArchDep($dep, $installcondition = false) { $structure = array( 'pattern', '*conflicts', ); $type = $installcondition ? '' : ''; $this->_stupidSchemaValidate($structure, $dep, $type); } function _validateInstallConditions($cond, $release) { $structure = array( '*php', '*extension', '*os', '*arch', ); if (!$this->_stupidSchemaValidate($structure, $cond, $release)) { return false; } foreach (array('php', 'extension', 'os', 'arch') as $type) { if (isset($cond[$type])) { $iter = $cond[$type]; if (!is_array($iter) || !isset($iter[0])) { $iter = array($iter); } foreach ($iter as $package) { if ($type == 'extension') { $this->{"_validate{$type}Dep"}($package, false, true); } else { $this->{"_validate{$type}Dep"}($package, true); } } } } } function _validateDependencies() { $structure = array( 'required', '*optional', '*group->name->hint' ); if (!$this->_stupidSchemaValidate($structure, $this->_packageInfo['dependencies'], '')) { return false; } foreach (array('required', 'optional') as $simpledep) { if (isset($this->_packageInfo['dependencies'][$simpledep])) { if ($simpledep == 'optional') { $structure = array( '*package', '*subpackage', '*extension', ); } else { $structure = array( 'php', 'pearinstaller', '*package', '*subpackage', '*extension', '*os', '*arch', ); } if ($this->_stupidSchemaValidate($structure, $this->_packageInfo['dependencies'][$simpledep], "<$simpledep>")) { foreach (array('package', 'subpackage', 'extension') as $type) { if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) { $iter = $this->_packageInfo['dependencies'][$simpledep][$type]; if (!isset($iter[0])) { $iter = array($iter); } foreach ($iter as $package) { if ($type != 'extension') { if (isset($package['uri'])) { if (isset($package['channel'])) { $this->_UrlOrChannel($type, $package['name']); } } else { if (!isset($package['channel'])) { $this->_NoChannel($type, $package['name']); } } } $this->{"_validate{$type}Dep"}($package, "<$simpledep>"); } } } if ($simpledep == 'optional') { continue; } foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) { if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) { $iter = $this->_packageInfo['dependencies'][$simpledep][$type]; if (!isset($iter[0])) { $iter = array($iter); } foreach ($iter as $package) { $this->{"_validate{$type}Dep"}($package); } } } } } } if (isset($this->_packageInfo['dependencies']['group'])) { $groups = $this->_packageInfo['dependencies']['group']; if (!isset($groups[0])) { $groups = array($groups); } $structure = array( '*package', '*subpackage', '*extension', ); foreach ($groups as $group) { if ($this->_stupidSchemaValidate($structure, $group, '')) { if (!PEAR_Validate::validGroupName($group['attribs']['name'])) { $this->_invalidDepGroupName($group['attribs']['name']); } foreach (array('package', 'subpackage', 'extension') as $type) { if (isset($group[$type])) { $iter = $group[$type]; if (!isset($iter[0])) { $iter = array($iter); } foreach ($iter as $package) { if ($type != 'extension') { if (isset($package['uri'])) { if (isset($package['channel'])) { $this->_UrlOrChannelGroup($type, $package['name'], $group['name']); } } else { if (!isset($package['channel'])) { $this->_NoChannelGroup($type, $package['name'], $group['name']); } } } $this->{"_validate{$type}Dep"}($package, ''); } } } } } } } function _validateCompatible() { $compat = $this->_packageInfo['compatible']; if (!isset($compat[0])) { $compat = array($compat); } $required = array('name', 'channel', 'min', 'max', '*exclude'); foreach ($compat as $package) { $type = ''; if (is_array($package) && array_key_exists('name', $package)) { $type .= '' . $package['name'] . ''; } $this->_stupidSchemaValidate($required, $package, $type); if (is_array($package) && array_key_exists('min', $package)) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $package['min'])) { $this->_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_NoBundledPackages(); } if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) { return $this->_AtLeast2BundledPackages(); } foreach ($list['bundledpackage'] as $package) { if (!is_string($package)) { $this->_bundledPackagesMustBeFilename(); } } } function _validateFilelist($list = false, $allowignore = false, $dirs = '') { $iscontents = false; if (!$list) { $iscontents = true; $list = $this->_packageInfo['contents']; if (isset($this->_packageInfo['bundle'])) { return $this->_validateBundle($list); } } if ($allowignore) { $struc = array( '*install->name->as', '*ignore->name' ); } else { $struc = array( '*dir->name->?baseinstalldir', '*file->name->role->?baseinstalldir->?md5sum' ); if (isset($list['dir']) && isset($list['file'])) { // stave off validation errors without requiring a set order. $_old = $list; if (isset($list['attribs'])) { $list = array('attribs' => $_old['attribs']); } $list['dir'] = $_old['dir']; $list['file'] = $_old['file']; } } if (!isset($list['attribs']) || !isset($list['attribs']['name'])) { $unknown = $allowignore ? '' : ''; $dirname = $iscontents ? '' : $unknown; } else { $dirname = ''; if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $list['attribs']['name']))) { // file contains .. parent directory or . cur directory $this->_invalidDirName($list['attribs']['name']); } } $res = $this->_stupidSchemaValidate($struc, $list, $dirname); if ($allowignore && $res) { $ignored_or_installed = array(); $this->_pf->getFilelist(); $fcontents = $this->_pf->getContents(); $filelist = array(); if (!isset($fcontents['dir']['file'][0])) { $fcontents['dir']['file'] = array($fcontents['dir']['file']); } foreach ($fcontents['dir']['file'] as $file) { $filelist[$file['attribs']['name']] = true; } if (isset($list['install'])) { if (!isset($list['install'][0])) { $list['install'] = array($list['install']); } foreach ($list['install'] as $file) { if (!isset($filelist[$file['attribs']['name']])) { $this->_notInContents($file['attribs']['name'], 'install'); continue; } if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) { $this->_multipleInstallAs($file['attribs']['name']); } if (!isset($ignored_or_installed[$file['attribs']['name']])) { $ignored_or_installed[$file['attribs']['name']] = array(); } $ignored_or_installed[$file['attribs']['name']][] = 1; if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file['attribs']['as']))) { // file contains .. parent directory or . cur directory references $this->_invalidFileInstallAs($file['attribs']['name'], $file['attribs']['as']); } } } if (isset($list['ignore'])) { if (!isset($list['ignore'][0])) { $list['ignore'] = array($list['ignore']); } foreach ($list['ignore'] as $file) { if (!isset($filelist[$file['attribs']['name']])) { $this->_notInContents($file['attribs']['name'], 'ignore'); continue; } if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) { $this->_ignoreAndInstallAs($file['attribs']['name']); } } } } if (!$allowignore && isset($list['file'])) { if (is_string($list['file'])) { $this->_oldStyleFileNotAllowed(); return false; } if (!isset($list['file'][0])) { // single file $list['file'] = array($list['file']); } foreach ($list['file'] as $i => $file) { if (isset($file['attribs']) && isset($file['attribs']['name'])) { if ($file['attribs']['name'][0] == '.' && $file['attribs']['name'][1] == '/') { // name is something like "./doc/whatever.txt" $this->_invalidFileName($file['attribs']['name'], $dirname); } if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file['attribs']['name']))) { // file contains .. parent directory or . cur directory $this->_invalidFileName($file['attribs']['name'], $dirname); } } if (isset($file['attribs']) && isset($file['attribs']['role'])) { if (!$this->_validateRole($file['attribs']['role'])) { if (isset($this->_packageInfo['usesrole'])) { $roles = $this->_packageInfo['usesrole']; if (!isset($roles[0])) { $roles = array($roles); } foreach ($roles as $role) { if ($role['role'] = $file['attribs']['role']) { $msg = 'This package contains role "%role%" and requires ' . 'package "%package%" to be used'; if (isset($role['uri'])) { $params = array('role' => $role['role'], 'package' => $role['uri']); } else { $params = array('role' => $role['role'], 'package' => $this->_pf->_registry-> parsedPackageNameToString(array('package' => $role['package'], 'channel' => $role['channel']), true)); } $this->_stack->push('_mustInstallRole', 'error', $params, $msg); } } } $this->_invalidFileRole($file['attribs']['name'], $dirname, $file['attribs']['role']); } } if (!isset($file['attribs'])) { continue; } $save = $file['attribs']; if ($dirs) { $save['name'] = $dirs . '/' . $save['name']; } unset($file['attribs']); if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks foreach ($file as $task => $value) { if ($tagClass = $this->_pf->getTask($task)) { if (!is_array($value) || !isset($value[0])) { $value = array($value); } foreach ($value as $v) { $ret = call_user_func(array($tagClass, 'validateXml'), $this->_pf, $v, $this->_pf->_config, $save); if (is_array($ret)) { $this->_invalidTask($task, $ret, isset($save['name']) ? $save['name'] : ''); } } } else { if (isset($this->_packageInfo['usestask'])) { $roles = $this->_packageInfo['usestask']; if (!isset($roles[0])) { $roles = array($roles); } foreach ($roles as $role) { if ($role['task'] = $task) { $msg = 'This package contains task "%task%" and requires ' . 'package "%package%" to be used'; if (isset($role['uri'])) { $params = array('task' => $role['task'], 'package' => $role['uri']); } else { $params = array('task' => $role['task'], 'package' => $this->_pf->_registry-> parsedPackageNameToString(array('package' => $role['package'], 'channel' => $role['channel']), true)); } $this->_stack->push('_mustInstallTask', 'error', $params, $msg); } } } $this->_unknownTask($task, $save['name']); } } } } } if (isset($list['ignore'])) { if (!$allowignore) { $this->_ignoreNotAllowed('ignore'); } } if (isset($list['install'])) { if (!$allowignore) { $this->_ignoreNotAllowed('install'); } } if (isset($list['file'])) { if ($allowignore) { $this->_fileNotAllowed('file'); } } if (isset($list['dir'])) { if ($allowignore) { $this->_fileNotAllowed('dir'); } else { if (!isset($list['dir'][0])) { $list['dir'] = array($list['dir']); } foreach ($list['dir'] as $dir) { if (isset($dir['attribs']) && isset($dir['attribs']['name'])) { if ($dir['attribs']['name'] == '/' || !isset($this->_packageInfo['contents']['dir']['dir'])) { // always use nothing if the filelist has already been flattened $newdirs = ''; } elseif ($dirs == '') { $newdirs = $dir['attribs']['name']; } else { $newdirs = $dirs . '/' . $dir['attribs']['name']; } } else { $newdirs = $dirs; } $this->_validateFilelist($dir, $allowignore, $newdirs); } } } } function _validateRelease() { if (isset($this->_packageInfo['phprelease'])) { $release = 'phprelease'; if (isset($this->_packageInfo['providesextension'])) { $this->_cannotProvideExtension($release); } if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { $this->_cannotHaveSrcpackage($release); } $releases = $this->_packageInfo['phprelease']; if (!is_array($releases)) { return true; } if (!isset($releases[0])) { $releases = array($releases); } foreach ($releases as $rel) { $this->_stupidSchemaValidate(array( '*installconditions', '*filelist', ), $rel, ''); } } foreach (array('', 'zend') as $prefix) { $releasetype = $prefix . 'extsrcrelease'; if (isset($this->_packageInfo[$releasetype])) { $release = $releasetype; if (!isset($this->_packageInfo['providesextension'])) { $this->_mustProvideExtension($release); } if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { $this->_cannotHaveSrcpackage($release); } $releases = $this->_packageInfo[$releasetype]; if (!is_array($releases)) { return true; } if (!isset($releases[0])) { $releases = array($releases); } foreach ($releases as $rel) { $this->_stupidSchemaValidate(array( '*installconditions', '*configureoption->name->prompt->?default', '*binarypackage', '*filelist', ), $rel, '<' . $releasetype . '>'); if (isset($rel['binarypackage'])) { if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) { $rel['binarypackage'] = array($rel['binarypackage']); } foreach ($rel['binarypackage'] as $bin) { if (!is_string($bin)) { $this->_binaryPackageMustBePackagename(); } } } } } $releasetype = 'extbinrelease'; if (isset($this->_packageInfo[$releasetype])) { $release = $releasetype; if (!isset($this->_packageInfo['providesextension'])) { $this->_mustProvideExtension($release); } if (isset($this->_packageInfo['channel']) && !isset($this->_packageInfo['srcpackage'])) { $this->_mustSrcPackage($release); } if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) { $this->_mustSrcuri($release); } $releases = $this->_packageInfo[$releasetype]; if (!is_array($releases)) { return true; } if (!isset($releases[0])) { $releases = array($releases); } foreach ($releases as $rel) { $this->_stupidSchemaValidate(array( '*installconditions', '*filelist', ), $rel, '<' . $releasetype . '>'); } } } if (isset($this->_packageInfo['bundle'])) { $release = 'bundle'; if (isset($this->_packageInfo['providesextension'])) { $this->_cannotProvideExtension($release); } if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { $this->_cannotHaveSrcpackage($release); } $releases = $this->_packageInfo['bundle']; if (!is_array($releases) || !isset($releases[0])) { $releases = array($releases); } foreach ($releases as $rel) { $this->_stupidSchemaValidate(array( '*installconditions', '*filelist', ), $rel, ''); } } foreach ($releases as $rel) { if (is_array($rel) && array_key_exists('installconditions', $rel)) { $this->_validateInstallConditions($rel['installconditions'], "<$release>"); } if (is_array($rel) && array_key_exists('filelist', $rel)) { if ($rel['filelist']) { $this->_validateFilelist($rel['filelist'], true); } } } } /** * This is here to allow role extension through plugins * @param string */ function _validateRole($role) { return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())); } function _pearVersionTooLow($version) { $this->_stack->push(__FUNCTION__, 'error', array('version' => $version), 'This package.xml requires PEAR version %version% to parse properly, we are ' . 'version 1.10.16'); } function _invalidTagOrder($oktags, $actual, $root) { $this->_stack->push(__FUNCTION__, 'error', array('oktags' => $oktags, 'actual' => $actual, 'root' => $root), 'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"'); } function _ignoreNotAllowed($type) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), '<%type%> is not allowed inside global , only inside ' . '//, use and only'); } function _fileNotAllowed($type) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), '<%type%> is not allowed inside release , only inside ' . ', use and only'); } function _oldStyleFileNotAllowed() { $this->_stack->push(__FUNCTION__, 'error', array(), 'Old-style name is not allowed. Use' . ''); } function _tagMissingAttribute($tag, $attr, $context) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'attribute' => $attr, 'context' => $context), 'tag <%tag%> in context "%context%" has no attribute "%attribute%"'); } function _tagHasNoAttribs($tag, $context) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'context' => $context), 'tag <%tag%> has no attributes in context "%context%"'); } function _invalidInternalStructure() { $this->_stack->push(__FUNCTION__, 'exception', array(), 'internal array was not generated by compatible parser, or extreme parser error, cannot continue'); } function _invalidFileRole($file, $dir, $role) { $this->_stack->push(__FUNCTION__, 'error', array( 'file' => $file, 'dir' => $dir, 'role' => $role, 'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())), 'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%'); } function _invalidFileName($file, $dir) { $this->_stack->push(__FUNCTION__, 'error', array( 'file' => $file), 'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."'); } function _invalidFileInstallAs($file, $as) { $this->_stack->push(__FUNCTION__, 'error', array( 'file' => $file, 'as' => $as), 'File "%file%" cannot contain "./" or contain ".."'); } function _invalidDirName($dir) { $this->_stack->push(__FUNCTION__, 'error', array( 'dir' => $file), 'Directory "%dir%" cannot begin with "./" or contain ".."'); } function _filelistCannotContainFile($filelist) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist), '<%tag%> can only contain , contains . Use ' . ' as the first dir element'); } function _filelistMustContainDir($filelist) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist), '<%tag%> must contain . Use as the ' . 'first dir element'); } function _tagCannotBeEmpty($tag) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag), '<%tag%> cannot be empty (<%tag%/>)'); } function _UrlOrChannel($type, $name) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'name' => $name), 'Required dependency <%type%> "%name%" can have either url OR ' . 'channel attributes, and not both'); } function _NoChannel($type, $name) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'name' => $name), 'Required dependency <%type%> "%name%" must have either url OR ' . 'channel attributes'); } function _UrlOrChannelGroup($type, $name, $group) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'name' => $name, 'group' => $group), 'Group "%group%" dependency <%type%> "%name%" can have either url OR ' . 'channel attributes, and not both'); } function _NoChannelGroup($type, $name, $group) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'name' => $name, 'group' => $group), 'Group "%group%" dependency <%type%> "%name%" must have either url OR ' . 'channel attributes'); } function _unknownChannel($channel) { $this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel), 'Unknown channel "%channel%"'); } function _noPackageVersion() { $this->_stack->push(__FUNCTION__, 'error', array(), 'package.xml tag has no version attribute, or version is not 2.0'); } function _NoBundledPackages() { $this->_stack->push(__FUNCTION__, 'error', array(), 'No tag was found in , required for bundle packages'); } function _AtLeast2BundledPackages() { $this->_stack->push(__FUNCTION__, 'error', array(), 'At least 2 packages must be bundled in a bundle package'); } function _ChannelOrUri($name) { $this->_stack->push(__FUNCTION__, 'error', array('name' => $name), 'Bundled package "%name%" can have either a uri or a channel, not both'); } function _noChildTag($child, $tag) { $this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag), 'Tag <%tag%> is missing child tag <%child%>'); } function _invalidVersion($type, $value) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value), 'Version type <%type%> is not a valid version (%value%)'); } function _invalidState($type, $value) { $states = array('stable', 'beta', 'alpha', 'devel'); if ($type != 'api') { $states[] = 'snapshot'; } if (strtolower($value) == 'rc') { $this->_stack->push(__FUNCTION__, 'error', array('version' => $this->_packageInfo['version']['release']), 'RC is not a state, it is a version postfix, try %version%RC1, stability beta'); } $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value, 'types' => $states), 'Stability type <%type%> is not a valid stability (%value%), must be one of ' . '%types%'); } function _invalidTask($task, $ret, $file) { switch ($ret[0]) { case PEAR_TASK_ERROR_MISSING_ATTRIB : $info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file); $msg = 'task <%task%> is missing attribute "%attrib%" in file %file%'; break; case PEAR_TASK_ERROR_NOATTRIBS : $info = array('task' => $task, 'file' => $file); $msg = 'task <%task%> has no attributes in file %file%'; break; case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE : $info = array('attrib' => $ret[1], 'values' => $ret[3], 'was' => $ret[2], 'task' => $task, 'file' => $file); $msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '. 'in file %file%, expecting one of "%values%"'; break; case PEAR_TASK_ERROR_INVALID : $info = array('reason' => $ret[1], 'task' => $task, 'file' => $file); $msg = 'task <%task%> in file %file% is invalid because of "%reason%"'; break; } $this->_stack->push(__FUNCTION__, 'error', $info, $msg); } function _unknownTask($task, $file) { $this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file), 'Unknown task "%task%" passed in file '); } function _subpackageCannotProvideExtension($name) { $this->_stack->push(__FUNCTION__, 'error', array('name' => $name), 'Subpackage dependency "%name%" cannot use , ' . 'only package dependencies can use this tag'); } function _subpackagesCannotConflict($name) { $this->_stack->push(__FUNCTION__, 'error', array('name' => $name), 'Subpackage dependency "%name%" cannot use , ' . 'only package dependencies can use this tag'); } function _cannotProvideExtension($release) { $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), '<%release%> packages cannot use , only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension'); } function _mustProvideExtension($release) { $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), '<%release%> packages must use to indicate which PHP extension is provided'); } function _cannotHaveSrcpackage($release) { $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), '<%release%> packages cannot specify a source code package, only extension binaries may use the tag'); } function _mustSrcPackage($release) { $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), '/ packages must specify a source code package with '); } function _mustSrcuri($release) { $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), '/ packages must specify a source code package with '); } function _uriDepsCannotHaveVersioning($type) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), '%type%: dependencies with a tag cannot have any versioning information'); } function _conflictingDepsCannotHaveVersioning($type) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), '%type%: conflicting dependencies cannot have versioning info, use to ' . 'exclude specific versions of a dependency'); } function _DepchannelCannotBeUri($type) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), '%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' . 'dependencies only'); } function _bundledPackagesMustBeFilename() { $this->_stack->push(__FUNCTION__, 'error', array(), ' tags must contain only the filename of a package release ' . 'in the bundle'); } function _binaryPackageMustBePackagename() { $this->_stack->push(__FUNCTION__, 'error', array(), ' tags must contain the name of a package that is ' . 'a compiled version of this extsrc/zendextsrc package'); } function _fileNotFound($file) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), 'File "%file%" in package.xml does not exist'); } function _notInContents($file, $tag) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag), '<%tag% name="%file%"> is invalid, file is not in '); } function _cannotValidateNoPathSet() { $this->_stack->push(__FUNCTION__, 'error', array(), 'Cannot validate files, no path to package file is set (use setPackageFile())'); } function _usesroletaskMustHaveChannelOrUri($role, $tag) { $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag), '<%tag%> for role "%role%" must contain either , or and '); } function _usesroletaskMustHavePackage($role, $tag) { $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag), '<%tag%> for role "%role%" must contain '); } function _usesroletaskMustHaveRoleTask($tag, $type) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type), '<%tag%> must contain <%type%> defining the %type% to be used'); } function _cannotConflictWithAllOs($type) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag), '%tag% cannot conflict with all OSes'); } function _invalidDepGroupName($name) { $this->_stack->push(__FUNCTION__, 'error', array('name' => $name), 'Invalid dependency group name "%name%"'); } function _multipleToplevelDirNotAllowed() { $this->_stack->push(__FUNCTION__, 'error', array(), 'Multiple top-level tags are not allowed. Enclose them ' . 'in a '); } function _multipleInstallAs($file) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), 'Only one tag is allowed for file "%file%"'); } function _ignoreAndInstallAs($file) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), 'Cannot have both and tags for file "%file%"'); } function _analyzeBundledPackages() { if (!$this->_isValid) { return false; } if (!$this->_pf->getPackageType() == 'bundle') { return false; } if (!isset($this->_pf->_packageFile)) { return false; } $dir_prefix = dirname($this->_pf->_packageFile); $common = new PEAR_Common; $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') : array($common, 'log'); $info = $this->_pf->getContents(); $info = $info['bundledpackage']; if (!is_array($info)) { $info = array($info); } $pkg = new PEAR_PackageFile($this->_pf->_config); foreach ($info as $package) { if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) { $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package); $this->_isValid = 0; continue; } call_user_func_array($log, array(1, "Analyzing bundled package $package")); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package, PEAR_VALIDATE_NORMAL); PEAR::popErrorHandling(); if (PEAR::isError($ret)) { call_user_func_array($log, array(0, "ERROR: package $package is not a valid " . 'package')); $inf = $ret->getUserInfo(); if (is_array($inf)) { foreach ($inf as $err) { call_user_func_array($log, array(1, $err['message'])); } } return false; } } return true; } function _analyzePhpFiles() { if (!$this->_isValid) { return false; } if (!isset($this->_pf->_packageFile)) { $this->_cannotValidateNoPathSet(); return false; } $dir_prefix = dirname($this->_pf->_packageFile); $common = new PEAR_Common; $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') : array(&$common, 'log'); $info = $this->_pf->getContents(); if (!$info || !isset($info['dir']['file'])) { $this->_tagCannotBeEmpty('contents>_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file); $this->_isValid = 0; continue; } if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) { call_user_func_array($log, array(1, "Analyzing $file")); $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file); if ($srcinfo) { $provides = array_merge($provides, $this->_buildProvidesArray($srcinfo)); } } } $this->_packageName = $pn = $this->_pf->getPackage(); $pnl = strlen($pn); foreach ($provides as $key => $what) { if (isset($what['explicit']) || !$what) { // skip conformance checks if the provides entry is // specified in the package.xml file continue; } extract($what); if ($type == 'class') { if (!strncasecmp($name, $pn, $pnl)) { continue; } $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn), 'in %file%: %type% "%name%" not prefixed with package name "%package%"'); } elseif ($type == 'function') { if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) { continue; } $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn), 'in %file%: %type% "%name%" not prefixed with package name "%package%"'); } } return $this->_isValid; } /** * Analyze the source code of the given PHP file * * @param string Filename of the PHP file * @param boolean whether to analyze $file as the file contents * @return mixed */ function analyzeSourceCode($file, $string = false) { if (!function_exists("token_get_all")) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), 'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer'); return false; } if (!defined('T_DOC_COMMENT')) { define('T_DOC_COMMENT', T_COMMENT); } if (!defined('T_INTERFACE')) { define('T_INTERFACE', -1); } if (!defined('T_IMPLEMENTS')) { define('T_IMPLEMENTS', -1); } if ($string) { $contents = $file; } else { if (!$fp = @fopen($file, "r")) { return false; } fclose($fp); $contents = file_get_contents($file); } // Silence this function so we can catch PHP Warnings and show our own custom message $tokens = @token_get_all($contents); if (isset($php_errormsg)) { if (isset($this->_stack)) { $pn = $this->_pf->getPackage(); $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file, 'package' => $pn), 'in %file%: Could not process file for unknown reasons,' . ' possibly a PHP parse error in %file% from %package%'); } } /* for ($i = 0; $i < sizeof($tokens); $i++) { @list($token, $data) = $tokens[$i]; if (is_string($token)) { var_dump($token); } else { print token_name($token) . ' '; var_dump(rtrim($data)); } } */ $look_for = 0; $paren_level = 0; $bracket_level = 0; $brace_level = 0; $lastphpdoc = ''; $current_class = ''; $current_interface = ''; $current_class_level = -1; $current_function = ''; $current_function_level = -1; $declared_classes = array(); $declared_interfaces = array(); $declared_functions = array(); $declared_methods = array(); $used_classes = array(); $used_functions = array(); $extends = array(); $implements = array(); $nodeps = array(); $inquote = false; $interface = false; for ($i = 0; $i < sizeof($tokens); $i++) { if (is_array($tokens[$i])) { list($token, $data) = $tokens[$i]; } else { $token = $tokens[$i]; $data = ''; } if ($inquote) { if ($token != '"' && $token != T_END_HEREDOC) { continue; } else { $inquote = false; continue; } } switch ($token) { case T_WHITESPACE : continue 2; case ';': if ($interface) { $current_function = ''; $current_function_level = -1; } break; case '"': case T_START_HEREDOC: $inquote = true; break; case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: case '{': $brace_level++; continue 2; case '}': $brace_level--; if ($current_class_level == $brace_level) { $current_class = ''; $current_class_level = -1; } if ($current_function_level == $brace_level) { $current_function = ''; $current_function_level = -1; } continue 2; case '[': $bracket_level++; continue 2; case ']': $bracket_level--; continue 2; case '(': $paren_level++; continue 2; case ')': $paren_level--; continue 2; case T_INTERFACE: $interface = true; case T_CLASS: if (($current_class_level != -1) || ($current_function_level != -1)) { if (isset($this->_stack)) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), 'Parser error: invalid PHP found in file "%file%"'); } else { PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"", PEAR_COMMON_ERROR_INVALIDPHP); } return false; } case T_FUNCTION: case T_NEW: case T_EXTENDS: case T_IMPLEMENTS: $look_for = $token; continue 2; case T_STRING: if ($look_for == T_CLASS) { $current_class = $data; $current_class_level = $brace_level; $declared_classes[] = $current_class; } elseif ($look_for == T_INTERFACE) { $current_interface = $data; $current_class_level = $brace_level; $declared_interfaces[] = $current_interface; } elseif ($look_for == T_IMPLEMENTS) { $implements[$current_class] = $data; } elseif ($look_for == T_EXTENDS) { $extends[$current_class] = $data; } elseif ($look_for == T_FUNCTION) { if ($current_class) { $current_function = "$current_class::$data"; $declared_methods[$current_class][] = $data; } elseif ($current_interface) { $current_function = "$current_interface::$data"; $declared_methods[$current_interface][] = $data; } else { $current_function = $data; $declared_functions[] = $current_function; } $current_function_level = $brace_level; $m = array(); } elseif ($look_for == T_NEW) { $used_classes[$data] = true; } $look_for = 0; continue 2; case T_VARIABLE: $look_for = 0; continue 2; case T_DOC_COMMENT: case T_COMMENT: if (preg_match('!^/\*\*\s!', $data)) { $lastphpdoc = $data; if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) { $nodeps = array_merge($nodeps, $m[1]); } } continue 2; case T_DOUBLE_COLON: $token = $tokens[$i - 1][0]; if (!($token == T_WHITESPACE || $token == T_STRING || $token == T_STATIC || $token == T_VARIABLE)) { if (isset($this->_stack)) { $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file), 'Parser error: invalid PHP found in file "%file%"'); } else { PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"", PEAR_COMMON_ERROR_INVALIDPHP); } return false; } $class = $tokens[$i - 1][1]; if (strtolower($class) != 'parent') { $used_classes[$class] = true; } continue 2; } } return array( "source_file" => $file, "declared_classes" => $declared_classes, "declared_interfaces" => $declared_interfaces, "declared_methods" => $declared_methods, "declared_functions" => $declared_functions, "used_classes" => array_diff(array_keys($used_classes), $nodeps), "inheritance" => $extends, "implements" => $implements, ); } /** * Build a "provides" array from data returned by * analyzeSourceCode(). The format of the built array is like * this: * * array( * 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), * ... * ) * * * @param array $srcinfo array with information about a source file * as returned by the analyzeSourceCode() method. * * @return void * * @access private * */ function _buildProvidesArray($srcinfo) { if (!$this->_isValid) { return array(); } $providesret = array(); $file = basename($srcinfo['source_file']); $pn = isset($this->_pf) ? $this->_pf->getPackage() : ''; $pnl = strlen($pn); foreach ($srcinfo['declared_classes'] as $class) { $key = "class;$class"; if (isset($providesret[$key])) { continue; } $providesret[$key] = array('file'=> $file, 'type' => 'class', 'name' => $class); if (isset($srcinfo['inheritance'][$class])) { $providesret[$key]['extends'] = $srcinfo['inheritance'][$class]; } } foreach ($srcinfo['declared_methods'] as $class => $methods) { foreach ($methods as $method) { $function = "$class::$method"; $key = "function;$function"; if ($method[0] == '_' || !strcasecmp($method, $class) || isset($providesret[$key])) { continue; } $providesret[$key] = array('file'=> $file, 'type' => 'function', 'name' => $function); } } foreach ($srcinfo['declared_functions'] as $function) { $key = "function;$function"; if ($function[0] == '_' || isset($providesret[$key])) { continue; } if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; } $providesret[$key] = array('file'=> $file, 'type' => 'function', 'name' => $function); } return $providesret; } } PK!=__rw.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a8 */ /** * For base class */ require_once 'PEAR/PackageFile/v2.php'; /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a8 */ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2 { /** * @param string Extension name * @return bool success of operation */ function setProvidesExtension($extension) { if (in_array($this->getPackageType(), array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) { if (!isset($this->_packageInfo['providesextension'])) { // ensure that the channel tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $extension, 'providesextension'); } $this->_packageInfo['providesextension'] = $extension; return true; } return false; } function setPackage($package) { $this->_isValid = 0; if (!isset($this->_packageInfo['attribs'])) { $this->_packageInfo = array_merge(array('attribs' => array( 'version' => '2.0', 'xmlns' => 'http://pear.php.net/dtd/package-2.0', 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd', )), $this->_packageInfo); } if (!isset($this->_packageInfo['name'])) { return $this->_packageInfo = array_merge(array('name' => $package), $this->_packageInfo); } $this->_packageInfo['name'] = $package; } /** * set this as a package.xml version 2.1 * @access private */ function _setPackageVersion2_1() { $info = array( 'version' => '2.1', 'xmlns' => 'http://pear.php.net/dtd/package-2.1', 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.1 http://pear.php.net/dtd/package-2.1.xsd', ); if (!isset($this->_packageInfo['attribs'])) { $this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo); } else { $this->_packageInfo['attribs'] = $info; } } function setUri($uri) { unset($this->_packageInfo['channel']); $this->_isValid = 0; if (!isset($this->_packageInfo['uri'])) { // ensure that the uri tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('extends', 'summary', 'description', 'lead', 'developer', 'contributor', 'helper', 'date', 'time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), $uri, 'uri'); } $this->_packageInfo['uri'] = $uri; } function setChannel($channel) { unset($this->_packageInfo['uri']); $this->_isValid = 0; if (!isset($this->_packageInfo['channel'])) { // ensure that the channel tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('extends', 'summary', 'description', 'lead', 'developer', 'contributor', 'helper', 'date', 'time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), $channel, 'channel'); } $this->_packageInfo['channel'] = $channel; } function setExtends($extends) { $this->_isValid = 0; if (!isset($this->_packageInfo['extends'])) { // ensure that the extends tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('summary', 'description', 'lead', 'developer', 'contributor', 'helper', 'date', 'time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), $extends, 'extends'); } $this->_packageInfo['extends'] = $extends; } function setSummary($summary) { $this->_isValid = 0; if (!isset($this->_packageInfo['summary'])) { // ensure that the summary tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('description', 'lead', 'developer', 'contributor', 'helper', 'date', 'time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), $summary, 'summary'); } $this->_packageInfo['summary'] = $summary; } function setDescription($desc) { $this->_isValid = 0; if (!isset($this->_packageInfo['description'])) { // ensure that the description tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('lead', 'developer', 'contributor', 'helper', 'date', 'time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), $desc, 'description'); } $this->_packageInfo['description'] = $desc; } /** * Adds a new maintainer - no checking of duplicates is performed, use * updatemaintainer for that purpose. */ function addMaintainer($role, $handle, $name, $email, $active = 'yes') { if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) { return false; } if (isset($this->_packageInfo[$role])) { if (!isset($this->_packageInfo[$role][0])) { $this->_packageInfo[$role] = array($this->_packageInfo[$role]); } $this->_packageInfo[$role][] = array( 'name' => $name, 'user' => $handle, 'email' => $email, 'active' => $active, ); } else { $testarr = array('lead', 'developer', 'contributor', 'helper', 'date', 'time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'); foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) { array_shift($testarr); if ($role == $testrole) { break; } } if (!isset($this->_packageInfo[$role])) { // ensure that the extends tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr, array(), $role); } $this->_packageInfo[$role] = array( 'name' => $name, 'user' => $handle, 'email' => $email, 'active' => $active, ); } $this->_isValid = 0; } function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes') { $found = false; foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { if (!isset($this->_packageInfo[$role])) { continue; } $info = $this->_packageInfo[$role]; if (!isset($info[0])) { if ($info['user'] == $handle) { $found = true; break; } } foreach ($info as $i => $maintainer) { if (is_array($maintainer) && $maintainer['user'] == $handle) { $found = $i; break 2; } } } if ($found === false) { return $this->addMaintainer($newrole, $handle, $name, $email, $active); } if ($found !== false) { if ($found === true) { unset($this->_packageInfo[$role]); } else { unset($this->_packageInfo[$role][$found]); $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]); } } $this->addMaintainer($newrole, $handle, $name, $email, $active); $this->_isValid = 0; } function deleteMaintainer($handle) { $found = false; foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { if (!isset($this->_packageInfo[$role])) { continue; } if (!isset($this->_packageInfo[$role][0])) { $this->_packageInfo[$role] = array($this->_packageInfo[$role]); } foreach ($this->_packageInfo[$role] as $i => $maintainer) { if ($maintainer['user'] == $handle) { $found = $i; break; } } if ($found !== false) { unset($this->_packageInfo[$role][$found]); if (!count($this->_packageInfo[$role]) && $role == 'lead') { $this->_isValid = 0; } if (!count($this->_packageInfo[$role])) { unset($this->_packageInfo[$role]); return true; } $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]); if (count($this->_packageInfo[$role]) == 1) { $this->_packageInfo[$role] = $this->_packageInfo[$role][0]; } return true; } if (count($this->_packageInfo[$role]) == 1) { $this->_packageInfo[$role] = $this->_packageInfo[$role][0]; } } return false; } function setReleaseVersion($version) { if (isset($this->_packageInfo['version']) && isset($this->_packageInfo['version']['release'])) { unset($this->_packageInfo['version']['release']); } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array( 'version' => array('stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), 'release' => array('api'))); $this->_isValid = 0; } function setAPIVersion($version) { if (isset($this->_packageInfo['version']) && isset($this->_packageInfo['version']['api'])) { unset($this->_packageInfo['version']['api']); } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array( 'version' => array('stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), 'api' => array())); $this->_isValid = 0; } /** * snapshot|devel|alpha|beta|stable */ function setReleaseStability($state) { if (isset($this->_packageInfo['stability']) && isset($this->_packageInfo['stability']['release'])) { unset($this->_packageInfo['stability']['release']); } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array( 'stability' => array('license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), 'release' => array('api'))); $this->_isValid = 0; } /** * @param devel|alpha|beta|stable */ function setAPIStability($state) { if (isset($this->_packageInfo['stability']) && isset($this->_packageInfo['stability']['api'])) { unset($this->_packageInfo['stability']['api']); } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array( 'stability' => array('license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), 'api' => array())); $this->_isValid = 0; } function setLicense($license, $uri = false, $filesource = false) { if (!isset($this->_packageInfo['license'])) { // ensure that the license tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), 0, 'license'); } if ($uri || $filesource) { $attribs = array(); if ($uri) { $attribs['uri'] = $uri; } $uri = true; // for test below if ($filesource) { $attribs['filesource'] = $filesource; } } $license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license; $this->_packageInfo['license'] = $license; $this->_isValid = 0; } function setNotes($notes) { $this->_isValid = 0; if (!isset($this->_packageInfo['notes'])) { // ensure that the notes tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), $notes, 'notes'); } $this->_packageInfo['notes'] = $notes; } /** * This is only used at install-time, after all serialization * is over. * @param string file name * @param string installed path */ function setInstalledAs($file, $path) { if ($path) { return $this->_packageInfo['filelist'][$file]['installed_as'] = $path; } unset($this->_packageInfo['filelist'][$file]['installed_as']); } /** * This is only used at install-time, after all serialization * is over. */ function installedFile($file, $atts) { if (isset($this->_packageInfo['filelist'][$file])) { $this->_packageInfo['filelist'][$file] = array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']); } else { $this->_packageInfo['filelist'][$file] = $atts['attribs']; } } /** * Reset the listing of package contents * @param string base installation dir for the whole package, if any */ function clearContents($baseinstall = false) { $this->_filesValid = false; $this->_isValid = 0; if (!isset($this->_packageInfo['contents'])) { $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), array(), 'contents'); } if ($this->getPackageType() != 'bundle') { $this->_packageInfo['contents'] = array('dir' => array('attribs' => array('name' => '/'))); if ($baseinstall) { $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall; } } else { $this->_packageInfo['contents'] = array('bundledpackage' => array()); } } /** * @param string relative path of the bundled package. */ function addBundledPackage($path) { if ($this->getPackageType() != 'bundle') { return false; } $this->_filesValid = false; $this->_isValid = 0; $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array( 'contents' => array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'bundledpackage' => array())); } /** * @param string file name * @param PEAR_Task_Common a read/write task */ function addTaskToFile($filename, $task) { if (!method_exists($task, 'getXml')) { return false; } if (!method_exists($task, 'getName')) { return false; } if (!method_exists($task, 'validate')) { return false; } if (!$task->validate()) { return false; } if (!isset($this->_packageInfo['contents']['dir']['file'])) { return false; } $this->getTasksNs(); // discover the tasks namespace if not done already $files = $this->_packageInfo['contents']['dir']['file']; if (!isset($files[0])) { $files = array($files); $ind = false; } else { $ind = true; } foreach ($files as $i => $file) { if (isset($file['attribs'])) { if ($file['attribs']['name'] == $filename) { if ($ind) { $t = isset($this->_packageInfo['contents']['dir']['file'][$i] ['attribs'][$this->_tasksNs . ':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file'][$i] ['attribs'][$this->_tasksNs . ':' . $task->getName()] : false; if ($t && !isset($t[0])) { $this->_packageInfo['contents']['dir']['file'][$i] [$this->_tasksNs . ':' . $task->getName()] = array($t); } $this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs . ':' . $task->getName()][] = $task->getXml(); } else { $t = isset($this->_packageInfo['contents']['dir']['file'] ['attribs'][$this->_tasksNs . ':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file'] ['attribs'][$this->_tasksNs . ':' . $task->getName()] : false; if ($t && !isset($t[0])) { $this->_packageInfo['contents']['dir']['file'] [$this->_tasksNs . ':' . $task->getName()] = array($t); } $this->_packageInfo['contents']['dir']['file'][$this->_tasksNs . ':' . $task->getName()][] = $task->getXml(); } return true; } } } return false; } /** * @param string path to the file * @param string filename * @param array extra attributes */ function addFile($dir, $file, $attrs) { if ($this->getPackageType() == 'bundle') { return false; } $this->_filesValid = false; $this->_isValid = 0; $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir); if ($dir == '/' || $dir == '') { $dir = ''; } else { $dir .= '/'; } $attrs['name'] = $dir . $file; if (!isset($this->_packageInfo['contents'])) { // ensure that the contents tag is set up $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), array(), 'contents'); } if (isset($this->_packageInfo['contents']['dir']['file'])) { if (!isset($this->_packageInfo['contents']['dir']['file'][0])) { $this->_packageInfo['contents']['dir']['file'] = array($this->_packageInfo['contents']['dir']['file']); } $this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs; } else { $this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs; } } /** * @param string Dependent package name * @param string Dependent package's channel name * @param string minimum version of specified package that this release is guaranteed to be * compatible with * @param string maximum version of specified package that this release is guaranteed to be * compatible with * @param string versions of specified package that this release is not compatible with */ function addCompatiblePackage($name, $channel, $min, $max, $exclude = false) { $this->_isValid = 0; $set = array( 'name' => $name, 'channel' => $channel, 'min' => $min, 'max' => $max, ); if ($exclude) { $set['exclude'] = $exclude; } $this->_isValid = 0; $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( 'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') )); } /** * Removes the tag entirely */ function resetUsesrole() { if (isset($this->_packageInfo['usesrole'])) { unset($this->_packageInfo['usesrole']); } } /** * @param string * @param string package name or uri * @param string channel name if non-uri */ function addUsesrole($role, $packageOrUri, $channel = false) { $set = array('role' => $role); if ($channel) { $set['package'] = $packageOrUri; $set['channel'] = $channel; } else { $set['uri'] = $packageOrUri; } $this->_isValid = 0; $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( 'usesrole' => array('usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') )); } /** * Removes the tag entirely */ function resetUsestask() { if (isset($this->_packageInfo['usestask'])) { unset($this->_packageInfo['usestask']); } } /** * @param string * @param string package name or uri * @param string channel name if non-uri */ function addUsestask($task, $packageOrUri, $channel = false) { $set = array('task' => $task); if ($channel) { $set['package'] = $packageOrUri; $set['channel'] = $channel; } else { $set['uri'] = $packageOrUri; } $this->_isValid = 0; $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( 'usestask' => array('srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') )); } /** * Remove all compatible tags */ function clearCompatible() { unset($this->_packageInfo['compatible']); } /** * Reset dependencies prior to adding new ones */ function clearDeps() { if (!isset($this->_packageInfo['dependencies'])) { $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(), array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'))); } $this->_packageInfo['dependencies'] = array(); } /** * @param string minimum PHP version allowed * @param string maximum PHP version allowed * @param array $exclude incompatible PHP versions */ function setPhpDep($min, $max = false, $exclude = false) { $this->_isValid = 0; $dep = array( 'min' => $min, ); if ($max) { $dep['max'] = $max; } if ($exclude) { if (count($exclude) == 1) { $exclude = $exclude[0]; } $dep['exclude'] = $exclude; } if (isset($this->_packageInfo['dependencies']['required']['php'])) { $this->_stack->push(__FUNCTION__, 'warning', array('dep' => $this->_packageInfo['dependencies']['required']['php']), 'warning: PHP dependency already exists, overwriting'); unset($this->_packageInfo['dependencies']['required']['php']); } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'required' => array('optional', 'group'), 'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch') )); return true; } /** * @param string minimum allowed PEAR installer version * @param string maximum allowed PEAR installer version * @param string recommended PEAR installer version * @param array incompatible version of the PEAR installer */ function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false) { $this->_isValid = 0; $dep = array( 'min' => $min, ); if ($max) { $dep['max'] = $max; } if ($recommended) { $dep['recommended'] = $recommended; } if ($exclude) { if (count($exclude) == 1) { $exclude = $exclude[0]; } $dep['exclude'] = $exclude; } if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) { $this->_stack->push(__FUNCTION__, 'warning', array('dep' => $this->_packageInfo['dependencies']['required']['pearinstaller']), 'warning: PEAR Installer dependency already exists, overwriting'); unset($this->_packageInfo['dependencies']['required']['pearinstaller']); } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'required' => array('optional', 'group'), 'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch') )); } /** * Mark a package as conflicting with this package * @param string package name * @param string package channel * @param string extension this package provides, if any * @param string|false minimum version required * @param string|false maximum version allowed * @param array|false versions to exclude from installation */ function addConflictingPackageDepWithChannel($name, $channel, $providesextension = false, $min = false, $max = false, $exclude = false) { $this->_isValid = 0; $dep = $this->_constructDep($name, $channel, false, $min, $max, false, $exclude, $providesextension, false, true); $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'required' => array('optional', 'group'), 'package' => array('subpackage', 'extension', 'os', 'arch') )); } /** * Mark a package as conflicting with this package * @param string package name * @param string package channel * @param string extension this package provides, if any */ function addConflictingPackageDepWithUri($name, $uri, $providesextension = false) { $this->_isValid = 0; $dep = array( 'name' => $name, 'uri' => $uri, 'conflicts' => '', ); if ($providesextension) { $dep['providesextension'] = $providesextension; } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'required' => array('optional', 'group'), 'package' => array('subpackage', 'extension', 'os', 'arch') )); } function addDependencyGroup($name, $hint) { $this->_isValid = 0; $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array('attribs' => array('name' => $name, 'hint' => $hint)), array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'group' => array(), )); } /** * @param string package name * @param string|false channel name, false if this is a uri * @param string|false uri name, false if this is a channel * @param string|false minimum version required * @param string|false maximum version allowed * @param string|false recommended installation version * @param array|false versions to exclude from installation * @param string extension this package provides, if any * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package * @param bool if true, tells the installer to negate this dependency (conflicts) * @return array * @access private */ function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude, $providesextension = false, $nodefault = false, $conflicts = false) { $dep = array( 'name' => $name, ); if ($channel) { $dep['channel'] = $channel; } elseif ($uri) { $dep['uri'] = $uri; } if ($min) { $dep['min'] = $min; } if ($max) { $dep['max'] = $max; } if ($recommended) { $dep['recommended'] = $recommended; } if ($exclude) { if (is_array($exclude) && count($exclude) == 1) { $exclude = $exclude[0]; } $dep['exclude'] = $exclude; } if ($conflicts) { $dep['conflicts'] = ''; } if ($nodefault) { $dep['nodefault'] = ''; } if ($providesextension) { $dep['providesextension'] = $providesextension; } return $dep; } /** * @param package|subpackage * @param string group name * @param string package name * @param string package channel * @param string minimum version * @param string maximum version * @param string recommended version * @param array|false optional excluded versions * @param string extension this package provides, if any * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package * @return bool false if the dependency group has not been initialized with * {@link addDependencyGroup()}, or a subpackage is added with * a providesextension */ function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false, $max = false, $recommended = false, $exclude = false, $providesextension = false, $nodefault = false) { if ($type == 'subpackage' && $providesextension) { return false; // subpackages must be php packages } $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, $providesextension, $nodefault); return $this->_addGroupDependency($type, $dep, $groupname); } /** * @param package|subpackage * @param string group name * @param string package name * @param string package uri * @param string extension this package provides, if any * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package * @return bool false if the dependency group has not been initialized with * {@link addDependencyGroup()} */ function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false, $nodefault = false) { if ($type == 'subpackage' && $providesextension) { return false; // subpackages must be php packages } $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $providesextension, $nodefault); return $this->_addGroupDependency($type, $dep, $groupname); } /** * @param string group name (must be pre-existing) * @param string extension name * @param string minimum version allowed * @param string maximum version allowed * @param string recommended version * @param array incompatible versions */ function addGroupExtensionDep($groupname, $name, $min = false, $max = false, $recommended = false, $exclude = false) { $this->_isValid = 0; $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); return $this->_addGroupDependency('extension', $dep, $groupname); } /** * @param package|subpackage|extension * @param array dependency contents * @param string name of the dependency group to add this to * @return boolean * @access private */ function _addGroupDependency($type, $dep, $groupname) { $arr = array('subpackage', 'extension'); if ($type != 'package') { array_shift($arr); } if ($type == 'extension') { array_shift($arr); } if (!isset($this->_packageInfo['dependencies']['group'])) { return false; } else { if (!isset($this->_packageInfo['dependencies']['group'][0])) { if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) { $this->_packageInfo['dependencies']['group'] = $this->_mergeTag( $this->_packageInfo['dependencies']['group'], $dep, array( $type => $arr )); $this->_isValid = 0; return true; } else { return false; } } else { foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) { if ($group['attribs']['name'] == $groupname) { $this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag( $this->_packageInfo['dependencies']['group'][$i], $dep, array( $type => $arr )); $this->_isValid = 0; return true; } } return false; } } } /** * @param optional|required * @param string package name * @param string package channel * @param string minimum version * @param string maximum version * @param string recommended version * @param string extension this package provides, if any * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package * @param array|false optional excluded versions */ function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false, $recommended = false, $exclude = false, $providesextension = false, $nodefault = false) { if (!in_array($type, array('optional', 'required'), true)) { $type = 'required'; } $this->_isValid = 0; $arr = array('optional', 'group'); if ($type != 'required') { array_shift($arr); } $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, $providesextension, $nodefault); $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $type => $arr, 'package' => array('subpackage', 'extension', 'os', 'arch') )); } /** * @param optional|required * @param string name of the package * @param string uri of the package * @param string extension this package provides, if any * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package */ function addPackageDepWithUri($type, $name, $uri, $providesextension = false, $nodefault = false) { $this->_isValid = 0; $arr = array('optional', 'group'); if ($type != 'required') { array_shift($arr); } $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $providesextension, $nodefault); $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $type => $arr, 'package' => array('subpackage', 'extension', 'os', 'arch') )); } /** * @param optional|required optional, required * @param string package name * @param string package channel * @param string minimum version * @param string maximum version * @param string recommended version * @param array incompatible versions * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package */ function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false, $recommended = false, $exclude = false, $nodefault = false) { $this->_isValid = 0; $arr = array('optional', 'group'); if ($type != 'required') { array_shift($arr); } $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, $nodefault); $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $type => $arr, 'subpackage' => array('extension', 'os', 'arch') )); } /** * @param optional|required optional, required * @param string package name * @param string package uri for download * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package */ function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false) { $this->_isValid = 0; $arr = array('optional', 'group'); if ($type != 'required') { array_shift($arr); } $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault); $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $type => $arr, 'subpackage' => array('extension', 'os', 'arch') )); } /** * @param optional|required optional, required * @param string extension name * @param string minimum version * @param string maximum version * @param string recommended version * @param array incompatible versions */ function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false, $exclude = false) { $this->_isValid = 0; $arr = array('optional', 'group'); if ($type != 'required') { array_shift($arr); } $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $type => $arr, 'extension' => array('os', 'arch') )); } /** * @param string Operating system name * @param boolean true if this package cannot be installed on this OS */ function addOsDep($name, $conflicts = false) { $this->_isValid = 0; $dep = array('name' => $name); if ($conflicts) { $dep['conflicts'] = ''; } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'required' => array('optional', 'group'), 'os' => array('arch') )); } /** * @param string Architecture matching pattern * @param boolean true if this package cannot be installed on this architecture */ function addArchDep($pattern, $conflicts = false) { $this->_isValid = 0; $dep = array('pattern' => $pattern); if ($conflicts) { $dep['conflicts'] = ''; } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'required' => array('optional', 'group'), 'arch' => array() )); } /** * Set the kind of package, and erase all release tags * * - a php package is a PEAR-style package * - an extbin package is a PECL-style extension binary * - an extsrc package is a PECL-style source for a binary * - an zendextbin package is a PECL-style zend extension binary * - an zendextsrc package is a PECL-style source for a zend extension binary * - a bundle package is a collection of other pre-packaged packages * @param php|extbin|extsrc|zendextsrc|zendextbin|bundle * @return bool success */ function setPackageType($type) { $this->_isValid = 0; if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc', 'zendextbin', 'bundle'))) { return false; } if (in_array($type, array('zendextsrc', 'zendextbin'))) { $this->_setPackageVersion2_1(); } if ($type != 'bundle') { $type .= 'release'; } foreach (array('phprelease', 'extbinrelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) { unset($this->_packageInfo[$test]); } if (!isset($this->_packageInfo[$type])) { // ensure that the release tag is set up $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'), array(), $type); } $this->_packageInfo[$type] = array(); return true; } /** * @return bool true if package type is set up */ function addRelease() { if ($type = $this->getPackageType()) { if ($type != 'bundle') { $type .= 'release'; } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(), array($type => array('changelog'))); return true; } return false; } /** * Get the current release tag in order to add to it * @param bool returns only releases that have installcondition if true * @return array|null */ function &_getCurrentRelease($strict = true) { if ($p = $this->getPackageType()) { if ($strict) { if ($p == 'extsrc' || $p == 'zendextsrc') { $a = null; return $a; } } if ($p != 'bundle') { $p .= 'release'; } if (isset($this->_packageInfo[$p][0])) { return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1]; } else { return $this->_packageInfo[$p]; } } else { $a = null; return $a; } } /** * Add a file to the current release that should be installed under a different name * @param string path to file * @param string name the file should be installed as */ function addInstallAs($path, $as) { $r = &$this->_getCurrentRelease(); if ($r === null) { return false; } $this->_isValid = 0; $r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)), array( 'filelist' => array(), 'install' => array('ignore') )); } /** * Add a file to the current release that should be ignored * @param string path to file * @return bool success of operation */ function addIgnore($path) { $r = &$this->_getCurrentRelease(); if ($r === null) { return false; } $this->_isValid = 0; $r = $this->_mergeTag($r, array('attribs' => array('name' => $path)), array( 'filelist' => array(), 'ignore' => array() )); } /** * Add an extension binary package for this extension source code release * * Note that the package must be from the same channel as the extension source package * @param string */ function addBinarypackage($package) { if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { return false; } $r = &$this->_getCurrentRelease(false); if ($r === null) { return false; } $this->_isValid = 0; $r = $this->_mergeTag($r, $package, array( 'binarypackage' => array('filelist'), )); } /** * Add a configureoption to an extension source package * @param string * @param string * @param string */ function addConfigureOption($name, $prompt, $default = null) { if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { return false; } $r = &$this->_getCurrentRelease(false); if ($r === null) { return false; } $opt = array('attribs' => array('name' => $name, 'prompt' => $prompt)); if ($default !== null) { $opt['attribs']['default'] = $default; } $this->_isValid = 0; $r = $this->_mergeTag($r, $opt, array( 'configureoption' => array('binarypackage', 'filelist'), )); } /** * Set an installation condition based on php version for the current release set * @param string minimum version * @param string maximum version * @param false|array incompatible versions of PHP */ function setPhpInstallCondition($min, $max, $exclude = false) { $r = &$this->_getCurrentRelease(); if ($r === null) { return false; } $this->_isValid = 0; if (isset($r['installconditions']['php'])) { unset($r['installconditions']['php']); } $dep = array('min' => $min, 'max' => $max); if ($exclude) { if (is_array($exclude) && count($exclude) == 1) { $exclude = $exclude[0]; } $dep['exclude'] = $exclude; } if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('configureoption', 'binarypackage', 'filelist'), 'php' => array('extension', 'os', 'arch') )); } else { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('filelist'), 'php' => array('extension', 'os', 'arch') )); } } /** * @param optional|required optional, required * @param string extension name * @param string minimum version * @param string maximum version * @param string recommended version * @param array incompatible versions */ function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false, $exclude = false) { $r = &$this->_getCurrentRelease(); if ($r === null) { return false; } $this->_isValid = 0; $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('configureoption', 'binarypackage', 'filelist'), 'extension' => array('os', 'arch') )); } else { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('filelist'), 'extension' => array('os', 'arch') )); } } /** * Set an installation condition based on operating system for the current release set * @param string OS name * @param bool whether this OS is incompatible with the current release */ function setOsInstallCondition($name, $conflicts = false) { $r = &$this->_getCurrentRelease(); if ($r === null) { return false; } $this->_isValid = 0; if (isset($r['installconditions']['os'])) { unset($r['installconditions']['os']); } $dep = array('name' => $name); if ($conflicts) { $dep['conflicts'] = ''; } if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('configureoption', 'binarypackage', 'filelist'), 'os' => array('arch') )); } else { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('filelist'), 'os' => array('arch') )); } } /** * Set an installation condition based on architecture for the current release set * @param string architecture pattern * @param bool whether this arch is incompatible with the current release */ function setArchInstallCondition($pattern, $conflicts = false) { $r = &$this->_getCurrentRelease(); if ($r === null) { return false; } $this->_isValid = 0; if (isset($r['installconditions']['arch'])) { unset($r['installconditions']['arch']); } $dep = array('pattern' => $pattern); if ($conflicts) { $dep['conflicts'] = ''; } if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('configureoption', 'binarypackage', 'filelist'), 'arch' => array() )); } else { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('filelist'), 'arch' => array() )); } } /** * For extension binary releases, this is used to specify either the * static URI to a source package, or the package name and channel of the extsrc/zendextsrc * package it is based on. * @param string Package name, or full URI to source package (extsrc/zendextsrc type) */ function setSourcePackage($packageOrUri) { $this->_isValid = 0; if (isset($this->_packageInfo['channel'])) { $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $packageOrUri, 'srcpackage'); } else { $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $packageOrUri, 'srcuri'); } } /** * Generate a valid change log entry from the current package.xml * @param string|false */ function generateChangeLogEntry($notes = false) { return array( 'version' => array( 'release' => $this->getVersion('release'), 'api' => $this->getVersion('api'), ), 'stability' => $this->getStability(), 'date' => $this->getDate(), 'license' => $this->getLicense(true), 'notes' => $notes ? $notes : $this->getNotes() ); } /** * @param string release version to set change log notes for * @param array output of {@link generateChangeLogEntry()} */ function setChangelogEntry($releaseversion, $contents) { if (!isset($this->_packageInfo['changelog'])) { $this->_packageInfo['changelog']['release'] = $contents; return; } if (!isset($this->_packageInfo['changelog']['release'][0])) { if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) { $this->_packageInfo['changelog']['release'] = array( $this->_packageInfo['changelog']['release']); } else { $this->_packageInfo['changelog']['release'] = array( $this->_packageInfo['changelog']['release']); return $this->_packageInfo['changelog']['release'][] = $contents; } } foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) { if (isset($changelog['version']) && strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) { $curlog = $index; } } if (isset($curlog)) { $this->_packageInfo['changelog']['release'][$curlog] = $contents; } else { $this->_packageInfo['changelog']['release'][] = $contents; } } /** * Remove the changelog entirely */ function clearChangeLog() { unset($this->_packageInfo['changelog']); } }PK!5zzbase/endpoint/index.phpnu[PK!z4xx$base/endpoint/index/all-children.phpnu[PK!mx*base/endpoint/index/sub-index-endpoint.phpnu[PK!>7 base/endpoint.phpnu[PK!Hcgg base/processor.phpnu[PK!))$base/base-route.phpnu[PK!e!!Mbase/processor/after.phpnu[PK! wPPbase/processor/before.phpnu[PK!gj..Rbase/controller.phpnu[PK!_#[[Kbase/exceptions/error-404.phpnu[PK!Hqq&base/exceptions/wp-error-exception.phpnu[PK!Uhmm"base/exceptions/data-exception.phpnu[PK!SJnnybase/exceptions/error-500.phpnu[PK!]"## 4manager.phpnu[PK!C8LL Validator.phpnu[PK!=__rw.phpnu[PKa