├── .gitignore ├── .travis.yml ├── README.md ├── composer.json ├── phpunit.xml ├── public └── .gitkeep ├── src ├── Bulforce │ └── ExtDirect │ │ ├── ExtDirect.php │ │ ├── ExtDirectServiceProvider.php │ │ └── Facades │ │ └── ExtDirect.php ├── config │ ├── .gitkeep │ └── config.php ├── controllers │ └── .gitkeep ├── lang │ └── .gitkeep ├── migrations │ └── .gitkeep └── views │ └── .gitkeep └── tests └── .gitkeep /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | .idea 3 | composer.phar 4 | composer.lock 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | - 5.6 8 | - hhvm 9 | 10 | before_script: 11 | - composer self-update 12 | - composer install --prefer-source --no-interaction --dev 13 | 14 | script: phpunit 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##Info 2 | This is ext-direct provider for laravel 5 and ExtJS 4 (works with extjs 5 as well) 3 | 4 | Looking for the laravel 4 package, check the laravel4 branch. 5 | 6 | The idea behind ext-direct is to allow javascript to call remote php methods as they were client side javascript methods. This is reducing dramatically the development time. 7 | 8 | Heavily(almost 99%) based on http://www.sencha.com/forum/showthread.php?102357-Extremely-Easy-Ext.Direct-integration-with-PHP 9 | 10 | The original class was touched just a little bit. 11 | 12 | 13 | ##Installation## 14 | 15 | Add this line to the composer.json require list and run composer update 16 | 17 | ``` 18 | "bulforce/ext-direct": "dev-master" 19 | ``` 20 | 21 | 22 | Add to app.php 'providers' array: 23 | 24 | ``` 25 | 'Bulforce\ExtDirect\ExtDirectServiceProvider', 26 | ``` 27 | 28 | This package comes with a Facade but you dont have to include it in your app.php it is automatically included. 29 | 30 | You **MUST** publish or create this config file: 31 | 32 | ``` 33 | ../laravel_project/app/config/packages/bulforce/ext-direct/config.php 34 | ``` 35 | You **MUST** edit the config.php file: 36 | ``` 37 | 'Ext.rpc', 41 | 'descriptor' => 'Ext.rpc.REMOTING_API', 42 | 'timeout' => 30, 43 | 'debug' => true, 44 | 'api_classes' => array( 45 | 'Items' => 'ItemsController' 46 | ) 47 | ); 48 | ``` 49 | Most important part is the **api_classes** array, there you have to list all the classes(normally controllers) from your application that you want to make availabe to extjs to call directly. 50 | 51 | **Note** that it doesnt have to be associative array, you can simply list the class name in a normal indexed array. However if you list them as associative array then you can call them from extjs using the array element ``key`` instead of the actuall controller class name. This way you can hide your real application structure from the front end. 52 | 53 | **TAG Direct methods** 54 | In order for a controller method to be made available to extjs/sencha to call directly **two** conditions must be met: 55 | 56 | 1. Method needs to be declared as **public** 57 | 2. Method needs to contain comment tag @direct 58 | 59 | example: 60 | ```php 61 | /** 62 | * @direct 63 | */ 64 | public function read($params = null) { 65 | return Item::take(50)->get(); 66 | } 67 | ``` 68 | 69 | 70 | add a route in your routes.php 71 | ```php 72 | Route::any('/rpc', function() { 73 | return ExtDirect::provide(); 74 | }); 75 | ``` 76 | 77 | Lastly add something like this in your index.html (after extjs library and before your application code!!!) 78 | ```html 79 | 80 | ``` 81 | 82 | Now you should be able to call laravel controller methods from javascript directly 83 | ```javascript 84 | Ext.rpc.Items.read(function(response) { 85 | console.log(response); 86 | }); 87 | 88 | //with params, params will be passed to the controller method as php object 89 | Ext.rpc.Items.read({page: 5},function(response) { 90 | console.log(response); 91 | }); 92 | 93 | //use it in direct stores api object 94 | api: { 95 | read: Ext.rpc.Items.read 96 | } 97 | ``` 98 | 99 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bulforce/ext-direct", 3 | "description": "Laravel ExtJS/Sencha direct provider", 4 | "keywords": ["extjs", "extdirect", "laravel"], 5 | "authors": [ 6 | { 7 | "name": "bulforce", 8 | "email": "bulforce@gmail.com" 9 | } 10 | ], 11 | "require": { 12 | "php": ">=5.4.0", 13 | "illuminate/support": "~5.2" 14 | }, 15 | "autoload": { 16 | "classmap": [ 17 | "src/migrations", 18 | "src/Bulforce/ExtDirect/Facades", 19 | "src" 20 | ], 21 | "psr-0": { 22 | "Bulforce\\ExtDirect\\": "src/Bulforce/ExtDirect/" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests/ 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bulforce/laravel-ext-direct/98681584324436371f91347e63fae32f107e7fdd/public/.gitkeep -------------------------------------------------------------------------------- /src/Bulforce/ExtDirect/ExtDirect.php: -------------------------------------------------------------------------------- 1 | array( 'param1', 'param2' ) ) 108 | */ 109 | static public $constructor_params = array(); 110 | 111 | /** 112 | * @return string Array containing the full API declaration 113 | */ 114 | static public function get_api_array() 115 | { 116 | $api_array = array( 117 | 'id' => self::$id, 118 | 'url' => ( empty( self::$url ) ? $_SERVER['PHP_SELF'] : self::$url ), 119 | 'type' => 'remoting', 120 | 'timeout' => self::$timeout, 121 | 'namespace' => self::$namespace, 122 | 'descriptor' => self::$descriptor 123 | ); 124 | 125 | if ( empty( $api_array['id'] ) ) 126 | unset( $api_array['id'] ); 127 | 128 | $actions = array(); 129 | 130 | foreach( self::$api_classes as $api_name => $class ) 131 | { 132 | $methods = array(); 133 | $reflection = new \ReflectionClass( $class ); 134 | 135 | foreach( $reflection->getMethods() as $method ) 136 | { 137 | $docComment = $method->getDocComment(); 138 | 139 | $direct = strpos($docComment, "@direct"); 140 | 141 | // Only public and @direct methods will be declared 142 | if ( !$method->isPublic() || !$direct ) 143 | continue; 144 | 145 | // Don't declare constructor, destructor or abstract methods 146 | if ( $method->isConstructor() || $method->isDestructor() || $method->isAbstract() ) 147 | continue; 148 | 149 | // Only declare static methods according to "include_static_methods" configuration 150 | if ( !self::$include_static_methods && $method->isStatic() ) 151 | continue; 152 | 153 | // Do not declare inherited methods, according to "include_inherited_methods" configuration 154 | if ( !self::$include_inherited_methods && ( $method->getDeclaringClass()->name != $class ) ) 155 | continue; 156 | 157 | // If "declare_method_function" is set, we test if the method can be declared, according to its return result 158 | if ( !empty( self::$declare_method_function ) && !call_user_func( self::$declare_method_function, $class, $method->getName() ) ) 159 | continue; 160 | 161 | // Count only required parameters or count them all, according to "count_only_required_params" configuration 162 | if ( self::$count_only_required_params ) 163 | $api_method = array( 'name' => $method->getName(), 'len' => $method->getNumberOfRequiredParameters() ); 164 | else 165 | $api_method = array( 'name' => $method->getName(), 'len' => $method->getNumberOfParameters() ); 166 | 167 | // Check if method should be marked as "formHandler" 168 | if ( in_array( $class . '::' . $method->getName(), self::$form_handlers ) || ( strpos( $method->getDocComment(), '@formHandler' ) !== false ) ) 169 | $api_method['formHandler'] = true; 170 | 171 | $methods[] = $api_method; 172 | } 173 | 174 | // if (!!preg_match('/@directname ([\w]+)/', $reflection->getDocComment(), $matches)) { 175 | // $class = $matches[1]; 176 | // } 177 | 178 | if(!is_int($api_name)) { 179 | $class = $api_name; 180 | } 181 | 182 | $actions[$class] = $methods; 183 | } 184 | 185 | $api_array['actions'] = $actions; 186 | 187 | return $api_array; 188 | } 189 | 190 | /** 191 | * @return string JSON encoded array containing the full API declaration 192 | */ 193 | static public function get_api_json() 194 | { 195 | return json_encode( self::get_api_array() ); 196 | } 197 | 198 | /** 199 | * @return string JavaScript code containing the full API declaration 200 | */ 201 | static public function get_api_javascript() 202 | { 203 | $template = << self::get_api_json(), 216 | '[%namespace%]' => ExtDirect::$namespace, 217 | '[%descriptor%]' => ExtDirect::$descriptor 218 | ); 219 | 220 | return strtr( $template, $elements ); 221 | } 222 | 223 | /** 224 | * Provide access via Ext.Direct to the specified class or classes 225 | * This method does one of the following two things, depending on the HTTP request. 226 | * 1) Outputs the API declaration in the chosen format (JSON or JavaScript) 227 | * 2) Process the action(s) and return its result(s) (JSON) 228 | * @param string | array $api_classes Class name(s) to publish in the API declaration 229 | */ 230 | static public function provide( $api_classes = null ) 231 | { 232 | self::config(\Config::get('ext-direct')); 233 | 234 | $c = new ExtDirectController($api_classes, false); 235 | $c->run(); 236 | $response = $c->getResponseContents(); 237 | return $response; 238 | } 239 | 240 | static public function config($settings = array()) 241 | { 242 | foreach($settings as $option => $value) { 243 | if(property_exists(get_class(), $option)) { 244 | self::$$option = $value; 245 | } 246 | } 247 | } 248 | } 249 | 250 | /** 251 | * Process Ext.Direct HTTP requests 252 | * 253 | * @author J. Bruni 254 | */ 255 | class ExtDirectRequest 256 | { 257 | /** 258 | * @var array Actions to be executed in this request 259 | */ 260 | public $actions = array(); 261 | 262 | /** 263 | * @var boolean True if there is a file upload; false otherwise 264 | */ 265 | public $upload = false; 266 | 267 | /** 268 | * Call the correct actions processing method according to $_POST['extAction'] availability 269 | */ 270 | public function __construct() 271 | { 272 | if ( isset( $_POST['extAction'] ) ) 273 | $this->get_form_action(); 274 | else 275 | $this->get_request_actions(); 276 | } 277 | 278 | /** 279 | * Instantiate actions to be executed in this request using "extAction" (form) 280 | */ 281 | protected function get_form_action() 282 | { 283 | $extParameters = $_POST; 284 | 285 | foreach( array( 'extAction', 'extMethod', 'extTID', 'extUpload', 'extType' ) as $variable ) 286 | { 287 | if ( !isset( $extParameters[$variable] ) ) 288 | $$variable = ''; 289 | else 290 | { 291 | $$variable = $extParameters[$variable]; 292 | unset( $extParameters[$variable] ); 293 | } 294 | } 295 | 296 | if ( $extType == 'rpc' ) 297 | { 298 | $this->actions[] = new ExtDirectAction( $extAction, $extMethod, $extParameters, $extTID, ( $extUpload == 'true' ), true ); 299 | $this->upload = ( $extUpload == 'true' ); 300 | } 301 | } 302 | 303 | /** 304 | * Instantiate actions to be executed in this request (without "extAction") 305 | */ 306 | protected function get_request_actions() 307 | { 308 | $input = file_get_contents( 'php://input' ); 309 | 310 | $request = json_decode( $input ); 311 | 312 | if ( !is_array( $request ) ) 313 | $request = array( $request ); 314 | 315 | foreach( $request as $rpc ) 316 | { 317 | foreach( array( 'type', 'action', 'method', 'data', 'tid' ) as $variable ) 318 | $$variable = ( isset( $rpc->$variable ) ? $rpc->$variable : '' ); 319 | 320 | if ( $type == 'rpc' ) 321 | $this->actions[] = new ExtDirectAction( $action, $method, $data, $tid, false, false ); 322 | } 323 | } 324 | } 325 | 326 | /** 327 | * Store HTTP response contents for output 328 | * 329 | * @author J. Bruni 330 | */ 331 | class ExtDirectResponse 332 | { 333 | /** 334 | * @var array HTTP headers to be sent in the response 335 | */ 336 | public $headers = array(); 337 | 338 | /** 339 | * @var contents HTTP body to be sent in the response 340 | */ 341 | public $contents = ''; 342 | } 343 | 344 | /** 345 | * Call a Ext.Direct API class method and format the results 346 | * 347 | * @author J. Bruni 348 | */ 349 | class ExtDirectAction 350 | { 351 | /** 352 | * @var string API class name 353 | */ 354 | public $action; 355 | 356 | /** 357 | * @var string Method name 358 | */ 359 | public $method; 360 | 361 | /** 362 | * @var array Method parameters 363 | */ 364 | public $parameters; 365 | 366 | /** 367 | * @var integer Unique identifier for the transaction 368 | */ 369 | public $transaction_id; 370 | 371 | /** 372 | * @var boolean True if there is a file upload; false otherwise 373 | */ 374 | public $upload = false; 375 | 376 | /** 377 | * @var boolean True if this action is handling a form; false otherwise 378 | */ 379 | public $form_handler = false; 380 | 381 | /** 382 | * @var boolean False only when "authorization_function" (if configured) returns a non-true value 383 | */ 384 | public $authorized = true; 385 | 386 | /** 387 | * @var Exception Exception object, instantiated if an exception occurs while executing the action 388 | */ 389 | public $exception; 390 | 391 | /** 392 | * @param string $action API class name 393 | * @param string $method Method name 394 | * @param array $parameters Method parameters 395 | * @param integer $transaction_id Unique identifier for the transaction 396 | * @param boolean $upload True if there is a file upload; false otherwise 397 | * @param boolean $form_handler True if the action is a form handler; false otherwise 398 | */ 399 | public function __construct( $action, $method, $parameters, $transaction_id, $upload = false, $form_handler = false ) 400 | { 401 | foreach( array( 'action', 'method', 'parameters', 'transaction_id', 'upload', 'form_handler' ) as $parameter ) 402 | $this->$parameter = $$parameter; 403 | 404 | if ( empty( $this->parameters ) ) 405 | $this->parameters = array(); 406 | } 407 | 408 | /** 409 | * @return array Result of the action execution 410 | */ 411 | public function run() 412 | { 413 | $response = array( 414 | 'type' => 'rpc', 415 | 'tid' => $this->transaction_id, 416 | 'action' => $this->action, 417 | 'method' => $this->method 418 | ); 419 | 420 | try 421 | { 422 | $result = $this->call_action(); 423 | $response['result'] = $result; 424 | } 425 | 426 | catch ( \Exception $e ) 427 | { 428 | $response['result'] = 'Exception'; 429 | if ( ExtDirect::$debug ) 430 | $response = array( 431 | 'type' => 'exception', 432 | 'tid' => $this->transaction_id, 433 | 'message' => $e->getMessage(), 434 | 'where' => $e->getTraceAsString() 435 | ); 436 | $this->exception = $e; 437 | } 438 | 439 | if ( is_callable( ExtDirect::$transform_response_function ) ) 440 | $response = call_user_func( ExtDirect::$transform_response_function, $this, $response ); 441 | 442 | if ( ExtDirect::$utf8_encode ) 443 | array_walk_recursive( $response, array( $this, 'utf8_encode' ) ); 444 | 445 | return $response; 446 | } 447 | 448 | /** 449 | * @param mixed $value If it is a string, it will be UTF8 encoded 450 | * @param mixed $key Not used (passed by "array_walk_recursive" function) 451 | * @return mixed UTF8 encoded string, or unchanged value if not a string 452 | */ 453 | protected function &utf8_encode( &$value, $key ) 454 | { 455 | if ( is_string( $value ) ) 456 | $value = utf8_encode( $value ); 457 | return $value; 458 | } 459 | 460 | /** 461 | * @return mixed Result of the action 462 | */ 463 | protected function call_action() 464 | { 465 | $class = $this->action; 466 | 467 | if(array_key_exists($class, ExtDirect::$api_classes)) { 468 | $class = ExtDirect::$api_classes[$class]; 469 | } 470 | 471 | 472 | // Accept only calls to classes defined at "api_classes" configuration 473 | if ( !in_array( $class, ExtDirect::$api_classes ) ) 474 | throw new \Exception( 'Call to undefined or not allowed class ' . $class, E_USER_ERROR ); 475 | 476 | // Do not allow calls to magic methods; only allow calls to methods returned by "get_class_methods" function 477 | if ( ( substr( $this->method, 0, 2 ) == '__' ) || !in_array( $this->method, get_class_methods( $class ) ) ) 478 | throw new \Exception( 'Call to undefined or not allowed method ' . $class . '::' . $this->method, E_USER_ERROR ); 479 | 480 | // Do not allow calls to methods that do not pass the declare_method_function (if configured) 481 | if ( !empty( self::$declare_method_function ) && !call_user_func( self::$declare_method_function, $class, $this->method ) ) 482 | throw new \Exception( 'Call to undefined or not allowed method ' . $class . '::' . $this->method, E_USER_ERROR ); 483 | 484 | $ref_method = new \ReflectionMethod( $class, $this->method ); 485 | 486 | // Get number of parameters for the method 487 | if ( ExtDirect::$count_only_required_params ) 488 | $params = $ref_method->getNumberOfRequiredParameters(); 489 | else 490 | $params = $ref_method->getNumberOfParameters(); 491 | 492 | if ( $this->upload && ( count( $_FILES ) == 1 ) ) 493 | $params -= 1; 494 | 495 | if ( count( $this->parameters ) < $params ) 496 | throw new \Exception( 'Call to ' . $class . ' method ' . $this->method . ' needs at least ' . $params . ' parameters', E_USER_ERROR ); 497 | 498 | // Check inheritance 499 | if ( !ExtDirect::$include_inherited_methods && ( $ref_method->getDeclaringClass()->name != $class ) ) 500 | throw new \Exception( 'Call to ' . $class . ' inhreited method ' . $this->method . ' not allowed', E_USER_ERROR ); 501 | 502 | // Confirm if the method is a formHandler 503 | $this->form_handler = $this->form_handler && ( in_array( $class . '::' . $this->method, ExtDirect::$form_handlers ) || ( strpos( $ref_method->getDocComment(), '@formHandler' ) !== false ) ); 504 | 505 | if ( !$this->form_handler ) 506 | $parameters = $this->parameters; 507 | else 508 | { 509 | $parameters = array(); 510 | 511 | // We treat formHandler's parameters in a special way 512 | foreach( $ref_method->getParameters() as $ref_parameter ) 513 | { 514 | $param_name = $ref_parameter->getName(); 515 | 516 | if ( isset( $this->parameters[$param_name] ) ) 517 | $value = $this->parameters[$param_name]; 518 | 519 | elseif ( $this->upload && isset( $_FILES[$param_name] ) ) 520 | $value = $_FILES[$param_name]; 521 | 522 | elseif ( $ref_parameter->isDefaultValueAvailable() ) 523 | $value = $ref_parameter->getDefaultValue(); 524 | 525 | else 526 | $value = null; 527 | 528 | $parameters[] = $value; 529 | } 530 | } 531 | 532 | if ( $ref_method->isStatic() ) 533 | { 534 | if ( !ExtDirect::$include_static_methods ) 535 | throw new \Exception( 'Call to static method ' . $class . '::' . $this->method . ' not allowed', E_USER_ERROR ); 536 | 537 | // If the method is static, we usually don't need to create an instance 538 | if ( !ExtDirect::$instantiate_static ) 539 | return $this->call_action_func_array( array( $class, $this->method ), $parameters ); 540 | } 541 | 542 | // By default, we don't send parameters to constructor, but "constructor_send_params" and "constructor_params" configurations allow this 543 | if ( !ExtDirect::$constructor_send_params && empty( ExtDirect::$constructor_params[$class] ) ) 544 | $this->instance = new $class; 545 | else 546 | { 547 | if ( empty( ExtDirect::$constructor_params[$class] ) ) 548 | $constructor_params = $this->parameters; 549 | else 550 | $constructor_params = ExtDirect::$constructor_params[$class]; 551 | 552 | $ref_class = new \ReflectionClass( $class ); 553 | $this->instance = $ref_class->newInstanceArgs( $constructor_params ); 554 | } 555 | 556 | return $this->call_action_func_array( array( $this->instance, $this->method ), $parameters ); 557 | } 558 | 559 | /** 560 | * Checks for authorization (if "authorization_function" is configured), calls the action method, 561 | * transform the results (if "transform_result_function" is configured), and then return the results 562 | * 563 | * @param callback $callback Action method to be called 564 | * @param array $parameters Parameters to pass to the action method 565 | * @return mixed Result of the action method 566 | */ 567 | protected function call_action_func_array( $callback, $parameters ) 568 | { 569 | if ( is_callable( ExtDirect::$authorization_function ) ) 570 | { 571 | $auth_result = call_user_func( ExtDirect::$authorization_function, $this ); 572 | 573 | $this->authorized = ( $auth_result === true ); 574 | 575 | if ( $auth_result === false ) 576 | throw new \Exception( 'Not authorized to call ' . $this->action . '::' . $this->method, E_USER_ERROR ); 577 | 578 | elseif ( $auth_result !== true ) 579 | $result = $auth_result; 580 | } 581 | 582 | if ( !isset( $result ) ) 583 | $result = call_user_func_array( $callback, $parameters ); 584 | 585 | if ( is_callable( ExtDirect::$transform_result_function ) ) 586 | $result = call_user_func( ExtDirect::$transform_result_function, $this, $result ); 587 | 588 | return $result; 589 | } 590 | } 591 | 592 | /** 593 | * Ext.Direct API controller 594 | * 595 | * @author J. Bruni 596 | */ 597 | class ExtDirectController 598 | { 599 | /** 600 | * @var ExtDirectRequest Object to process HTTP request 601 | */ 602 | public $request; 603 | 604 | /** 605 | * @var ExtDirectResponse Object to store HTTP response 606 | */ 607 | public $response; 608 | 609 | /** 610 | * @param string $api_classes Name of the class or classes to be published to the Ext.Direct API 611 | * @param boolean $autorun If true, automatically run the controller 612 | */ 613 | public function __construct( $api_classes = null, $autorun = true ) 614 | { 615 | if ( is_array( $api_classes ) ) 616 | ExtDirect::$api_classes = $api_classes; 617 | 618 | elseif ( is_string( $api_classes ) ) 619 | ExtDirect::$api_classes = array( $api_classes ); 620 | 621 | $this->request = new ExtDirectRequest(); 622 | $this->response = new ExtDirectResponse(); 623 | 624 | if ( $autorun ) 625 | { 626 | $this->run(); 627 | $this->output(); 628 | exit(); 629 | } 630 | } 631 | 632 | 633 | /** 634 | * @return string JSON or JavaScript API declaration for the classes on "api_classes" configuration array 635 | */ 636 | public function get_api() 637 | { 638 | if ( isset( $_GET['javascript'] ) || ( ExtDirect::$default_api_output == 'javascript' ) ) 639 | return ExtDirect::get_api_javascript(); 640 | else 641 | return ExtDirect::get_api_json(); 642 | } 643 | 644 | /** 645 | * Process the request, execute the actions, and generate the response 646 | */ 647 | public function run() 648 | { 649 | if ( empty( $this->request->actions ) ) 650 | $this->response->contents = $this->get_api(); 651 | 652 | else 653 | { 654 | $response = array(); 655 | foreach( $this->request->actions as $action ) 656 | $response[] = $action->run(); 657 | 658 | if ( count( $response ) > 1 ) 659 | $this->response->contents = utf8_encode( json_encode( $response ) ); 660 | else 661 | $this->response->contents = utf8_encode( json_encode( $response[0] ) ); 662 | 663 | if ( $this->request->upload ) 664 | $this->response->contents = ''; 665 | } 666 | 667 | if ( $this->request->upload ) 668 | $this->response->headers[] = 'Content-Type: text/html'; 669 | else 670 | $this->response->headers[] = 'Content-Type: text/javascript'; 671 | } 672 | 673 | public function getResponseContents() { 674 | return $this->response->contents; 675 | } 676 | 677 | /** 678 | * Output response contents 679 | */ 680 | public function output() 681 | { 682 | foreach( $this->response->headers as $header ) 683 | header( $header ); 684 | 685 | echo $this->response->contents; 686 | } 687 | } 688 | -------------------------------------------------------------------------------- /src/Bulforce/ExtDirect/ExtDirectServiceProvider.php: -------------------------------------------------------------------------------- 1 | app['ext-direct'] = $this->app->share(function($app) 33 | { 34 | return new ExtDirect; 35 | }); 36 | 37 | $this->app->booting(function() 38 | { 39 | $loader = \Illuminate\Foundation\AliasLoader::getInstance(); 40 | $loader->alias('ExtDirect', 'Bulforce\ExtDirect\Facades\ExtDirect'); 41 | }); 42 | 43 | } 44 | 45 | /** 46 | * Get the services provided by the provider. 47 | * 48 | * @return array 49 | */ 50 | public function provides() 51 | { 52 | return array('ext-direct'); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/Bulforce/ExtDirect/Facades/ExtDirect.php: -------------------------------------------------------------------------------- 1 | 'Ext.rpc', 4 | 'descriptor' => 'Ext.rpc.REMOTING_API', 5 | 'debug' => true, 6 | 'api_classes' => array( 7 | 'ExternalItems' => 'ItemExternalController' 8 | ) 9 | ); -------------------------------------------------------------------------------- /src/controllers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bulforce/laravel-ext-direct/98681584324436371f91347e63fae32f107e7fdd/src/controllers/.gitkeep -------------------------------------------------------------------------------- /src/lang/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bulforce/laravel-ext-direct/98681584324436371f91347e63fae32f107e7fdd/src/lang/.gitkeep -------------------------------------------------------------------------------- /src/migrations/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bulforce/laravel-ext-direct/98681584324436371f91347e63fae32f107e7fdd/src/migrations/.gitkeep -------------------------------------------------------------------------------- /src/views/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bulforce/laravel-ext-direct/98681584324436371f91347e63fae32f107e7fdd/src/views/.gitkeep -------------------------------------------------------------------------------- /tests/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bulforce/laravel-ext-direct/98681584324436371f91347e63fae32f107e7fdd/tests/.gitkeep --------------------------------------------------------------------------------