Skip to content

Commit

Permalink
Merge pull request #17 from calcinai/special-property-saving
Browse files Browse the repository at this point in the history
Models not know how to make special PUT requests for properties that need it.
  • Loading branch information
calcinai committed Mar 30, 2015
2 parents 55cf3c1 + 215403d commit 50a25a4
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 27 deletions.
20 changes: 14 additions & 6 deletions generator/generate
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ foreach($scrape_apis as $scrape_api) {
}
}

});
});

//Add here
if($current_object instanceof Model){
Expand Down Expand Up @@ -247,6 +247,15 @@ foreach($scrape_apis as $scrape_api) {
if($node->parents()->getNode(0)->tagName != 'em')
$section_name = $node->text();
});

//filtering for properties that have special PUT/DELETE URI
if(preg_match('/PUT\s\/(?<primary_model>[a-z]+)\/[a-z0-9\-]+\/(?<secondary_model>[a-z]+)/i', $node->text(), $matches)){
/** @var Model $primary_model */
if($matches['primary_model'] === $primary_model->getName() && $primary_model->hasProperty($matches['secondary_model'])){
$primary_model->getProperty($matches['secondary_model'])->save_directly = true;
}
}

break;
case 'table':
//If no section, we're in the overview table.
Expand Down Expand Up @@ -317,7 +326,6 @@ foreach($scrape_apis as $scrape_api) {
return;
}


//At this point, we will have a $current_model, so parse properties
$node->filter('tr')->each(function($node) use ($current_model){
static $mandatory, $read_only, $skip_next;
Expand Down Expand Up @@ -372,7 +380,7 @@ foreach($scrape_apis as $scrape_api) {

//add links to property (for parsing types)
$children->eq(1)->filter('a')->each(function($node) use($property){
$property->addLink($node->text(), $node->attr('href'));
$property->addLink($node->text(), $node->attr('href'));
});

}
Expand All @@ -391,10 +399,10 @@ foreach($scrape_apis as $scrape_api) {
// }
unset($section_name);
break;
//END HANDLING FOR TABLE ELEMENT
}
//END HANDLING FOR TABLE ELEMENT
}

});
});

//Debug
if($current_model !== null)
Expand Down
30 changes: 20 additions & 10 deletions generator/objects/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,6 @@ public function getUsedClasses(){
return $classes;
}

/**
* Getter for propertied
*
* @return array
*/
public function getProperties() {
return $this->properties;
}


/**
* Bit of a messy way to add properties at a position. Just so it doesn't muck about the generated property order.
* As it's an associative array there's not a lot else that can be done.
Expand Down Expand Up @@ -163,6 +153,26 @@ public function hasProperty($property_name){
return isset($this->properties[$property_name]);
}

/**
* Getter for property
*
* @param $property_name
* @return Property
*/
public function getProperty($property_name) {
return $this->properties[$property_name];
}


/**
* Getter for properties
*
* @return array
*/
public function getProperties() {
return $this->properties;
}


/**
* @return mixed
Expand Down
4 changes: 4 additions & 0 deletions generator/objects/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class Property {

private $related_object;

public $save_directly;

public function __construct($name, $description, $mandatory = false, $read_only = false, $deprecated = false){
if(strpos($name, '(deprecated)')){
$name = str_replace('(deprecated)', '', $name);
Expand All @@ -30,6 +32,8 @@ public function __construct($name, $description, $mandatory = false, $read_only
$this->description = $description;
$this->links = array();
$this->related_object = null;
$this->save_directly = false;


}

Expand Down
3 changes: 2 additions & 1 deletion generator/templates/model.twig
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,14 @@ class {{ model.ClassName }} extends Remote\Object {
* [1] - Type
* [2] - PHP type
* [3] - Is an Array
* [4] - Saves directly
*
* @return array
*/
public static function getProperties() {
return array(
{% for property in model.Properties %}
'{{ property.name }}' => array ({% if property.isMandatory %}true{% else %}false{% endif %}, self::{{ property.getTypeConstant }}, {% if property.isHintable %}'{{ property.getPHPType(true)|addslashes }}'{% else %}null{% endif %}, {% if property.isArray %}true{% else %}false{% endif %}){% if not loop.last %},{% endif %}
'{{ property.name }}' => array ({% if property.isMandatory %}true{% else %}false{% endif %}, self::{{ property.getTypeConstant }}, {% if property.isHintable %}'{{ property.getPHPType(true)|addslashes }}'{% else %}null{% endif %}, {% if property.isArray %}true{% else %}false{% endif %}, {% if property.save_directly %}true{% else %}false{% endif %}){% if not loop.last %},{% endif %}

{% endfor %}
);
Expand Down
42 changes: 40 additions & 2 deletions src/XeroPHP/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,15 @@ public function load($model) {
*/
public function save(Object $object) {

//Saves any properties that don't want to be included in the normal loop (special saving endpoints)
$this->savePropertiesDirectly($object);

if($object->isDirty()) {
$object->validate();

//In this case it's new
if($object->hasGUID()) {

$method = Request::METHOD_POST;
$uri = sprintf('%s/%s', $object::getResourceURI(), $object->getGUID());

Expand All @@ -138,7 +142,6 @@ public function save(Object $object) {
$request = new Request($this, $url, $method);

$request->setBody(Helpers::arrayToXML($data))->send();

$response = $request->getResponse();

if(false !== $element = current($response->getElements())) {
Expand All @@ -150,7 +153,6 @@ public function save(Object $object) {
return $response;

}

}


Expand Down Expand Up @@ -195,6 +197,42 @@ public function saveAll(array $objects) {
return $response;
}


/**
* Function to save properties directly which do not update via a POST
*
* This is called automatically from the save method for things like adding contacts to ContactGroups
*
* @param Object $object
* @throws Exception
*/
private function savePropertiesDirectly(Object $object){
foreach($object::getProperties() as $property_name => $meta){
if($meta[Object::KEY_SAVE_DIRECTLY] && $object->isDirty($property_name)){
//Then actually save
$property = $object->$property_name;
$property_type = get_class(current($property));

$url = new URL($this, sprintf('%s/%s/%s', $object::getResourceURI(), $object->getGUID(), $property_type::getResourceURI()));
$request = new Request($this, $url, Request::METHOD_PUT);

$property_array = array();
foreach($property as $property_object){
$property_array[] = $property_object->toStringArray();
}

$root_node_name = Helpers::pluralize($property_type::getRootNodeName());
$request->setBody(Helpers::arrayToXML(array($root_node_name => $property_array)));

$request->send();

//Set it clean so the following save might have nothing to do.
$object->setClean($property_name);
}
}
}


/**
* @param Remote\Object $object
*/
Expand Down
24 changes: 16 additions & 8 deletions src/XeroPHP/Remote/Object.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ class Object {
/**
* Keys for the meta properties array
*/
const KEY_MANDATORY = 0;
const KEY_TYPE = 1;
const KEY_PHP_TYPE = 2;
const KEY_IS_ARRAY = 3;
const KEY_MANDATORY = 0;
const KEY_TYPE = 1;
const KEY_PHP_TYPE = 2;
const KEY_IS_ARRAY = 3;
const KEY_SAVE_DIRECTLY = 4;

/**
*
Expand Down Expand Up @@ -55,12 +56,19 @@ public function __construct() {
*
* @return bool
*/
public function isDirty() {
return count($this->_dirty) > 0;
public function isDirty($property = null) {
if($property === null)
return count($this->_dirty) > 0;
else
return isset($this->_dirty[$property]);
}

public function setClean() {
$this->_dirty = array();
public function setClean($property = null) {
if($property === null)
$this->_dirty = array();
else
unset($this->_dirty[$property]);

}

/**
Expand Down

0 comments on commit 50a25a4

Please sign in to comment.