/**
  * @param array $input_settings     {
  * @type string $model_name         the name of model to be used for searching, both via the REST API and server-side model queries
  * @type array  $query_params       default query parameters which will apply to both REST API queries and server-side queries. This should be 
  *									in the exact format that will be used for server-side model usage (eg use index 0 for where conditions, not 
  *									the string "where")
  * @type string $value_field_name   the name of the model field on this model to
  *                                  be used for the HTML select's option's values
  * @type string $display_field_name the name of the model field on this model
  *                                  to be used for the HTML select's option's display text
  * @type array  $select2_args       arguments to be passed directly into the select2's JS constructor
  *                                  }
  *                                  And the arguments accepted by EE_Form_Input_With_Options_Base
  * @throws \EE_Error
  */
 public function __construct($input_settings = array())
 {
     //needed input settings:
     //select2_args
     $this->_model_name = EEH_Array::is_set($input_settings, 'model_name', null);
     $model = $this->_get_model();
     $query_params = EEH_Array::is_set($input_settings, 'query_params', array('limit' => 10, 'caps' => EEM_Base::caps_read_admin));
     $this->_value_field_name = EEH_Array::is_set($input_settings, 'value_field_name', $model->primary_key_name());
     $this->_display_field_name = EEH_Array::is_set($input_settings, 'display_field_name', $model->get_a_field_of_type('EE_Text_Field_Base')->get_name());
     $this->_add_validation_strategy(new EE_Model_Matching_Query_Validation_Strategy('', $this->_model_name, $query_params, $this->_value_field_name));
     //get resource endpoint
     $rest_controller = new EventEspresso\core\libraries\rest_api\controllers\model\Read();
     $rest_controller->set_requested_version(EED_Core_Rest_Api::latest_rest_api_version());
     $url = $rest_controller->get_versioned_link_to(EEH_Inflector::pluralize_and_lower($this->_model_name));
     $default_select2_args = array('ajax' => array('url' => $url, 'dataType' => 'json', 'delay' => '250', 'data_interface' => 'EE_Select2_REST_API_Interface', 'data_interface_args' => array('default_query_params' => (object) Model_Data_Translator::prepare_query_params_for_rest_api($query_params, $model), 'display_field' => $this->_display_field_name, 'value_field' => $this->_value_field_name, 'nonce' => wp_create_nonce('wp_rest'))), 'cache' => true, 'width' => '100');
     $select2_args = array_replace_recursive($default_select2_args, (array) EEH_Array::is_set($input_settings, 'select2_args', array()));
     $this->set_display_strategy(new EE_Select2_Display_Strategy($select2_args));
     parent::__construct(array(), $input_settings);
 }
 /**
  * About all child constructors:
  * they should define the _tables, _fields and _model_relations arrays.
  * Should ALWAYS be called after child constructor.
  * In order to make the child constructors to be as simple as possible, this parent constructor
  * finalizes constructing all the object's attributes.
  * Generally, rather than requiring a child to code
  * $this->_tables = array(
  *        'Event_Post_Table' => new EE_Table('Event_Post_Table','wp_posts')
  *        ...);
  *  (thus repeating itself in the array key and in the constructor of the new EE_Table,)
  * each EE_Table has a function to set the table's alias after the constructor, using
  * the array key ('Event_Post_Table'), instead of repeating it. The model fields and model relations
  * do something similar.
  *
  * @param null $timezone
  * @throws \EE_Error
  */
 protected function __construct($timezone = NULL)
 {
     // check that the model has not been loaded too soon
     if (!did_action('AHEE__EE_System__load_espresso_addons')) {
         throw new EE_Error(sprintf(__('The %1$s model can not be loaded before the "AHEE__EE_System__load_espresso_addons" hook has been called. This gives other addons a chance to extend this model.', 'event_espresso'), get_class($this)));
     }
     /**
      * Filters the list of tables on a model. It is best to NOT use this directly and instead
      * just use EE_Register_Model_Extension
      * @var EE_Table_Base[] $_tables
      */
     $this->_tables = apply_filters('FHEE__' . get_class($this) . '__construct__tables', $this->_tables);
     foreach ($this->_tables as $table_alias => $table_obj) {
         /** @var $table_obj EE_Table_Base */
         $table_obj->_construct_finalize_with_alias($table_alias);
         if ($table_obj instanceof EE_Secondary_Table) {
             /** @var $table_obj EE_Secondary_Table */
             $table_obj->_construct_finalize_set_table_to_join_with($this->_get_main_table());
         }
     }
     /**
      * Filters the list of fields on a model. It is best to NOT use this directly and instead just use
      * EE_Register_Model_Extension
      * @param EE_Model_Field_Base[] $_fields
      */
     $this->_fields = apply_filters('FHEE__' . get_class($this) . '__construct__fields', $this->_fields);
     foreach ($this->_fields as $table_alias => $fields_for_table) {
         if (!array_key_exists($table_alias, $this->_tables)) {
             throw new EE_Error(sprintf(__("Table alias %s does not exist in EEM_Base child's _tables array. Only tables defined are %s", 'event_espresso'), $table_alias, implode(",", $this->_fields)));
         }
         foreach ($fields_for_table as $field_name => $field_obj) {
             /** @var $field_obj EE_Model_Field_Base | EE_Primary_Key_Field_Base */
             //primary key field base has a slightly different _construct_finalize
             /** @var $field_obj EE_Model_Field_Base */
             $field_obj->_construct_finalize($table_alias, $field_name, $this->get_this_model_name());
         }
     }
     // everything is related to Extra_Meta
     if (get_class($this) != 'EEM_Extra_Meta') {
         //make extra meta related to everything, but don't block deleting things just
         //because they have related extra meta info. For now just orphan those extra meta
         //in the future we should automatically delete them
         $this->_model_relations['Extra_Meta'] = new EE_Has_Many_Any_Relation(FALSE);
     }
     //and change logs
     if (get_class($this) != 'EEM_Change_Log') {
         $this->_model_relations['Change_Log'] = new EE_Has_Many_Any_Relation(FALSE);
     }
     /**
      * Filters the list of relations on a model. It is best to NOT use this directly and instead just use
      * EE_Register_Model_Extension
      * @param EE_Model_Relation_Base[] $_model_relations
      */
     $this->_model_relations = apply_filters('FHEE__' . get_class($this) . '__construct__model_relations', $this->_model_relations);
     foreach ($this->_model_relations as $model_name => $relation_obj) {
         /** @var $relation_obj EE_Model_Relation_Base */
         $relation_obj->_construct_finalize_set_models($this->get_this_model_name(), $model_name);
     }
     foreach ($this->_indexes as $index_name => $index_obj) {
         /** @var $index_obj EE_Index */
         $index_obj->_construct_finalize($index_name, $this->get_this_model_name());
     }
     $this->set_timezone($timezone);
     //finalize default where condition strategy, or set default
     if (!$this->_default_where_conditions_strategy) {
         //nothing was set during child constructor, so set default
         $this->_default_where_conditions_strategy = new EE_Default_Where_Conditions();
     }
     $this->_default_where_conditions_strategy->_finalize_construct($this);
     //if the cap slug hasn't been set, and we haven't set it to false on purpose
     //to indicate to NOT set it, set it to the logical default
     if ($this->_caps_slug === null) {
         EE_Registry::instance()->load_helper('Inflector');
         $this->_caps_slug = EEH_Inflector::pluralize_and_lower($this->get_this_model_name());
     }
     //initialize the standard cap restriction generators if none were specified by the child constructor
     if ($this->_cap_restriction_generators !== false) {
         foreach ($this->cap_contexts_to_cap_action_map() as $cap_context => $action) {
             if (!isset($this->_cap_restriction_generators[$cap_context])) {
                 $this->_cap_restriction_generators[$cap_context] = apply_filters('FHEE__EEM_Base___construct__standard_cap_restriction_generator', new EE_Restriction_Generator_Protected(), $cap_context, $this);
             }
         }
     }
     //if there are cap restriction generators, use them to make the default cap restrictions
     if ($this->_cap_restriction_generators !== false) {
         foreach ($this->_cap_restriction_generators as $context => $generator_object) {
             if (!$generator_object) {
                 continue;
             }
             if (!$generator_object instanceof EE_Restriction_Generator_Base) {
                 throw new EE_Error(sprintf(__('Index "%1$s" in the model %2$s\'s _cap_restriction_generators is not a child of EE_Restriction_Generator_Base. It should be that or NULL.', 'event_espresso'), $context, $this->get_this_model_name()));
             }
             $action = $this->cap_action_for_context($context);
             if (!$generator_object->construction_finalized()) {
                 $generator_object->_construct_finalize($this, $action);
             }
         }
     }
     do_action('AHEE__' . get_class($this) . '__construct__end');
 }
 /**
  * Gets the correct lowercase name for the relation in the API according
  * to the relation's type
  * @param string $relation_name
  * @param \EE_Model_Relation_Base $relation_obj
  * @return string
  */
 public static function get_related_entity_name($relation_name, $relation_obj)
 {
     if ($relation_obj instanceof \EE_Belongs_To_Relation) {
         return strtolower($relation_name);
     } else {
         return \EEH_Inflector::pluralize_and_lower($relation_name);
     }
 }
 /**
  * Gets all the route information relating to EE models
  * @return array @see get_ee_route_data
  */
 protected function _register_model_routes()
 {
     EE_Registry::instance()->load_helper('Inflector');
     $models_to_register = apply_filters('FHEE__EED_Core_REST_API___register_model_routes', EE_Registry::instance()->non_abstract_db_models);
     //let's not bother having endpoints for extra metas
     unset($models_to_register['Extra_Meta']);
     unset($models_to_register['Extra_Join']);
     $model_routes = array();
     foreach (self::versions_served() as $version => $hidden_endpoint) {
         foreach ($models_to_register as $model_name => $model_classname) {
             //yes we could just register one route for ALL models, but then they wouldn't show up in the index
             $ee_namespace = self::ee_api_namespace . $version;
             $plural_model_route = EEH_Inflector::pluralize_and_lower($model_name);
             $singular_model_route = $plural_model_route . '/(?P<id>\\d+)';
             $model_routes[$ee_namespace][$plural_model_route] = array(array('callback' => array('EventEspresso\\core\\libraries\\rest_api\\controllers\\model\\Read', 'handle_request_get_all'), 'methods' => WP_REST_Server::READABLE, 'hidden_endpoint' => $hidden_endpoint, 'args' => $this->_get_read_query_params($model_name), '_links' => array('self' => rest_url($ee_namespace . $singular_model_route))));
             $model_routes[$ee_namespace][$singular_model_route] = array(array('callback' => array('EventEspresso\\core\\libraries\\rest_api\\controllers\\model\\Read', 'handle_request_get_one'), 'methods' => WP_REST_Server::READABLE, 'hidden_endpoint' => $hidden_endpoint, 'args' => array('include' => array('required' => false, 'default' => '*', 'description' => __('See http://developer.eventespresso.com/docs/ee4-rest-api-reading/#Including_Specific_Fields_and_Related_Entities_in_Results for documentation', 'event_espresso')))));
             //@todo: also handle  DELETE for a single item
             $model = EE_Registry::instance()->load_model($model_classname);
             foreach ($model->relation_settings() as $relation_name => $relation_obj) {
                 $related_model_name_endpoint_part = EventEspresso\core\libraries\rest_api\controllers\model\Read::get_related_entity_name($relation_name, $relation_obj);
                 $model_routes[$ee_namespace][$singular_model_route . '/' . $related_model_name_endpoint_part] = array(array('callback' => array('EventEspresso\\core\\libraries\\rest_api\\controllers\\model\\Read', 'handle_request_get_related'), 'methods' => WP_REST_Server::READABLE, 'hidden_endpoint' => $hidden_endpoint, 'args' => $this->_get_read_query_params($relation_name)));
                 //@todo: handle delete related and possibly remove relation (not sure hwo to distinguish)
             }
         }
     }
     return $model_routes;
 }
 public function test_singuralize_and_upper__funny_plural()
 {
     $this->assertEquals('Term_Taxonomy', EEH_Inflector::singularize_and_upper('term_taxonomies'));
 }
 /**
  * Converts a table name to its class name according to rails
  * naming conventions.
  *
  * Converts "people" to "Person"
  *
  * @access public
  * @static
  * @see tableize
  * @param    string    $table_name    Table name for getting related ClassName.
  * @return string SingularClassName
  */
 static function classify($table_name)
 {
     return EEH_Inflector::camelize(EEH_Inflector::singularize($table_name));
 }
 /**
  * Array of headers derived from EE sucess, attention, and error messages
  * @return array
  */
 protected function _get_headers_from_ee_notices()
 {
     $headers = array();
     $notices = \EE_Error::get_raw_notices();
     foreach ($notices as $notice_type => $sub_notices) {
         if (!is_array($sub_notices)) {
             continue;
         }
         foreach ($sub_notices as $notice_code => $sub_notice) {
             $headers['X-EE4-Notices-' . \EEH_Inflector::humanize($notice_type) . '[' . $notice_code . ']'] = strip_tags($sub_notice);
         }
     }
     return apply_filters('FHEE__EventEspresso\\core\\libraries\\rest_api\\controllers\\Base___get_headers_from_ee_notices__return', $headers, $this->_requested_version, $notices);
 }
 /**
  * Gets the route data for EE models in the specified version
  * @param string $version
  * @param boolean $hidden_endpoint
  * @return array
  */
 protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
 {
     $model_version_info = new \EventEspresso\core\libraries\rest_api\Model_Version_Info($version);
     $models_to_register = apply_filters('FHEE__EED_Core_REST_API___register_model_routes', $model_version_info->models_for_requested_version());
     //let's not bother having endpoints for extra metas
     unset($models_to_register['Extra_Meta']);
     unset($models_to_register['Extra_Join']);
     $model_routes = array();
     foreach ($models_to_register as $model_name => $model_classname) {
         $model = \EE_Registry::instance()->load_model($model_name);
         //yes we could just register one route for ALL models, but then they wouldn't show up in the index
         $plural_model_route = EEH_Inflector::pluralize_and_lower($model_name);
         $singular_model_route = $plural_model_route . '/(?P<id>\\d+)';
         $model_routes[$plural_model_route] = array(array('callback' => array('EventEspresso\\core\\libraries\\rest_api\\controllers\\model\\Read', 'handle_request_get_all'), 'methods' => WP_REST_Server::READABLE, 'hidden_endpoint' => $hidden_endpoint, 'args' => $this->_get_read_query_params($model, $version), '_links' => array('self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route))));
         $model_routes[$singular_model_route] = array(array('callback' => array('EventEspresso\\core\\libraries\\rest_api\\controllers\\model\\Read', 'handle_request_get_one'), 'methods' => WP_REST_Server::READABLE, 'hidden_endpoint' => $hidden_endpoint, 'args' => $this->_get_response_selection_query_params($model, $version)));
         //@todo: also handle  DELETE for a single item
         foreach ($model->relation_settings() as $relation_name => $relation_obj) {
             $related_model_name_endpoint_part = EventEspresso\core\libraries\rest_api\controllers\model\Read::get_related_entity_name($relation_name, $relation_obj);
             $model_routes[$singular_model_route . '/' . $related_model_name_endpoint_part] = array(array('callback' => array('EventEspresso\\core\\libraries\\rest_api\\controllers\\model\\Read', 'handle_request_get_related'), 'methods' => WP_REST_Server::READABLE, 'hidden_endpoint' => $hidden_endpoint, 'args' => $this->_get_read_query_params($relation_obj->get_other_model(), $version)));
             //@todo: handle delete related and possibly remove relation (not sure hwo to distinguish)
         }
     }
     return $model_routes;
 }
Beispiel #9
0
 /**
  * @param $required_permission
  * @param $attempted_calculation
  * @throws \EventEspresso\core\libraries\rest_api\Rest_Exception
  */
 protected static function _verify_current_user_can($required_permission, $attempted_calculation)
 {
     if (!current_user_can($required_permission)) {
         throw new Rest_Exception('permission_denied', sprintf(__('Permission denied, you cannot calculate %1$s on %2$s because you do not have the capability "%3$s"', 'event_espresso'), $attempted_calculation, \EEH_Inflector::pluralize_and_lower(self::get_resource_name()), $required_permission));
     }
 }