PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/classes/webservice/WebserviceOutputBuilder.php

https://github.com/netplayer/PrestaShop
PHP | 810 lines | 571 code | 68 blank | 171 comment | 112 complexity | 1ab6a36357745f7fdb8f162a4543c144 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, LGPL-3.0
  1. <?php
  2. /*
  3. * 2007-2014 PrestaShop
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@prestashop.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
  18. * versions in the future. If you wish to customize PrestaShop for your
  19. * needs please refer to http://www.prestashop.com for more information.
  20. *
  21. * @author PrestaShop SA <contact@prestashop.com>
  22. * @copyright 2007-2014 PrestaShop SA
  23. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  24. * International Registered Trademark & Property of PrestaShop SA
  25. */
  26. /**
  27. * @todo : Create typed exception for more finer errors check
  28. */
  29. class WebserviceOutputBuilderCore
  30. {
  31. /**
  32. *
  33. * @var int constant
  34. */
  35. const VIEW_LIST = 1;
  36. const VIEW_DETAILS = 2;
  37. protected $wsUrl;
  38. protected $output;
  39. public $objectRender;
  40. protected $wsResource;
  41. protected $depth = 0;
  42. protected $schemaToDisplay;
  43. protected $fieldsToDisplay;
  44. protected $specificFields = array();
  45. protected $virtualFields = array();
  46. protected $statusInt;
  47. protected $wsParamOverrides;
  48. protected static $_cache_ws_parameters = array();
  49. // Header properties
  50. protected $headerParams = array(
  51. 'Access-Time' => 0,
  52. 'X-Powered-By' => 0,
  53. 'PSWS-Version' => 0,
  54. 'Content-Type' => 0,
  55. );
  56. /**
  57. * @var string Status header sent at return
  58. */
  59. protected $status;
  60. public function __construct($ws_url)
  61. {
  62. $this->statusInt = 200;
  63. $this->status = $_SERVER['SERVER_PROTOCOL'].' 200 OK';
  64. $this->wsUrl = $ws_url;
  65. $this->wsParamOverrides = array();
  66. }
  67. /**
  68. * Set the render object for set the output format.
  69. * Set the Content-type for the http header.
  70. *
  71. * @param WebserviceOutputInterface $obj_render
  72. * @throw WebserviceException if the object render is not an instance of WebserviceOutputInterface
  73. * @return $this
  74. */
  75. public function setObjectRender(WebserviceOutputInterface $obj_render)
  76. {
  77. if (!$obj_render instanceof WebserviceOutputInterface)
  78. throw new WebserviceException('Obj_render param must be an WebserviceOutputInterface object type', array(83, 500));
  79. $this->objectRender = $obj_render;
  80. $this->objectRender->setWsUrl($this->wsUrl);
  81. if ($this->objectRender->getContentType())
  82. $this->setHeaderParams('Content-Type', $this->objectRender->getContentType());
  83. return $this;
  84. }
  85. /**
  86. * getter
  87. * @return WebserviceOutputInterface
  88. */
  89. public function getObjectRender()
  90. {
  91. return $this->objectRender;
  92. }
  93. /**
  94. * Need to have the resource list to get the class name for an entity,
  95. * To build
  96. *
  97. * @param array $resources
  98. * @return $this
  99. */
  100. public function setWsResources($resources)
  101. {
  102. $this->wsResource = $resources;
  103. return $this;
  104. }
  105. /**
  106. * This method return an array with each http header params for a content.
  107. * This check each required params.
  108. *
  109. * If this method is overrided don't forget to check required specific params (for xml etc...)
  110. *
  111. * @return array
  112. */
  113. public function buildHeader()
  114. {
  115. $return = array();
  116. $return[] = $this->status;
  117. foreach ($this->headerParams as $key => $param)
  118. {
  119. $return[] = trim($key).': '.$param;
  120. }
  121. return $return;
  122. }
  123. /**
  124. * @param string $key The normalized key expected for an http response
  125. * @param string $value
  126. * @throw WebserviceException if the key or the value are corrupted
  127. * (use Validate::isCleanHtml method)
  128. * @return $this
  129. */
  130. public function setHeaderParams($key, $value)
  131. {
  132. if (!Validate::isCleanHtml($key) OR !Validate::isCleanHtml($value))
  133. throw new WebserviceException('the key or your value is corrupted.', array(94, 500));
  134. $this->headerParams[$key] = $value;
  135. return $this;
  136. }
  137. /**
  138. * @param null|string $key if null get all header params otherwise the params specified by the key
  139. * @throw WebserviceException if the key is corrupted (use Validate::isCleanHtml method)
  140. * @throw WebserviceException if the asked key does'nt exists.
  141. * @return array|string
  142. */
  143. public function getHeaderParams($key = null)
  144. {
  145. $return = '';
  146. if (!is_null($key))
  147. {
  148. if (!Validate::isCleanHtml($key))
  149. throw new WebserviceException('the key you write is a corrupted text.', array(95, 500));
  150. if (!array_key_exists($key, $this->headerParams))
  151. throw new WebserviceException(sprintf('The key %s does\'nt exist', $key), array(96, 500));
  152. $return = $this->headerParams[$key];
  153. }
  154. else
  155. $return = $this->headerParams;
  156. return $return;
  157. }
  158. /**
  159. * Delete all Header parameters previously set.
  160. *
  161. * @return $this
  162. */
  163. public function resetHeaderParams()
  164. {
  165. $this->headerParams = array();
  166. return $this;
  167. }
  168. /**
  169. * @return string the normalized status for http request
  170. */
  171. public function getStatus()
  172. {
  173. return $this->status;
  174. }
  175. public function getStatusInt()
  176. {
  177. return $this->statusInt;
  178. }
  179. /**
  180. * Set the return header status
  181. *
  182. * @param int $num the Http status code
  183. * @return void
  184. */
  185. public function setStatus($num)
  186. {
  187. $this->statusInt = (int)$num;
  188. switch ($num)
  189. {
  190. case 200 :
  191. $this->status = $_SERVER['SERVER_PROTOCOL'].' 200 OK';
  192. break;
  193. case 201 :
  194. $this->status = $_SERVER['SERVER_PROTOCOL'].' 201 Created';
  195. break;
  196. case 204 :
  197. $this->status = $_SERVER['SERVER_PROTOCOL'].' 204 No Content';
  198. break;
  199. case 304 :
  200. $this->status = $_SERVER['SERVER_PROTOCOL'].' 304 Not Modified';
  201. break;
  202. case 400 :
  203. $this->status = $_SERVER['SERVER_PROTOCOL'].' 400 Bad Request';
  204. break;
  205. case 401 :
  206. $this->status = $_SERVER['SERVER_PROTOCOL'].' 401 Unauthorized';
  207. break;
  208. case 403 :
  209. $this->status = $_SERVER['SERVER_PROTOCOL'].' 403 Forbidden';
  210. break;
  211. case 404 :
  212. $this->status = $_SERVER['SERVER_PROTOCOL'].' 404 Not Found';
  213. break;
  214. case 405 :
  215. $this->status = $_SERVER['SERVER_PROTOCOL'].' 405 Method Not Allowed';
  216. break;
  217. case 500 :
  218. $this->status = $_SERVER['SERVER_PROTOCOL'].' 500 Internal Server Error';
  219. break;
  220. case 501 :
  221. $this->status = $_SERVER['SERVER_PROTOCOL'].' 501 Not Implemented';
  222. break;
  223. case 503 :
  224. $this->status = $_SERVER['SERVER_PROTOCOL'].' 503 Service Unavailable';
  225. break;
  226. }
  227. }
  228. /**
  229. * Build errors output using an error array
  230. *
  231. * @param array $errors
  232. * @return string output in the format specified by WebserviceOutputBuilder::objectRender
  233. */
  234. public function getErrors($errors)
  235. {
  236. if (!empty($errors))
  237. {
  238. if (isset($this->objectRender))
  239. {
  240. $str_output = $this->objectRender->renderErrorsHeader();
  241. foreach ($errors as $error)
  242. {
  243. if (is_array($error))
  244. $str_output .= $this->objectRender->renderErrors($error[1], $error[0]);
  245. else
  246. $str_output .= $this->objectRender->renderErrors($error);
  247. }
  248. $str_output .= $this->objectRender->renderErrorsFooter();
  249. $str_output = $this->objectRender->overrideContent($str_output);
  250. }
  251. else
  252. {
  253. $str_output = '<pre>'.print_r($errors, true).'</pre>';
  254. }
  255. }
  256. return $str_output;
  257. }
  258. /**
  259. * Build the resource list in the output format specified by WebserviceOutputBuilder::objectRender
  260. * @param $key_permissions
  261. * @return string
  262. */
  263. public function getResourcesList($key_permissions)
  264. {
  265. if (is_null($this->wsResource))
  266. throw new WebserviceException ('You must set web service resource for get the resources list.', array(82, 500));
  267. $output = '';
  268. $more_attr = array('shop_name' => htmlspecialchars(Configuration::get('PS_SHOP_NAME')));
  269. $output .= $this->objectRender->renderNodeHeader('api', array(), $more_attr);
  270. foreach ($this->wsResource as $resourceName => $resource)
  271. {
  272. if (in_array($resourceName, array_keys($key_permissions)))
  273. {
  274. $more_attr = array(
  275. 'xlink_resource' => $this->wsUrl.$resourceName,
  276. 'get' => (in_array('GET', $key_permissions[$resourceName]) ? 'true' : 'false'),
  277. 'put' => (in_array('PUT', $key_permissions[$resourceName]) ? 'true' : 'false'),
  278. 'post' => (in_array('POST', $key_permissions[$resourceName]) ? 'true' : 'false'),
  279. 'delete' => (in_array('DELETE', $key_permissions[$resourceName]) ? 'true' : 'false'),
  280. 'head' => (in_array('HEAD', $key_permissions[$resourceName]) ? 'true' : 'false'),
  281. );
  282. $output .= $this->objectRender->renderNodeHeader($resourceName, array(), $more_attr);
  283. $output .= $this->objectRender->renderNodeHeader('description', array(), $more_attr);
  284. $output .= $resource['description'];
  285. $output .= $this->objectRender->renderNodeFooter('description', array());
  286. if (!isset($resource['specific_management']) || !$resource['specific_management'])
  287. {
  288. $more_attr_schema = array(
  289. 'xlink_resource' => $this->wsUrl.$resourceName.'?schema=blank',
  290. 'type' => 'blank',
  291. );
  292. $output .= $this->objectRender->renderNodeHeader('schema', array(), $more_attr_schema, false);
  293. $more_attr_schema = array(
  294. 'xlink_resource' => $this->wsUrl.$resourceName.'?schema=synopsis',
  295. 'type' => 'synopsis',
  296. );
  297. $output .= $this->objectRender->renderNodeHeader('schema', array(), $more_attr_schema, false);
  298. }
  299. $output .= $this->objectRender->renderNodeFooter($resourceName, array());
  300. }
  301. }
  302. $output .= $this->objectRender->renderNodeFooter('api', array());
  303. $output = $this->objectRender->overrideContent($output);
  304. return $output;
  305. }
  306. public function registerOverrideWSParameters($wsrObject, $method)
  307. {
  308. $this->wsParamOverrides[] = array('object' => $wsrObject, 'method' => $method);
  309. }
  310. /**
  311. * Method is used for each content type
  312. * Different content types are :
  313. * - list of entities,
  314. * - tree diagram of entity details (full or minimum),
  315. * - schema (synopsis & blank),
  316. *
  317. * @param array $objects each object created by entity asked
  318. * @see WebserviceOutputBuilder::executeEntityGetAndHead
  319. * @param null|string $schema_to_display if null display the entities list or entity details.
  320. * @param string|array $fields_to_display the fields allow for the output
  321. * @param int $depth depth for the tree diagram output.
  322. * @param int $type_of_view use the 2 constants WebserviceOutputBuilder::VIEW_LIST WebserviceOutputBuilder::VIEW_DETAILS
  323. * @return string in the output format specified by WebserviceOutputBuilder::objectRender
  324. */
  325. public function getContent($objects, $schema_to_display = null, $fields_to_display = 'minimum', $depth = 0, $type_of_view = self::VIEW_LIST, $override = true)
  326. {
  327. $this->fieldsToDisplay = $fields_to_display;
  328. $this->depth = $depth;
  329. $output = '';
  330. if ($schema_to_display != null)
  331. {
  332. $this->schemaToDisplay = $schema_to_display;
  333. $this->objectRender->setSchemaToDisplay($this->schemaToDisplay);
  334. // If a shema is asked the view must be an details type
  335. $type_of_view = self::VIEW_DETAILS;
  336. }
  337. $class = get_class($objects['empty']);
  338. if (!isset(WebserviceOutputBuilder::$_cache_ws_parameters[$class]))
  339. WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $objects['empty']->getWebserviceParameters();
  340. $ws_params = WebserviceOutputBuilder::$_cache_ws_parameters[$class];
  341. foreach ($this->wsParamOverrides AS $p)
  342. {
  343. $object = $p['object'];
  344. $ws_params = $object->{$p['method']}($ws_params);
  345. }
  346. // If a list is asked, need to wrap with a plural node
  347. if ($type_of_view === self::VIEW_LIST)
  348. $output .= $this->setIndent($depth).$this->objectRender->renderNodeHeader($ws_params['objectsNodeName'], $ws_params);
  349. if (is_null($this->schemaToDisplay))
  350. {
  351. foreach ($objects as $key => $object)
  352. {
  353. if ($key !== 'empty')
  354. {
  355. if ($this->fieldsToDisplay === 'minimum')
  356. $output .= $this->renderEntityMinimum($object, $depth);
  357. else
  358. $output .= $this->renderEntity($object, $depth);
  359. }
  360. }
  361. }
  362. else
  363. {
  364. $output .= $this->renderSchema($objects['empty'], $ws_params);
  365. }
  366. // If a list is asked, need to wrap with a plural node
  367. if ($type_of_view === self::VIEW_LIST)
  368. $output .= $this->setIndent($depth).$this->objectRender->renderNodeFooter($ws_params['objectsNodeName'], $ws_params);
  369. if ($override)
  370. $output = $this->objectRender->overrideContent($output);
  371. return $output;
  372. }
  373. /**
  374. * Create the tree diagram with no details
  375. *
  376. * @param ObjectModel $object create by the entity
  377. * @param int $depth the depth for the tree diagram
  378. * @return string
  379. */
  380. public function renderEntityMinimum($object, $depth)
  381. {
  382. $class = get_class($object);
  383. if (!isset(WebserviceOutputBuilder::$_cache_ws_parameters[$class]))
  384. WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $object->getWebserviceParameters();
  385. $ws_params = WebserviceOutputBuilder::$_cache_ws_parameters[$class];
  386. $more_attr['id'] = $object->id;
  387. $more_attr['xlink_resource'] = $this->wsUrl.$ws_params['objectsNodeName'].'/'.$object->id;
  388. $output = $this->setIndent($depth).$this->objectRender->renderNodeHeader($ws_params['objectNodeName'], $ws_params, $more_attr, false);
  389. return $output;
  390. }
  391. /**
  392. * Build a schema blank or synopsis
  393. *
  394. * @param ObjectModel $object create by the entity
  395. * @param array $ws_params webserviceParams from the entity
  396. * @return string
  397. */
  398. protected function renderSchema($object, $ws_params)
  399. {
  400. $output = $this->objectRender->renderNodeHeader($ws_params['objectNodeName'], $ws_params);
  401. foreach ($ws_params['fields'] as $field_name => $field)
  402. {
  403. $output .= $this->renderField($object, $ws_params, $field_name, $field, 0);
  404. }
  405. if (isset($ws_params['associations']) && count($ws_params['associations']) > 0)
  406. {
  407. $this->fieldsToDisplay = 'full';
  408. $output .= $this->renderAssociations($object, 0, $ws_params['associations'], $ws_params);
  409. }
  410. $output .= $this->objectRender->renderNodeFooter($ws_params['objectNodeName'], $ws_params);
  411. return $output;
  412. }
  413. /**
  414. * Build the entity detail.
  415. *
  416. * @param ObjectModel $object create by the entity
  417. * @param int $depth the depth for the tree diagram
  418. * @return string
  419. */
  420. public function renderEntity($object, $depth)
  421. {
  422. $output = '';
  423. $class = get_class($object);
  424. if (!isset(WebserviceOutputBuilder::$_cache_ws_parameters[$class]))
  425. WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $object->getWebserviceParameters();
  426. $ws_params = WebserviceOutputBuilder::$_cache_ws_parameters[$class];
  427. foreach ($this->wsParamOverrides AS $p)
  428. {
  429. $o = $p['object'];
  430. $ws_params = $o->{$p['method']}($ws_params);
  431. }
  432. $output .= $this->setIndent($depth).$this->objectRender->renderNodeHeader($ws_params['objectNodeName'], $ws_params);
  433. if ($object->id != 0)
  434. {
  435. // This to add virtual Fields for a particular entity.
  436. $virtual_fields = $this->addVirtualFields($ws_params['objectsNodeName'], $object);
  437. if (!empty($virtual_fields))
  438. $ws_params['fields'] = array_merge($ws_params['fields'], $virtual_fields);
  439. foreach ($ws_params['fields'] as $field_name => $field)
  440. {
  441. if ($this->fieldsToDisplay === 'full' || array_key_exists($field_name, $this->fieldsToDisplay))
  442. {
  443. $field['object_id'] = $object->id;
  444. $field['entity_name'] = $ws_params['objectNodeName'];
  445. $field['entities_name'] = $ws_params['objectsNodeName'];
  446. $output .= $this->renderField($object, $ws_params, $field_name, $field, $depth);
  447. }
  448. }
  449. }
  450. $subexists = false;
  451. if (is_array($this->fieldsToDisplay))
  452. foreach ($this->fieldsToDisplay as $fields)
  453. if (is_array($fields))
  454. $subexists = true;
  455. if (isset($ws_params['associations'])
  456. && ($this->fieldsToDisplay == 'full'
  457. || $subexists))
  458. {
  459. $output .= $this->renderAssociations($object, $depth, $ws_params['associations'], $ws_params);
  460. }
  461. $output .= $this->setIndent($depth).$this->objectRender->renderNodeFooter($ws_params['objectNodeName'], $ws_params);
  462. return $output;
  463. }
  464. /**
  465. * Build a field and use recursivity depend on the depth parameter.
  466. *
  467. * @param ObjectModel $object create by the entity
  468. * @param array $ws_params webserviceParams from the entity
  469. * @param string $field_name
  470. * @param array $field
  471. * @param int $depth
  472. * @return string
  473. */
  474. protected function renderField($object, $ws_params, $field_name, $field, $depth)
  475. {
  476. $output = '';
  477. $show_field = true;
  478. if (isset($ws_params['hidden_fields']) && in_array($field_name, $ws_params['hidden_fields']))
  479. return;
  480. if ($this->schemaToDisplay === 'synopsis')
  481. {
  482. $field['synopsis_details'] = $this->getSynopsisDetails($field);
  483. if ($field_name === 'id')
  484. $show_field = false;
  485. }
  486. if ($this->schemaToDisplay === 'blank')
  487. if (isset($field['setter']) && !$field['setter'])
  488. $show_field = false;
  489. // don't set any value for a schema
  490. if (isset($field['synopsis_details']) || $this->schemaToDisplay === 'blank')
  491. {
  492. $field['value'] = '';
  493. if (isset($field['xlink_resource']))
  494. unset($field['xlink_resource']);
  495. }
  496. elseif (isset($field['getter']) && $object != null && method_exists($object, $field['getter']))
  497. $field['value'] = $object->$field['getter']();
  498. elseif (!isset($field['value']))
  499. $field['value'] = $object->$field_name;
  500. // this apply specific function for a particular field on a choosen entity
  501. $field = $this->overrideSpecificField($ws_params['objectsNodeName'], $field_name, $field, $object, $ws_params);
  502. // don't display informations for a not existant id
  503. if (substr($field['sqlId'], 0, 3) == 'id_' && !$field['value'])
  504. {
  505. if ($field['value'] === null)
  506. $field['value'] = '';
  507. // delete the xlink except for schemas
  508. if (isset($field['xlink_resource']) && is_null($this->schemaToDisplay))
  509. unset($field['xlink_resource']);
  510. }
  511. // set "id" for each node name which display the id of the entity
  512. if ($field_name === 'id')
  513. $field['sqlId'] = 'id';
  514. // don't display the node id for a synopsis schema
  515. if ($show_field)
  516. $output .= $this->setIndent($depth-1).$this->objectRender->renderField($field);
  517. return $output;
  518. }
  519. /**
  520. *
  521. *
  522. * @param $object
  523. * @param $depth
  524. * @param $associations
  525. * @param $ws_params
  526. * @return string
  527. */
  528. protected function renderAssociations($object, $depth, $associations, $ws_params)
  529. {
  530. $output = $this->objectRender->renderAssociationWrapperHeader();
  531. foreach ($associations as $assoc_name => $association)
  532. {
  533. if ($this->fieldsToDisplay == 'full' || is_array($this->fieldsToDisplay) && array_key_exists($assoc_name, $this->fieldsToDisplay))
  534. {
  535. $getter = $association['getter'];
  536. $objects_assoc = array();
  537. $fields_assoc = array();
  538. if (isset($association['fields']))
  539. $fields_assoc = $association['fields'];
  540. $parent_details = array(
  541. 'object_id' => $object->id,
  542. 'entity_name' => $ws_params['objectNodeName'],
  543. 'entities_name' => $ws_params['objectsNodeName'],
  544. );
  545. if (is_array($getter))
  546. {
  547. $association_resources = call_user_func($getter, $object);
  548. if (is_array($association_resources) && !empty($association_resources))
  549. foreach ($association_resources as $association_resource)
  550. $objects_assoc[] = $association_resource;
  551. }
  552. else
  553. {
  554. if (method_exists($object, $getter) && is_null($this->schemaToDisplay))
  555. {
  556. $association_resources = $object->$getter();
  557. if (is_array($association_resources) && !empty($association_resources))
  558. foreach ($association_resources as $association_resource)
  559. $objects_assoc[] = $association_resource;
  560. }
  561. else
  562. $objects_assoc[] = '';
  563. }
  564. $class_name = null;
  565. if (isset($this->wsResource[$assoc_name]['class']) && class_exists($this->wsResource[$assoc_name]['class'], true))
  566. $class_name = $this->wsResource[$assoc_name]['class'];
  567. $output_details = '';
  568. foreach ($objects_assoc as $object_assoc)
  569. {
  570. if ($depth == 0 || $class_name === null)
  571. {
  572. $value = null;
  573. if (!empty($object_assoc))
  574. $value = $object_assoc;
  575. if (empty($fields_assoc))
  576. $fields_assoc = array(array('id' => $value['id']));
  577. $output_details .= $this->renderFlatAssociation($object, $depth, $assoc_name, $association['resource'], $fields_assoc, $value, $parent_details);
  578. }
  579. else
  580. {
  581. foreach ($object_assoc as $id)
  582. {
  583. if ($class_name !== null)
  584. {
  585. $child_object = new $class_name($id);
  586. $output_details .= $this->renderEntity($child_object, ($depth-2 ? 0 : $depth-2));
  587. }
  588. }
  589. }
  590. }
  591. if ($output_details != '')
  592. {
  593. $output .= $this->setIndent($depth).$this->objectRender->renderAssociationHeader($object, $ws_params, $assoc_name);
  594. $output .= $output_details;
  595. $output .= $this->setIndent($depth).$this->objectRender->renderAssociationFooter($object, $ws_params, $assoc_name);
  596. }
  597. else
  598. {
  599. $output .= $this->setIndent($depth).$this->objectRender->renderAssociationHeader($object, $ws_params, $assoc_name, true);
  600. }
  601. }
  602. }
  603. $output .= $this->objectRender->renderAssociationWrapperFooter();
  604. return $output;
  605. }
  606. protected function renderFlatAssociation($object, $depth, $assoc_name, $resource_name, $fields_assoc, $object_assoc, $parent_details)
  607. {
  608. $output = '';
  609. $more_attr = array();
  610. if (isset($this->wsResource[$assoc_name]) && is_null($this->schemaToDisplay))
  611. {
  612. if ($assoc_name == 'images')
  613. $more_attr['xlink_resource'] = $this->wsUrl.$assoc_name.'/'.$parent_details['entities_name'].'/'.$parent_details['object_id'].'/'.$object_assoc['id'];
  614. else
  615. $more_attr['xlink_resource'] = $this->wsUrl.$assoc_name.'/'.$object_assoc['id'];
  616. }
  617. $output .= $this->setIndent($depth-1).$this->objectRender->renderNodeHeader($resource_name, array(), $more_attr);
  618. foreach ($fields_assoc as $field_name=>$field)
  619. {
  620. if (!is_array($this->fieldsToDisplay) || in_array($field_name, $this->fieldsToDisplay[$assoc_name]))
  621. {
  622. if ($field_name == 'id' && !isset($field['sqlId']))
  623. {
  624. $field['sqlId'] = 'id';
  625. $field['value'] = $object_assoc['id'];
  626. }
  627. elseif (!isset($field['sqlId']))
  628. {
  629. $field['sqlId'] = $field_name;
  630. $field['value'] = $object_assoc[$field_name];
  631. }
  632. $field['entities_name'] = $assoc_name;
  633. $field['entity_name'] = $resource_name;
  634. if (!is_null($this->schemaToDisplay))
  635. $field['synopsis_details'] = $this->getSynopsisDetails($field);
  636. $field['is_association'] = true;
  637. $output .= $this->setIndent($depth-1).$this->objectRender->renderField($field);
  638. }
  639. }
  640. $output .= $this->setIndent($depth-1).$this->objectRender->renderNodeFooter($resource_name, array());
  641. return $output;
  642. }
  643. public function setIndent($depth)
  644. {
  645. $string = '';
  646. $number_of_tabs = $this->depth - $depth;
  647. for ($i = 0; $i < $number_of_tabs; $i++)
  648. $string .= "\t";
  649. return $string;
  650. }
  651. public function getSynopsisDetails($field)
  652. {
  653. $arr_details = '';
  654. if (array_key_exists('required', $field) && $field['required'])
  655. $arr_details['required'] = 'true';
  656. if (array_key_exists('maxSize', $field) && $field['maxSize'])
  657. $arr_details['maxSize'] = $field['maxSize'];
  658. if (array_key_exists('validateMethod', $field) && $field['validateMethod'])
  659. $arr_details['format'] = $field['validateMethod'];
  660. return $arr_details;
  661. }
  662. /**
  663. *
  664. * @param string|object $object
  665. * @param string $method
  666. * @return $this
  667. */
  668. public function setSpecificField($object, $method, $field_name, $entity_name)
  669. {
  670. try {
  671. $this->validateObjectAndMethod($object, $method);
  672. } catch (WebserviceException $e) {
  673. throw $e;
  674. }
  675. $this->specificFields[$field_name] = array('entity'=>$entity_name, 'object' => $object, 'method' => $method, 'type' => gettype($object));
  676. return $this;
  677. }
  678. protected function validateObjectAndMethod($object, $method)
  679. {
  680. if (is_string($object) && !class_exists($object))
  681. throw new WebserviceException ('The object you want to set in '.__METHOD__.' is not allowed.', array(98, 500));
  682. if (!method_exists($object, $method))
  683. throw new WebserviceException ('The method you want to set in '.__METHOD__.' is not allowed.', array(99, 500));
  684. }
  685. public function getSpecificField()
  686. {
  687. return $this->specificFields;
  688. }
  689. protected function overrideSpecificField($entity_name, $field_name, $field, $entity_object, $ws_params)
  690. {
  691. if (array_key_exists($field_name, $this->specificFields) && $this->specificFields[$field_name]['entity'] == $entity_name)
  692. {
  693. if ($this->specificFields[$field_name]['type'] == 'string')
  694. $object = new $this->specificFields[$field_name]['object']();
  695. elseif ($this->specificFields[$field_name]['type'] == 'object')
  696. $object= $this->specificFields[$field_name]['object'];
  697. $field = $object->{$this->specificFields[$field_name]['method']}($field, $entity_object, $ws_params);
  698. }
  699. return $field;
  700. }
  701. public function setVirtualField($object, $method, $entity_name, $parameters)
  702. {
  703. try {
  704. $this->validateObjectAndMethod($object, $method);
  705. } catch (WebserviceException $e) {
  706. throw $e;
  707. }
  708. $this->virtualFields[$entity_name][] = array('parameters' => $parameters, 'object' => $object, 'method' => $method, 'type' => gettype($object));
  709. }
  710. public function getVirtualFields()
  711. {
  712. return $this->virtualFields;
  713. }
  714. public function addVirtualFields($entity_name, $entity_object)
  715. {
  716. $arr_return = array();
  717. $virtual_fields = $this->getVirtualFields();
  718. if (array_key_exists($entity_name, $virtual_fields))
  719. {
  720. foreach ($virtual_fields[$entity_name] as $function_infos)
  721. {
  722. if ($function_infos['type'] == 'string')
  723. $object = new $function_infos['object']();
  724. elseif ($function_infos['type'] == 'object')
  725. $object= $function_infos['object'];
  726. $return_fields = $object->{$function_infos['method']}($entity_object, $function_infos['parameters']);
  727. foreach ($return_fields as $field_name => $value)
  728. {
  729. if (Validate::isConfigName($field_name))
  730. $arr_return[$field_name] = $value;
  731. else
  732. throw new WebserviceException('Name for the virtual field is not allow', array(128, 400));
  733. }
  734. }
  735. }
  736. return $arr_return;
  737. }
  738. public function setFieldsToDisplay($fields)
  739. {
  740. $this->fieldsToDisplay = $fields;
  741. }
  742. }