Created
June 28, 2012 09:37
-
-
Save danbettles/3010245 to your computer and use it in GitHub Desktop.
Simple, GET-only version of Rails' ActiveResource for CodeIgniter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Active_resource_model is a simple, GET-only version of Rails' ActiveResource | |
* (http://api.rubyonrails.org/classes/ActiveResource/Base.html) for CodeIgniter. | |
* | |
* Only JSON data sources are supported at present. Active_resource_model requires the CodeIgniter "curl" library | |
* (http://getsparks.org/packages/curl/show). | |
* | |
* Copy this file into application/models and then add "Active_resource_model" to the models array in | |
* application/config/autoload.php. | |
* | |
* Simply create model classes that extend "Active_resource_model". You must set the base URL of the data source | |
* (the "site" instance variable) in each subclass. Use Active_resource_model::find_by_id() and/or | |
* Active_resource_model::find_all() to fetch records. Get attributes from instances using "get_<attribute name>". | |
* | |
* @author Dan Bettles <[email protected]> | |
* @copyright 2012 Dan Bettles | |
* @license http://www.opensource.org/licenses/MIT MIT | |
*/ | |
if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |
/** | |
* Active_resource_model | |
* | |
* @author Dan Bettles <[email protected]> | |
*/ | |
class Active_resource_model extends CI_Model { | |
/** | |
* The URL of the API. | |
* | |
* @var string | |
*/ | |
public $site; | |
/** | |
* The name of the format of the data that will be requested from the API. | |
* | |
* @var string | |
*/ | |
public $format = 'json'; | |
/** | |
* The model's attributes. | |
* | |
* @var array | |
*/ | |
private $_attributes = array(); | |
/** | |
* The name of this model in the API. | |
* | |
* @var string | |
*/ | |
public $element_name; | |
/** | |
* __construct() | |
* | |
* @see parent::__construct | |
*/ | |
public function __construct() | |
{ | |
parent::__construct(); | |
$this->load->spark('curl/1.2.1'); | |
$this->load->helper('inflector'); | |
} | |
/** | |
* Returns the object with the specified ID, or throws an exception if the object doesn't exist | |
* | |
* @param mixed $object_id | |
* | |
* @return Active_resource | |
* @throws InvalidArgumentException If the ID is invalid | |
* @throws RuntimeException If the object does not exist | |
*/ | |
public function find_by_id($object_id) | |
{ | |
$this->_ensure_id_valid($object_id); | |
$api_request_url = $this->_get_api_controller_url() . '/' . $object_id . '.' . $this->_get_format(); | |
$something = $this->_fetch_json($api_request_url); | |
if ($something === FALSE) { | |
//@todo Create a more appropriate, custom exception | |
throw new RuntimeException('The object does not exist'); | |
} | |
return $something; | |
} | |
/** | |
* Returns TRUE if the specified ID is valid, or throws an exception otherwise | |
* | |
* @param mixed $object_id | |
* | |
* @return bool | |
* @throws InvalidArgumentException If the ID is invalid | |
*/ | |
private function _ensure_id_valid($object_id) | |
{ | |
if ( ! (is_scalar($object_id) AND strlen((string) $object_id))) | |
{ | |
throw new InvalidArgumentException('The ID is invalid'); | |
} | |
return TRUE; | |
} | |
/** | |
* Returns the name of the API controller corresponding to this model | |
* | |
* @return string | |
*/ | |
private function _get_api_controller_name() | |
{ | |
$element_name = $this->_get_element_name(); | |
if (is_string($element_name) AND strlen($element_name)) { | |
return plural($element_name); | |
} | |
return strtolower(plural(preg_replace('/_model$/i', '', get_class($this)))); | |
} | |
/** | |
* Returns the URL of the API, or throws an exception if the URL hasn't been set | |
* | |
* @return string | |
* @throws RuntimeException The URL of the API has not been set | |
*/ | |
private function _get_site() | |
{ | |
if ( ! strlen($this->site)) | |
{ | |
throw new RuntimeException('The URL of the API has not been set'); | |
} | |
return rtrim($this->site, '/'); | |
} | |
/** | |
* Returns the name of the format of the data that will be requested from the API | |
* | |
* @return string | |
*/ | |
private function _get_format() | |
{ | |
return ltrim($this->format, '.'); | |
} | |
/** | |
* Creates an instance of this class using values in the specified object | |
* | |
* @param stdClass $plain_object | |
* | |
* @return Active_resource_model | |
*/ | |
private function _create_instance_from_attrs(stdClass $plain_object) | |
{ | |
$instance = new $this(); | |
foreach ((array) $plain_object as $attribute_name => $attribute_value) { | |
$instance->{"set_{$attribute_name}"}($attribute_value); | |
} | |
return $instance; | |
} | |
/** | |
* Provides setters and getters for attributes | |
* | |
* @param string $method_name Name of the method | |
* @param array $arguments Arguments passed to the method | |
* | |
* @return mixed | |
* @throws RuntimeException If the method does not exist | |
*/ | |
public function __call($method_name, array $arguments) | |
{ | |
$method_supported = (bool) preg_match('/^(set|get)_(.+)/', $method_name, $matches); | |
if ( ! $method_supported) { | |
throw new RuntimeException('The method does not exist'); | |
} | |
switch ($matches[1]) { | |
case 'set': | |
$this->_attributes[$matches[2]] = reset($arguments); | |
break; | |
case 'get': | |
return $this->_attributes[$matches[2]]; | |
break; | |
} | |
} | |
/** | |
* Returns the URL of the API controller corresponding to this model | |
* | |
* @return string | |
*/ | |
private function _get_api_controller_url() | |
{ | |
return $this->_get_site() . '/' . $this->_get_api_controller_name(); | |
} | |
/** | |
* Returns all objects | |
* | |
* @param array [$arguments = array()] | |
* | |
* @return array | |
*/ | |
public function find_all(array $arguments = array()) | |
{ | |
$api_request_url = $this->_get_api_controller_url() . '.' . $this->_get_format(); | |
$api_request_url .= $this->_create_api_req_url_query($arguments); | |
$something = $this->_fetch_json($api_request_url); | |
return $something === FALSE ? array() : $something; | |
} | |
/** | |
* Returns either a single object or an array of objects, or FALSE if the API returned nothing | |
* | |
* @param string $api_request_url URL | |
* | |
* @return mixed | |
*/ | |
private function _fetch_json($api_request_url) | |
{ | |
$json = $this->curl->simple_get($api_request_url); | |
if ($json === FALSE) { | |
return FALSE; | |
} | |
$something = json_decode($json); | |
if (is_array($something)) { | |
$objects = array(); | |
foreach ($something as $plain_object) { | |
$objects[] = $this->_create_instance_from_attrs($plain_object); | |
} | |
return $objects; | |
} | |
return $this->_create_instance_from_attrs($something); | |
} | |
/** | |
* Creates a query-string for an API request URL from the specified arguments | |
* | |
* @param array $arguments | |
* | |
* @return string | |
*/ | |
private function _create_api_req_url_query(array $arguments) | |
{ | |
return empty($arguments) ? '' : '?' . http_build_query($arguments); | |
} | |
/** | |
* Returns the element name | |
* | |
* @return string | |
*/ | |
private function _get_element_name() | |
{ | |
return $this->element_name; | |
} | |
} | |
//Location: ./models/active_resource_model.php | |
//End of file active_resource_model.php |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Release_model | |
* | |
* @author Dan Bettles <[email protected]> | |
* @copyright 2012 Dan Bettles | |
* @license http://www.opensource.org/licenses/MIT MIT | |
*/ | |
/** | |
* Release_model | |
* | |
* @author Dan Bettles <[email protected]> | |
*/ | |
class Release_model extends Active_resource_model { | |
/** | |
* Tracks. | |
* | |
* @var array | |
*/ | |
private $_release_tracks = array(); | |
/** | |
* __construct | |
*/ | |
public function __construct() | |
{ | |
parent::__construct(); | |
$archaic_horizon_api_cfg = $this->config->item('archaic_horizon_api', 'app'); | |
$this->site = $archaic_horizon_api_cfg['site']; | |
} | |
/** | |
* Scope | |
* | |
* Returns all releases in reverse chronological order | |
* | |
* @return array | |
*/ | |
public function history() | |
{ | |
return $this->find_all(array('order' => 'released_at', 'in_reverse' => 1)); | |
} | |
/** | |
* Scope | |
* | |
* Returns the summary of the latest release or throws an exception otherwise | |
* | |
* @return Release_model | |
* @throws RuntimeException If there is no latest release | |
*/ | |
public function latest_summary() | |
{ | |
$something = $this->find_all(array( | |
'order' => 'released_at', | |
'in_reverse' => 1, | |
'num_per_page' => 1, | |
'page' => 1 | |
)); | |
if (empty($something)) { | |
throw new RuntimeException('There is no latest release'); | |
} | |
return reset($something); | |
} | |
/** | |
* Returns the description in HTML format | |
* | |
* @return string | |
*/ | |
public function get_description_html() | |
{ | |
$this->load->spark('markdown/1.2.0'); | |
return parse_markdown($this->get_description()); | |
} | |
/** | |
* Fetches the specified release and then fetches its associated objects | |
* | |
* @see parent::find_by_id() | |
*/ | |
public function find_by_id($object_id) | |
{ | |
$release = parent::find_by_id($object_id); | |
$release->_fetch_release_tracks(); | |
return $release; | |
} | |
/** | |
* _fetch_release_tracks | |
* | |
* @return void | |
*/ | |
private function _fetch_release_tracks() | |
{ | |
$this->load->model('Release_track_model'); | |
$this->_release_tracks = $this->Release_track_model->find_all(array( | |
'release_code' => $this->get_code(), | |
'order' => 'position' | |
)); | |
} | |
/** | |
* get_release_tracks | |
* | |
* @return array | |
*/ | |
public function get_release_tracks() | |
{ | |
return $this->_release_tracks; | |
} | |
} | |
//Location: ./models/release_model.php | |
//End of file release_model.php |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Release_track_model | |
* | |
* @author Dan Bettles <[email protected]> | |
* @copyright 2012 Dan Bettles | |
*/ | |
/** | |
* Release_track_model | |
* | |
* @author Dan Bettles <[email protected]> | |
*/ | |
class Release_track_model extends Active_resource_model { | |
/** | |
* __construct | |
*/ | |
public function __construct() | |
{ | |
parent::__construct(); | |
$archaic_horizon_api_cfg = $this->config->item('archaic_horizon_api', 'app'); | |
$this->site = $archaic_horizon_api_cfg['site']; | |
$this->element_name = 'track'; | |
} | |
/** | |
* Returns the length of the track in an ISO 8601 duration | |
* | |
* @return string | |
*/ | |
public function get_iso_8601_duration() | |
{ | |
list($minutes, $seconds) = explode(':', $this->get_time(), 2); | |
return "PT{$minutes}M{$seconds}S"; | |
} | |
} | |
//Location: ./models/release_track_model.php | |
//End of file release_track_model.php |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment