1 : <?php
2 :
3 :
4 : if( !defined( 'ROOTPATH' ) )
5 : define( 'ROOTPATH', dirname(__FILE__).'/..' );
6 :
7 : require_once(ROOTPATH.'/api/config.php');
8 :
9 : /**
10 : TODO list:
11 :
12 : * definir de forma centralizada os caminhos e as constantes necessárias;
13 : * criar um User Agent detect e um OS server detect para customizações espeçíficas de cada browser / servidor;
14 : * criar um registrador para fallback handlers;
15 : * criar um dependency manager na configuração dos serviços, para poder gerenciar os imports corretamente
16 : * criar um login e a recuperação da sessão;
17 :
18 : */
19 :
20 : class Controller {
21 :
22 : static $cache;
23 : static $services = array();
24 : static $interceptors = array();
25 : static $config = array();
26 : static $includes = array();
27 : static $tx = array();
28 : static $isConcept = array();
29 : static $hasOne = array();
30 : static $txID = 0;
31 : static $wallet;
32 :
33 : public function __destruct()
34 : {
35 : // if( $this->service )
36 : // $this->service->close();
37 : // else
38 0 : self::closeAll();
39 0 : }
40 :
41 : public static function closeAll()
42 : {
43 0 : if( self::$services )
44 0 : foreach( self::$services as $serviceName => $service )
45 0 : if( self::$config[ $serviceName ]['type'] === 'service' )
46 0 : $service->close();
47 0 : }
48 :
49 : public static function clearAll()
50 : {
51 0 : return self::$cache->clearAll();
52 : }
53 :
54 : public static function clear( $id )
55 : {
56 0 : return self::$cache->clear( $id );
57 : }
58 :
59 : public static function check( $id )
60 : {
61 0 : return self::$cache->get( $id );
62 : }
63 :
64 : public static function store( $id, $data, $expires, $compressed )
65 : {
66 0 : return self::$cache->put( $id, $data, $expires, $compressed );
67 : }
68 :
69 : public static function find( $URI, $params = false, $criteria = false )
70 : {
71 10 : if( isset($URI['id']) && $URI['id'] )
72 10 : return self::read( $URI, $params, $criteria );
73 :
74 10 : return self::call( 'find', $URI, $params, $criteria );
75 : }
76 :
77 : public static function read( $URI, $params = false, $criteria = false )
78 : {
79 0 : if( !isset($URI['id']) || !$URI['id'] )
80 0 : return self::find( $URI, $params, $criteria );
81 :
82 0 : return self::call( 'read', $URI, $params, $criteria );
83 : }
84 :
85 : public static function deleteAll( $URI, $params = false, $criteria = false )
86 : {
87 12 : if( isset($URI['id']) && $URI['id'] )
88 12 : return self::delete( $URI, $params, $criteria );
89 :
90 12 : return self::call( 'deleteAll', $URI, $params, $criteria );
91 : }
92 :
93 : public static function delete( $URI, $params = false, $criteria = false )
94 : {
95 12 : if( !isset($URI['id']) || !$URI['id'] )
96 12 : return self::deleteAll( $URI, $params, $criteria );
97 :
98 0 : return self::call( 'delete', $URI, $params, $criteria );
99 : }
100 :
101 : public static function replace( $URI, $params, $criteria = false )
102 : {
103 0 : if( isset($URI['id']) && $URI['id'] )
104 0 : return self::update( $URI, $params, $criteria );
105 :
106 0 : return self::call( 'replace', $URI, $params, $criteria );
107 : }
108 :
109 : public static function update( $URI, $params, $criteria = false )
110 : {
111 0 : if( !isset($URI['id']) || !$URI['id'] )
112 0 : return self::replace( $URI, $params, $criteria );
113 :
114 0 : return self::call( 'update', $URI, $params, $criteria );
115 : }
116 :
117 : public static function create( $URI, $params, $criteria = false )
118 : {
119 12 : return self::call( 'create', $URI, $params, $criteria );
120 : }
121 :
122 : public static function begin( $URI, $params = false, $criteria = false )
123 : {
124 0 : return self::call( 'begin', $URI, $params, $criteria );
125 : }
126 :
127 : public static function commit( $URI, $criteria = false )
128 : {
129 0 : return self::call( 'commit', $URI, false, $criteria );
130 : }
131 :
132 : public static function rollback( $URI, $criteria = false )
133 : {
134 0 : return self::call( 'rollback', $URI, false, $criteria );
135 : }
136 :
137 : public static function format( $URI, $params, $criteria = false )
138 : {
139 0 : return self::call( 'format', $URI, $params, $criteria );
140 : }
141 :
142 : public static function parse( $URI, $data, $criteria = false )
143 : {
144 0 : return self::call( 'parse', $URI, $data, $criteria );
145 : }
146 :
147 : public static function URI( $className, $id = false, $service = false )
148 : {
149 0 : return array( 'concept' => $className,
150 0 : 'service' => $service ? $service : false,
151 0 : 'id' => $id ? $id : '' );
152 : }
153 :
154 : //TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmo nos parametros passados
155 : public static function links( $concept = false, $linkage = false )
156 : {
157 :
158 :
159 0 : if( !isset(self::$config[ $concept ]) )
160 0 : self::$config[ $concept ] = self::loadConfig( $concept );
161 :
162 0 : $links = array();
163 0 : self::$isConcept[ $concept ] = array();
164 0 : self::$hasOne[ $concept ] = array();
165 :
166 0 : if( isset(self::$config[ $concept ][ 'model.hasOne' ]) )
167 0 : foreach( self::$config[ $concept ][ 'model.hasOne' ] as $linkName => $linkTarget )
168 : {
169 0 : list( $target, $link ) = explode( '.', $linkTarget );
170 :
171 0 : if( $linkage === $linkName )
172 0 : $return = $link;
173 :
174 0 : $links[$linkName] = $target;
175 0 : self::$hasOne[ $concept ][ $linkName ] = true;
176 0 : }
177 0 : if( isset(self::$config[ $concept ][ 'model.depends' ]) )
178 0 : foreach( self::$config[ $concept ][ 'model.depends' ] as $linkName => $linkTarget )
179 : {
180 0 : list( $target, $link ) = explode( '.', $linkTarget );
181 :
182 0 : if( $linkage === $linkName )
183 0 : $return = $link;
184 :
185 0 : $links[$linkName] = $target;
186 0 : self::$hasOne[ $concept ][ $linkName ] = true;
187 0 : self::$isConcept[ $concept ][ $linkName ] = true;
188 0 : }
189 0 : if( isset(self::$config[ $concept ][ 'model.hasMany' ]) )
190 0 : foreach( self::$config[ $concept ][ 'model.hasMany' ] as $linkName => $linkTarget )
191 : {
192 0 : list( $target, $link ) = explode( '.', $linkTarget );
193 :
194 0 : if( $linkage === $linkName )
195 0 : $return = $link;
196 :
197 0 : $links[$linkName] = $target;
198 0 : }
199 :
200 0 : return( isset($return) ? $return : $links );
201 : }
202 :
203 : public static function isConcept( $concept, $linkName )
204 : {
205 0 : if( !isset( self::$isConcept[ $concept ] ) )
206 0 : self::links( $concept );
207 :
208 0 : return( isset(self::$isConcept[ $concept ][ $linkName ]) );
209 : }
210 :
211 : public static function hasOne( $concept, $linkName )
212 : {
213 0 : if( !isset( self::$hasOne[ $concept ] ) )
214 0 : self::links( $concept );
215 :
216 0 : return( isset(self::$hasOne[ $concept ][ $linkName ]) );
217 : }
218 :
219 : public static function getConcept( $concept, $moduleName = false )
220 : {
221 0 : if( isset( self::$config[ $concept ] ) )
222 0 : return( self::$config[ $concept ] );
223 :
224 0 : return( self::$config[ $concept ] = self::loadConfig( $concept, $moduleName ) );
225 : }
226 :
227 : public static function loadCache( $cacheType = 'Memory' )
228 : {
229 0 : include_once( "cache/MemoryCache.php" );
230 0 : return new MemoryCache();
231 : }
232 :
233 : //TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmo nos parametros passados
234 : public static function loadConfig( $className, $isService = false)
235 : {
236 2 : $fileName = $className.'.'.($isService ? 'srv' : 'ini');
237 :
238 2 : $config = self::$cache->get( $fileName );
239 :
240 2 : if( !$config )
241 2 : {
242 2 : $config = parse_ini_file( ROOTPATH.'/config/'.$fileName, true );
243 :
244 2 : self::$cache->put( $fileName, $config );
245 2 : }
246 :
247 2 : return( $config );
248 : }
249 :
250 : public static function import( $path, $ext = ".php" )
251 : {
252 1 : if( !isset(self::$includes[$path]) )
253 1 : {
254 1 : require_once( ROOTPATH.'/'.$path.$ext );
255 1 : self::$includes[$path] = false;
256 1 : }
257 :
258 1 : return( self::$includes[$path] );
259 : }
260 :
261 : public static function load( $path, $class = false )
262 : {
263 1 : if( $return = self::import( $path, "" ) )
264 1 : return( $return );
265 :
266 1 : if( !$class ){
267 1 : preg_match( '/^\/?.*\/([^\/]+).php$/', $path, $class );
268 1 : $class = $class[1];
269 1 : }
270 :
271 1 : $object = self::$cache->get( $class );
272 :
273 1 : if( !$object )
274 1 : {
275 1 : $object = new $class();
276 1 : self::$cache->put( $class, $object );
277 1 : }
278 :
279 1 : self::$includes[$path] = $object;
280 :
281 1 : return( $object );
282 : }
283 :
284 : public static function wallet( $serviceName )
285 : {
286 1 : if( !isset( self::$wallet ) )
287 1 : {
288 : //// Hack //// TODO: passar o init da sessão no login do expresso
289 1 : Config::init();
290 :
291 1 : if(isset($_SESSION['wallet']))
292 1 : self::$wallet = $_SESSION['wallet'];
293 : /////////////
294 1 : }
295 :
296 1 : return isset( self::$wallet[ $serviceName ] )? self::$wallet[ $serviceName ] : false;
297 : }
298 :
299 : public static function connect( $service, $config )
300 : {
301 1 : $result = $service->open( $config );
302 :
303 1 : if( is_string( $result ) )
304 1 : throw new Exception( $result );
305 :
306 1 : return( true );
307 : }
308 :
309 : public static function configure( $config, $newConfig )
310 : {
311 1 : foreach( $newConfig as $key => $value )
312 1 : $config[$key] = $value;
313 :
314 1 : return( $config );
315 : }
316 :
317 : public static function dispatch( $dispatcher, $data, $optionsMap = false )
318 : {
319 : // if( $mappedTo )
320 : // $data = array( $mappedTo => $data );
321 : //
322 : // foreach( $data as $method => $params )
323 : // {
324 : // // foreach( $data[ $method ] as $name => $value )
325 : // }
326 : //
327 : // self::import( "$dispatcher.php" );
328 0 : }
329 :
330 : //TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmo nos parametros passados
331 : public static function service( $serviceName, $concept = false )
332 : {
333 12 : if( isset( self::$services[ $serviceName ] ) )
334 12 : return self::$services[ $serviceName ];
335 :
336 1 : if( !isset(self::$config[ $serviceName ]) )
337 1 : self::$config[ $serviceName ] = self::loadConfig( $serviceName, true );
338 :
339 1 : if( !isset(self::$config[ $serviceName ]) )
340 1 : return( false );
341 :
342 1 : if( !isset(self::$config[ $serviceName ]['type']) )
343 1 : self::$config[ $serviceName ]['type'] = 'service';
344 :
345 1 : self::import( 'api/'.self::$config[ $serviceName ]['type'] ); //TODO: Item 4
346 :
347 1 : $service = self::load( self::$config[ $serviceName ]['path'],
348 1 : self::$config[ $serviceName ]['class'] );
349 :
350 1 : $srvConfig = array();
351 :
352 1 : if( isset(self::$config[ $serviceName ][ 'config' ]) )
353 1 : $srvConfig = self::configure( $srvConfig, self::$config[ $serviceName ][ 'config' ] );
354 1 : if( $wallet = self::wallet( $serviceName ) )
355 1 : $srvConfig = self::configure( $srvConfig, $wallet );
356 1 : if( $concept && isset(self::$config[ $concept ]['service.config']) )
357 1 : $srvConfig = self::configure( $srvConfig, self::$config[ $concept ]['service.config'] );
358 :
359 1 : if( empty( $srvConfig ) )
360 1 : $srvConfig = false;
361 :
362 1 : if( $service && self::$config[ $serviceName ]['type'] === 'service' )
363 1 : self::connect( $service, $srvConfig );
364 :
365 1 : return( self::$services[ $serviceName ] = $service );
366 : }
367 :
368 : //TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmo nos parametros passados
369 : public static function interceptor( $method, $concept = false, $serviceName = false, $isService = false )
370 : {
371 12 : if( $concept && !isset(self::$config[ $concept ]) )
372 12 : self::$config[ $concept ] = self::loadConfig( $concept );
373 :
374 12 : if( !$concept ) $concept = 'global';
375 12 : if( !$isService || !$serviceName ) $serviceName = 'global';
376 :
377 12 : if( !isset( self::$interceptors[ $concept ] ) )
378 12 : self::$interceptors[ $concept ] = array();
379 :
380 12 : if( !isset( self::$interceptors[ $concept ][ $serviceName ] ) )
381 12 : self::$interceptors[ $concept ][ $serviceName ] = array();
382 :
383 12 : if( !isset( self::$interceptors[ $concept ][ $serviceName ][ $method ] ) )
384 12 : {
385 4 : $events = array( 'before', 'after' );
386 4 : $interceptors = array();
387 :
388 4 : $prefix = ( $isService )? "$serviceName." : "";
389 :
390 4 : foreach( $events as $i => $event )
391 : {
392 4 : $interceptors[$event] = array();
393 :
394 4 : if( !isset(self::$config[$concept]["$prefix$event.$method"]) )
395 4 : continue;
396 :
397 1 : foreach( self::$config[$concept]["$prefix$event.$method"] as $intercept => $interceptor )
398 1 : $interceptors[$event][$intercept] = self::load( $interceptor );
399 4 : }
400 :
401 4 : self::$interceptors[ $concept ][ $serviceName ][ $method ] = $interceptors;
402 4 : }
403 :
404 12 : return( self::$interceptors[ $concept ][ $serviceName ][ $method ] );
405 : }
406 :
407 : public static function interceptorCommit( $eventType, $commitList, $isService = false )
408 : {
409 12 : $result = array( $eventType => array() );
410 :
411 12 : if( is_array( $commitList ) )
412 12 : foreach( $commitList as $i => $tx )
413 : {
414 12 : $interceptors = self::interceptor( 'commit', $tx['concept'], $tx['service'], $isService );
415 :
416 12 : $result[$eventType] = array_merge( $result[$eventType], $interceptors[$eventType] );
417 12 : }
418 :
419 12 : return( $result );
420 : }
421 :
422 : public static function fire( $eventType, $method, &$params, $original, $isService = false )
423 : {
424 12 : if( $method === 'commit' )
425 12 : $interceptors = self::interceptorCommit( $eventType, $params['criteria'], $isService );
426 :
427 : else
428 12 : $interceptors = self::interceptor( $method,
429 12 : isset($original['URI']['concept']) ? $original['URI']['concept'] : false,
430 12 : isset($params['URI']['service']) ? $params['URI']['service'] : false, $isService );
431 :
432 12 : if( $interceptors && isset($interceptors[ $eventType ]) )
433 12 : foreach( $interceptors[ $eventType ] as $intercept => $interceptor )
434 : {
435 2 : $return = $interceptor->$intercept( $params['URI'], $params['properties'], $params['criteria'], $original /*, $params['service'] */);
436 :
437 2 : if( $return === false )
438 2 : return( false );
439 :
440 2 : if( isset($return) )
441 2 : $params['properties'] = $return;
442 12 : }
443 :
444 12 : return( $params );
445 : }
446 :
447 : /*
448 : * ex: array
449 : * (
450 : * [0] array( 'OR', array( array( '=', 'campo', 'valor' ),
451 : array( 'OR', array( array( '=', 'campo', 'valor' ) ) ) )
452 : * [1] array( '=', 'campo' , 'valor' )
453 : * [2] array( 'OR' , array( array( '=' , campo', 'valor' ) ) )
454 : * [3] array( 'IN', 'campo', array( '1' , '2' , '3' ) )
455 : * )
456 : * OR
457 : * array( '=' , 'campo' , 'valor' )
458 : */
459 :
460 : //TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmo nos parametros passados
461 : public static function serviceName( $URI, $original = false )
462 : {
463 12 : $concept = "";
464 :
465 12 : if( $original && isset($original['concept']) && $original['concept'] )
466 12 : $concept = $original['concept'];
467 0 : elseif( isset($URI['concept']) && $URI['concept'] )
468 0 : $concept = $URI['concept'];
469 :
470 12 : if( ( !isset($URI['service']) || !$URI['service'] ) && $concept )
471 12 : {
472 12 : if( !isset(self::$config[ $concept ]) )
473 12 : self::$config[ $concept ] = self::loadConfig( $concept );
474 :
475 12 : $URI['service'] = self::$config[ $concept ][ 'service' ];
476 12 : }
477 :
478 12 : if( !isset($URI['service']) )
479 12 : throw new Exception( "CONFIGURATION ERROR: service name from concept '$concept' not found" );
480 :
481 12 : return( $URI );
482 : }
483 :
484 : //TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmos nas options passadas
485 : public static function call( $method, $URI, $properties = false, $options = false, $service = false )
486 : {
487 : try
488 : {
489 12 : if( !isset($URI['concept']) ) $URI['concept'] = false;
490 :
491 12 : $original = $params = array( 'properties' => $properties,
492 12 : 'criteria' => $options,
493 12 : 'URI' => $URI,
494 12 : 'service' => $service );
495 :
496 12 : if( isset($params['URI']['concept']) && !self::fire( 'before', $method, $params, $original ) )
497 12 : return( empty($params['properties']) ? false : $params['properties'] );
498 :
499 :
500 :
501 12 : if( $params && !$params['service'] )
502 12 : {
503 12 : $params['URI'] = self::serviceName( $params['URI'], $original['URI'] );
504 :
505 12 : $params['service'] = self::service( $params['URI']['service'], $params['URI']['concept'] );
506 12 : }
507 :
508 12 : if( isset($params['URI']['service']) )
509 12 : {
510 12 : if( $method === 'create' || $method === 'update' || $method === 'delete' )
511 12 : {
512 12 : if( $commit = !isset(self::$tx[ $params['URI']['service'] ]) )
513 12 : {
514 12 : self::call( 'begin', $params['URI'] );
515 12 : }
516 :
517 12 : $TX = array();
518 12 : }
519 :
520 12 : if( !self::fire( 'before', $method, $params, $original, true ) )
521 12 : return( empty($params['properties']) ? false : $params['properties'] );
522 12 : }
523 :
524 12 : if( $params['service'] )
525 12 : switch( $method )
526 : {
527 12 : case 'find': $return = $params['service']->find( $params['URI'], $params['properties'], $params['criteria'] ); break;
528 :
529 12 : case 'read': $return = $params['service']->read( $params['URI'], $params['properties'] , $params['criteria'] ); break;
530 :
531 12 : case 'create': $return = $params['service']->create( $params['URI'], $params['properties']/*, $criteria*/ ); break;
532 :
533 12 : case 'delete': $return = $params['service']->delete( $params['URI'], $params['properties']/*, $criteria*/ ); break;
534 :
535 12 : case 'deleteAll': $return = $params['service']->deleteAll( $params['URI'], $params['properties'], $params['criteria'] ); break;
536 :
537 12 : case 'update': $return = $params['service']->update( $params['URI'], $params['properties']/*, $criteria*/ ); break;
538 :
539 12 : case 'replace': $return = $params['service']->replace( $params['URI'], $params['properties'], $params['criteria'] ); break;
540 :
541 12 : case 'begin': $return = $params['service']->begin( $params['URI'] ); break;
542 :
543 12 : case 'commit': $return = $params['service']->commit( $params['URI'], $params['criteria'] ); break;
544 :
545 0 : case 'rollback': $return = $params['service']->rollback( $params['URI'], $params['criteria'] ); break;
546 :
547 0 : case 'parse': $return = $params['service']->parse( $params['properties'], $params['criteria'] ); break;
548 :
549 0 : case 'analize': $return = $params['service']->analize( $params['properties'], $params['criteria'] ); break;
550 :
551 0 : case 'format': $return = $params['service']->format( $params['properties'], $params['criteria'] ); break;
552 :
553 0 : default : $return = $params['service']->$method( $params['properties'], $params['criteria'] );
554 12 : }
555 :
556 12 : if( isset($return) && $return !== false )
557 12 : $params['properties'] = $return;
558 :
559 12 : if( isset($params['URI']['service']) )
560 12 : if( !self::fire( 'after', $method, $params, $original, true ) )
561 12 : return( empty($params['properties']) ? false : $params['properties'] );
562 :
563 12 : if( isset($URI['concept']) )
564 12 : self::fire( 'after', $method, $params, $original );
565 :
566 12 : if( empty($params['properties']) )
567 12 : $params['properties'] = false;
568 :
569 12 : if( isset( $TX ) )
570 12 : {
571 12 : $TX['rollback'] = !!!$params['properties'];
572 :
573 12 : if( $params['properties'] && is_array($params['properties']) && isset($params['properties']['id']) )
574 12 : $TX['id'] = $params['properties']['id'];
575 :
576 12 : self::$tx[ $params['URI']['service'] ][] = array_merge( $TX, $original['URI'], array( 'service' => $params['URI']['service'], 'method' => $method ) );
577 :
578 12 : if( isset($commit) && $commit )
579 12 : {
580 12 : if( !self::call( 'commit', $params['URI'], false, self::$tx[ $params['URI']['service'] ] ) )
581 12 : self::call( 'rollback', $params['URI'] , false, self::$tx[ $params['URI']['service'] ] );
582 :
583 12 : unset( self::$tx[ $params['URI']['service'] ] );
584 12 : }
585 12 : }
586 : }
587 12 : catch( Exception $e )
588 : {
589 0 : if( !self::fallback( $e ) )
590 0 : self::closeAll();
591 :
592 0 : return( false );
593 : }
594 :
595 12 : return( $params['properties'] );
596 : }
597 :
598 : public static function fallback( $exception )
599 : {
600 0 : error_log( $exception->getMessage() );
601 0 : return( true );
602 : }
603 :
604 : public static function put( $URI, $data, $txIds = false )
605 : {
606 : try
607 : {
608 0 : $URI = self::serviceName( $URI );
609 :
610 0 : if( $commit = !$txIds )
611 0 : $txIds = array();
612 :
613 0 : if( !isset( self::$tx[ $URI['service'] ] ) )
614 0 : {
615 0 : self::call( 'begin', $URI );
616 0 : self::$tx[ $txIds[] = $URI['service'] ] = array();
617 0 : }
618 :
619 0 : $method = $data ? isset( $data['id'] ) ?
620 0 : 'update' : 'create' : 'delete';
621 :
622 0 : $links = self::links( $URI['concept'] );
623 :
624 0 : $order = self::$txID++;
625 :
626 0 : $postpone = array();
627 0 : $linkNames = array();
628 :
629 : if( $data )
630 0 : {
631 0 : $URI['id'] = isset( $data['id'] ) ? $data['id'] : false;
632 :
633 0 : foreach( $links as $linkName => $linkTarget )
634 : {
635 0 : if( isset( $data[$linkName] ) && is_array( $data[$linkName] ) )
636 0 : {
637 0 : if( self::isConcept( $URI['concept'], $linkName ) )
638 0 : $data[$linkName] = self::put( array( 'concept' => $linkTarget ), $data[$linkName], &$txIds );
639 : else
640 : {
641 0 : $postpone[ $linkTarget ] = $data[$linkName];
642 0 : $linkNames[ $linkTarget ] = $linkName;
643 : }
644 0 : }
645 0 : }
646 0 : }
647 : else
648 0 : $URI['id'] = isset( $data['id'] ) ? $data['id'] : $URI['id'];
649 :
650 0 : $result = Controller::call( $method, $URI, $data, false, false, true );
651 :
652 0 : if( is_array( $result ) && isset( $result['id'] ) )
653 0 : $URI['id'] = $result['id'];
654 :
655 0 : self::$tx[ $URI['service'] ][ count(self::$tx[ $URI['service'] ]) - 1 ]['order'] = $order;
656 0 : self::$tx[ $URI['service'] ][ count(self::$tx[ $URI['service'] ]) - 1 ]['id'] = $URI['id'];
657 :
658 0 : foreach( $postpone as $linkTarget => $dt )
659 : {
660 0 : if( Controller::hasOne( $URI['concept'], $linkNames[ $linkTarget ] ) )
661 0 : $dt = array( $dt );
662 :
663 0 : foreach( $dt as $ii => $value )
664 : {
665 0 : if( !is_array( $value ) )
666 0 : $value = array( 'id' => $value );
667 :
668 0 : $value[ self::links( $URI['concept'], $linkNames[ $linkTarget ] ) ] = $URI['id'];
669 :
670 0 : self::put( array( 'concept' => $linkTarget ), $value, &$txIds );
671 0 : }
672 0 : }
673 : if( $commit )
674 0 : {
675 0 : $result = array();
676 :
677 0 : for( $i = count( $txIds ) - 1; $i >= 0; $i-- )
678 : {
679 0 : $currentTx = self::$tx[ $txIds[$i] ];
680 0 : unset( self::$tx[ $txIds[$i] ] );
681 :
682 0 : if( !self::commit( array( 'service' => $txIds[$i] ), $currentTx ) )
683 0 : {
684 0 : self::rollback( array( 'service' => $txIds[$i] ), $currentTx );
685 :
686 0 : foreach( $currentTx as $i => $st )
687 0 : $currentTx[$i][ 'rollback' ] = true;
688 0 : }
689 :
690 0 : $result = array_merge( $result, $currentTx );
691 0 : }
692 :
693 0 : self::$txID = 0;
694 :
695 0 : return( $result );
696 : }
697 :
698 : }
699 0 : catch( Exception $e )
700 : {
701 0 : if( !self::fallback( $e ) )
702 0 : self::closeAll();
703 :
704 0 : return( false );
705 : }
706 :
707 0 : return( $URI['id'] );
708 : }
709 :
710 : public static function get()
711 : {
712 :
713 0 : }
714 : }
715 :
716 : Controller::$cache = Controller::loadCache();
717 : // ?>
|