Skip to content

Commit

Permalink
Introduced feature #12 for saving batches of objects
Browse files Browse the repository at this point in the history
  • Loading branch information
calcinai committed Mar 20, 2015
1 parent e975ec1 commit 79a22ce
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 21 deletions.
65 changes: 58 additions & 7 deletions src/XeroPHP/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,29 @@ abstract class Application {
protected $config;
protected $oauth_client;

/**
* @param array $user_config
*/
public function __construct(array $user_config){
//better here for overriding
$this->config = array_replace_recursive(self::$_config_defaults, static::$_type_config_defaults, $user_config);

$this->oauth_client = new Client($this->config['oauth']);
}

/**
* @return Client
*/
public function getOAuthClient(){
return $this->oauth_client;
}



/**
* @param $key
* @return mixed
* @throws Exception
*/
public function getConfig($key){

if(!isset($this->config[$key]))
Expand All @@ -69,6 +79,12 @@ public function getConfig($key){
return $this->config[$key];
}

/**
* @param $model
* @param $guid
* @return mixed
* @throws Exception
*/
public function loadByGUID($model, $guid){

$query = $this->load($model);
Expand All @@ -85,13 +101,23 @@ public function loadByGUID($model, $guid){
}


/**
* @param $model
* @return $this
* @throws Remote\Exception
*/
public function load($model){

$query = new Query($this);
return $query->from($model);
}


/**
* @param Remote\Object $object
* @return null
* @throws Exception
*/
public function save(Object $object){

if($object->isDirty()) {
Expand All @@ -115,16 +141,28 @@ public function save(Object $object){
$url = new URL($this, $uri);
$request = new Request($this, $url, $method);

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

$response = $request->getResponse();

if(false !== $element = current($response->getElements())) {
$object->fromStringArray($element);
}
//Mark the object as clean since no exception was thrown
$object->setClean();

return $request->getResponse();
return $response;

}

}


/**
* @param array $objects
* @return null
* @throws Exception
*/
public function saveAll(array $objects){

//Just get one type to compare with, doesn't matter which.
Expand All @@ -145,12 +183,25 @@ public function saveAll(array $objects){
$root_node_name = Helpers::pluralize($type::getRootNodeName());
$data = array($root_node_name => $object_arrays);

$request->setBody(Helpers::arrayToXML($data))
->send();
$request->setBody(Helpers::arrayToXML($data));
$request->setParameter('SummarizeErrors', 'false');
$request->send();

$response = $request->getResponse();

foreach($response->getElements() as $element_index => $element){
if($response->getErrorsForElement($element_index) === null){
$objects[$element_index]->fromStringArray($element);
$objects[$element_index]->setClean();
}
}

return $request->getResponse();
return $response;
}

/**
* @param Remote\Object $object
*/
public function delete(Object $object){

}
Expand Down
17 changes: 16 additions & 1 deletion src/XeroPHP/Remote/Object.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ public function isDirty(){
return count($this->_dirty) > 0;
}

public function setClean(){
$this->_dirty = array();
}

/**
* This is used to detect if the object has copy at the source
*
Expand All @@ -76,18 +80,29 @@ public function getGUID(){
$this->_data[static::getGUIDProperty()];
}


public function setGUID($guid){
$this->_data[static::getGUIDProperty()] = $guid;
}

/**
* Load an assoc array into the instance of the object $property => $value
* $replace_data - replace existing data
*
* @param $input_array
* @param $replace_data
* @return Object
*/
public function fromStringArray($input_array){
public function fromStringArray($input_array, $replace_data = false){

foreach(static::getProperties() as $property => $meta) {
$type = $meta[self::KEY_TYPE];
$php_type = $meta[self::KEY_PHP_TYPE];

//If set and NOT replace data, continue
if(!$replace_data && isset($this->_data[$property]))
continue;

if(!isset($input_array[$property]))
continue;

Expand Down
1 change: 1 addition & 0 deletions src/XeroPHP/Remote/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public function execute(){

$request->send();

$elements = array();
foreach($request->getResponse()->getElements() as $element){
$built_element = new $from_class;
$built_element->fromStringArray($element);
Expand Down
1 change: 0 additions & 1 deletion src/XeroPHP/Remote/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use XeroPHP\Application;
use XeroPHP\Exception;
use XeroPHP\Helpers;
use XeroPHP\Remote\OAuth\Client;


class Request {
Expand Down
44 changes: 32 additions & 12 deletions src/XeroPHP/Remote/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ public function parse(){
}

case Response::STATUS_UNAUTHORISED:
//This is where OAuth errors end up, this could maybe change to an OAuth exception
if(isset($this->oauth_response['oauth_problem_advice'])){
throw new UnauthorizedException($this->oauth_response['oauth_problem_advice']);
}
case Response::STATUS_FORBIDDEN:
throw new UnauthorizedException();

Expand All @@ -84,6 +88,14 @@ public function getElements(){
return $this->elements;
}

public function getErrorsForElement($element_id){
if(isset($this->element_errors[$element_id])){
return $this->element_errors[$element_id];
}

return null;
}

public function getElementErrors(){
return $this->element_errors;
}
Expand All @@ -102,10 +114,8 @@ public function getOAuthResponse(){

public function parseBody(){

if($this->request->getUrl()->isOAuth()){
parse_str($this->response_body, $this->oauth_response);
return;
}
if($this->request->getUrl()->isOAuth())
return $this->parseHTML();

$this->elements = array();
$this->element_errors = array();
Expand All @@ -114,40 +124,45 @@ public function parseBody(){

switch($this->content_type){
case Request::CONTENT_TYPE_XML:
self::parseXML();
$this->parseXML();
break;

case Request::CONTENT_TYPE_JSON:
self::parseJSON();
$this->parseJSON();
break;

case Request::CONTENT_TYPE_HTML:
$this->parseHTML();
break;

default:
throw new Exception("Parsing method not implemented for [{$this->content_type}]");
}

foreach($this->elements as $element)
$this->findElementErrors($element);
foreach($this->elements as $index => $element)
$this->findElementErrors($element, $index);
}


public function findElementErrors($element){
public function findElementErrors($element, $element_index){
foreach($element as $property => $value){
switch((string) $property){
case 'ValidationErrors':
if(is_array($value)){
foreach($value as $error)
$this->element_errors[] = trim($error['Message'], '.');
$this->element_errors[$element_index] = trim($error['Message'], '.');
}
break;
case 'Warnings':
if(is_array($value)){
foreach($value as $warning)
$this->element_warnings[] = trim($warning['Message'], '.');
$this->element_warnings[$element_index] = trim($warning['Message'], '.');
}
break;

default:
if(is_array($value)){
$this->findElementErrors($value);
$this->findElementErrors($value, $element_index);
}
}
}
Expand Down Expand Up @@ -210,5 +225,10 @@ public function parseJSON(){

}

//Xero sends text/html when it's an oauth response for some reason.
public function parseHTML(){
parse_str($this->response_body, $this->oauth_response);
}


}

1 comment on commit 79a22ce

@calcinai
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple of misc whitespace cleanups and default doc blocks in here too.

Please sign in to comment.