BridgeAbstract.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <?php
  2. require_once(__DIR__ . '/BridgeInterface.php');
  3. abstract class BridgeAbstract implements BridgeInterface {
  4. const NAME = 'Unnamed bridge';
  5. const URI = '';
  6. const DESCRIPTION = 'No description provided';
  7. const MAINTAINER = 'No maintainer';
  8. const CACHE_TIMEOUT = 3600;
  9. const PARAMETERS = array();
  10. protected $cache;
  11. protected $extraInfos;
  12. protected $items = array();
  13. protected $inputs = array();
  14. protected $queriedContext = '';
  15. protected $cacheTimeout;
  16. /**
  17. * Return cachable datas (extrainfos and items) stored in the bridge
  18. * @return mixed
  19. */
  20. public function getCachable(){
  21. return array(
  22. 'items' => $this->getItems(),
  23. 'extraInfos' => $this->getExtraInfos()
  24. );
  25. }
  26. /**
  27. * Return items stored in the bridge
  28. * @return mixed
  29. */
  30. public function getItems(){
  31. return $this->items;
  32. }
  33. /**
  34. * Sets the input values for a given context. Existing values are
  35. * overwritten.
  36. *
  37. * @param array $inputs Associative array of inputs
  38. * @param string $context The context name
  39. */
  40. protected function setInputs(array $inputs, $queriedContext){
  41. // Import and assign all inputs to their context
  42. foreach($inputs as $name => $value) {
  43. foreach(static::PARAMETERS as $context => $set) {
  44. if(array_key_exists($name, static::PARAMETERS[$context])) {
  45. $this->inputs[$context][$name]['value'] = $value;
  46. }
  47. }
  48. }
  49. // Apply default values to missing data
  50. $contexts = array($queriedContext);
  51. if(array_key_exists('global', static::PARAMETERS)) {
  52. $contexts[] = 'global';
  53. }
  54. foreach($contexts as $context) {
  55. foreach(static::PARAMETERS[$context] as $name => $properties) {
  56. if(isset($this->inputs[$context][$name]['value'])) {
  57. continue;
  58. }
  59. $type = isset($properties['type']) ? $properties['type'] : 'text';
  60. switch($type) {
  61. case 'checkbox':
  62. if(!isset($properties['defaultValue'])) {
  63. $this->inputs[$context][$name]['value'] = false;
  64. } else {
  65. $this->inputs[$context][$name]['value'] = $properties['defaultValue'];
  66. }
  67. break;
  68. case 'list':
  69. if(!isset($properties['defaultValue'])) {
  70. $firstItem = reset($properties['values']);
  71. if(is_array($firstItem)) {
  72. $firstItem = reset($firstItem);
  73. }
  74. $this->inputs[$context][$name]['value'] = $firstItem;
  75. } else {
  76. $this->inputs[$context][$name]['value'] = $properties['defaultValue'];
  77. }
  78. break;
  79. default:
  80. if(isset($properties['defaultValue'])) {
  81. $this->inputs[$context][$name]['value'] = $properties['defaultValue'];
  82. }
  83. break;
  84. }
  85. }
  86. }
  87. // Copy global parameter values to the guessed context
  88. if(array_key_exists('global', static::PARAMETERS)) {
  89. foreach(static::PARAMETERS['global'] as $name => $properties) {
  90. if(isset($inputs[$name])) {
  91. $value = $inputs[$name];
  92. } elseif(isset($properties['value'])) {
  93. $value = $properties['value'];
  94. } else {
  95. continue;
  96. }
  97. $this->inputs[$queriedContext][$name]['value'] = $value;
  98. }
  99. }
  100. // Only keep guessed context parameters values
  101. if(isset($this->inputs[$queriedContext])) {
  102. $this->inputs = array($queriedContext => $this->inputs[$queriedContext]);
  103. } else {
  104. $this->inputs = array();
  105. }
  106. }
  107. /**
  108. * Returns the name of the context matching the provided inputs
  109. *
  110. * @param array $inputs Associative array of inputs
  111. * @return mixed Returns the context name or null if no match was found
  112. */
  113. protected function getQueriedContext(array $inputs){
  114. $queriedContexts = array();
  115. // Detect matching context
  116. foreach(static::PARAMETERS as $context => $set) {
  117. $queriedContexts[$context] = null;
  118. // Check if all parameters of the context are satisfied
  119. foreach($set as $id => $properties) {
  120. if(isset($inputs[$id]) && !empty($inputs[$id])) {
  121. $queriedContexts[$context] = true;
  122. } elseif(isset($properties['required'])
  123. && $properties['required'] === true) {
  124. $queriedContexts[$context] = false;
  125. break;
  126. }
  127. }
  128. }
  129. // Abort if one of the globally required parameters is not satisfied
  130. if(array_key_exists('global', static::PARAMETERS)
  131. && $queriedContexts['global'] === false) {
  132. return null;
  133. }
  134. unset($queriedContexts['global']);
  135. switch(array_sum($queriedContexts)) {
  136. case 0: // Found no match, is there a context without parameters?
  137. foreach($queriedContexts as $context => $queried) {
  138. if(is_null($queried)) {
  139. return $context;
  140. }
  141. }
  142. return null;
  143. case 1: // Found unique match
  144. return array_search(true, $queriedContexts);
  145. default: return false;
  146. }
  147. }
  148. /**
  149. * Defined datas with parameters depending choose bridge
  150. * Note : you can define a cache with "setCache"
  151. * @param array array with expected bridge paramters
  152. */
  153. public function setDatas(array $inputs){
  154. if(!is_null($this->cache)) {
  155. $time = $this->cache->getTime();
  156. if($time !== false
  157. && (time() - $this->getCacheTimeout() < $time)
  158. && (!defined('DEBUG') || DEBUG !== true)) {
  159. $cached = $this->cache->loadData();
  160. if(isset($cached['items']) && isset($cached['extraInfos'])) {
  161. $this->items = $cached['items'];
  162. $this->extraInfos = $cached['extraInfos'];
  163. return;
  164. }
  165. }
  166. }
  167. if(empty(static::PARAMETERS)) {
  168. if(!empty($inputs)) {
  169. returnClientError('Invalid parameters value(s)');
  170. }
  171. $this->collectData();
  172. if(!is_null($this->cache)) {
  173. $this->cache->saveData($this->getCachable());
  174. }
  175. return;
  176. }
  177. if(!validateData($inputs, static::PARAMETERS)) {
  178. returnClientError('Invalid parameters value(s)');
  179. }
  180. // Guess the paramter context from input data
  181. $this->queriedContext = $this->getQueriedContext($inputs);
  182. if(is_null($this->queriedContext)) {
  183. returnClientError('Required parameter(s) missing');
  184. } elseif($this->queriedContext === false) {
  185. returnClientError('Mixed context parameters');
  186. }
  187. $this->setInputs($inputs, $this->queriedContext);
  188. $this->collectData();
  189. if(!is_null($this->cache)) {
  190. $this->cache->saveData($this->getCachable());
  191. }
  192. }
  193. /**
  194. * Returns the value for the provided input
  195. *
  196. * @param string $input The input name
  197. * @return mixed Returns the input value or null if the input is not defined
  198. */
  199. protected function getInput($input){
  200. if(!isset($this->inputs[$this->queriedContext][$input]['value'])) {
  201. return null;
  202. }
  203. return $this->inputs[$this->queriedContext][$input]['value'];
  204. }
  205. public function getDescription(){
  206. return static::DESCRIPTION;
  207. }
  208. public function getMaintainer(){
  209. return static::MAINTAINER;
  210. }
  211. public function getName(){
  212. // Return cached name when bridge is using cached data
  213. if(isset($this->extraInfos)) {
  214. return $this->extraInfos['name'];
  215. }
  216. return static::NAME;
  217. }
  218. public function getParameters(){
  219. return static::PARAMETERS;
  220. }
  221. public function getURI(){
  222. // Return cached uri when bridge is using cached data
  223. if(isset($this->extraInfos)) {
  224. return $this->extraInfos['uri'];
  225. }
  226. return static::URI;
  227. }
  228. public function getExtraInfos(){
  229. return array(
  230. 'name' => $this->getName(),
  231. 'uri' => $this->getURI()
  232. );
  233. }
  234. public function setCache(\CacheInterface $cache){
  235. $this->cache = $cache;
  236. }
  237. public function setCacheTimeout($timeout){
  238. if(is_numeric($timeout) && ($timeout < 1 || $timeout > 86400)) {
  239. $this->cacheTimeout = static::CACHE_TIMEOUT;
  240. return;
  241. }
  242. $this->cacheTimeout = $timeout;
  243. }
  244. public function getCacheTimeout(){
  245. return isset($this->cacheTimeout) ? $this->cacheTimeout : static::CACHE_TIMEOUT;
  246. }
  247. }