├── views ├── response.php ├── simple.handlebar ├── simple.twig ├── README.md ├── oauth2 │ ├── github.twig │ ├── client │ │ ├── error.twig │ │ ├── granted.twig │ │ ├── index.twig │ │ ├── denied.twig │ │ └── base.twig │ ├── analytics.twig │ └── server │ │ ├── authorize.twig │ │ ├── base.twig │ │ └── header.html └── todo │ ├── list.twig │ ├── list.blade.php │ ├── list.handlebar │ ├── list.php │ ├── index.php │ ├── index.handlebar │ ├── index.blade.php │ └── index.twig ├── public ├── examples │ ├── _016_forms │ │ ├── views │ │ │ └── users.blade.php │ │ ├── Address.php │ │ ├── .htaccess │ │ └── Users.php │ ├── resources │ │ ├── Form.gif │ │ ├── github.png │ │ ├── home.png │ │ ├── Luracast.gif │ │ ├── Luracast.png │ │ ├── Restler.png │ │ ├── examples.png │ │ ├── facebook.png │ │ ├── loading.gif │ │ ├── twitter.png │ │ ├── closelabel.png │ │ ├── debug_view.jpg │ │ ├── explorer1.png │ │ ├── html_view.png │ │ ├── Luracast_dark.png │ │ ├── OAuth2Client.png │ │ ├── OAuth2Server.png │ │ ├── documentation.png │ │ ├── restler_flow.png │ │ ├── stackoverflow.png │ │ ├── auth-code-workflow.png │ │ ├── auth-code-workflow-thumb.png │ │ ├── hacks.css │ │ ├── highlight.css │ │ ├── facebox.css │ │ └── getsource.php │ ├── _013_html │ │ ├── img │ │ │ ├── edit.png │ │ │ ├── delete.png │ │ │ └── button_green.png │ │ ├── .htaccess │ │ ├── DB │ │ │ ├── iTasks.php │ │ │ └── Task.php │ │ └── Tasks.php │ ├── _015_oauth2_server │ │ ├── cache │ │ │ ├── routes.php │ │ │ ├── 05 │ │ │ │ └── ff │ │ │ │ │ └── 95fefb36f5f0d52efc57124c056b.php │ │ │ └── b4 │ │ │ │ └── 4f │ │ │ │ └── d31d4fe40b2a78ec7d0795f97050.php │ │ ├── Auth │ │ │ └── db │ │ │ │ ├── oauth.sqlite │ │ │ │ └── rebuild_db.php │ │ ├── .htaccess │ │ └── css │ │ │ └── shared.css │ ├── _001_helloworld │ │ ├── Say.php │ │ ├── .htaccess │ │ └── index.php │ ├── _005_protected_api │ │ ├── Secured.php │ │ ├── Simple.php │ │ ├── .htaccess │ │ ├── SimpleAuth.php │ │ └── index.php │ ├── common │ │ ├── DataProviderInterface.php │ │ ├── SessionCache.php │ │ └── SessionDataProvider.php │ ├── _002_minimal │ │ ├── .htaccess │ │ ├── Math.php │ │ └── index.php │ ├── _006_routing │ │ ├── .htaccess │ │ └── Api.php │ ├── _007_crud │ │ ├── .htaccess │ │ └── Authors.php │ ├── _003_multiformat │ │ ├── .htaccess │ │ ├── BMI.php │ │ └── index.php │ ├── _008_documentation │ │ ├── .htaccess │ │ └── index.php │ ├── _009_rate_limiting │ │ ├── .htaccess │ │ ├── Author.php │ │ ├── KeyAuth.php │ │ └── index.php │ ├── _011_versioning │ │ ├── .htaccess │ │ └── v1 │ │ │ └── BMI.php │ ├── _012_vendor_mime │ │ ├── .htaccess │ │ └── SomeVendor │ │ │ └── v1 │ │ │ └── BMI.php │ ├── _014_oauth2_client │ │ ├── .htaccess │ │ ├── cache │ │ │ ├── 05 │ │ │ │ └── ff │ │ │ │ │ └── 95fefb36f5f0d52efc57124c056b.php │ │ │ ├── b4 │ │ │ │ └── 4f │ │ │ │ │ └── d31d4fe40b2a78ec7d0795f97050.php │ │ │ └── e0 │ │ │ │ └── 91 │ │ │ │ └── 88a66f88d48558825932c7326987.php │ │ └── css │ │ │ └── shared.css │ ├── _004_error_response │ │ ├── .htaccess │ │ ├── Currency.php │ │ └── index.php │ └── _010_access_control │ │ ├── .htaccess │ │ ├── Access.php │ │ ├── index.php │ │ └── AccessControl.php └── tests │ ├── request_data │ ├── explorer │ │ ├── images │ │ │ ├── logo_small.png │ │ │ ├── throbber.gif │ │ │ ├── wordnik_api.png │ │ │ └── pet_store_api.png │ │ └── lib │ │ │ ├── jquery.slideto.min.js │ │ │ └── jquery.wiggle.min.js │ ├── .htaccess │ ├── index.php │ └── Data.php │ └── param │ ├── .htaccess │ ├── index.php │ ├── MinMax.php │ ├── MinMaxFix.php │ └── Validation.php ├── .github └── FUNDING.yml ├── scratch └── README.md ├── src ├── Explorer │ ├── v2 │ │ └── client │ │ │ ├── images │ │ │ ├── expand.gif │ │ │ ├── collapse.gif │ │ │ ├── throbber.gif │ │ │ ├── logo_small.png │ │ │ └── explorer_icons.png │ │ │ ├── fonts │ │ │ ├── DroidSans.ttf │ │ │ └── DroidSans-Bold.ttf │ │ │ ├── lib │ │ │ ├── jquery.slideto.min.js │ │ │ └── jquery.wiggle.min.js │ │ │ ├── css │ │ │ ├── typography.css │ │ │ └── reset.css │ │ │ ├── o2c.html │ │ │ └── lang │ │ │ ├── translator.js │ │ │ ├── zh-cn.js │ │ │ ├── ja.js │ │ │ ├── tr.js │ │ │ ├── pl.js │ │ │ ├── pt.js │ │ │ ├── en.js │ │ │ ├── ru.js │ │ │ ├── es.js │ │ │ ├── fr.js │ │ │ └── it.js │ ├── v1 │ │ └── client │ │ │ ├── images │ │ │ ├── throbber.gif │ │ │ ├── logo_small.png │ │ │ └── explorer_icons.png │ │ │ ├── lib │ │ │ ├── jquery.slideto.min.js │ │ │ └── jquery.wiggle.min.js │ │ │ ├── o2c.html │ │ │ └── css │ │ │ └── reset.css │ └── Info.php ├── compatibility │ ├── iAuthenticate.php │ ├── restler1.php │ └── restler2.php ├── iProvideMultiVersionApi.php ├── README.md ├── Data │ ├── Invalid.php │ ├── Arr.php │ ├── iValidate.php │ ├── iValueObject.php │ ├── ApiMethodInfo.php │ └── ValueObject.php ├── InvalidAuthCredentials.php ├── Format │ ├── TsvFormat.php │ ├── iDecodeStream.php │ ├── YamlFormat.php │ ├── DependentMultiFormat.php │ ├── AmfFormat.php │ ├── JsFormat.php │ ├── DependentFormat.php │ └── UrlEncodedFormat.php ├── iAuthenticate.php ├── iFilter.php ├── iUseAuthentication.php ├── iCompose.php ├── composer.json ├── iCache.php ├── UI │ ├── Foundation5Form.php │ ├── HtmlForm.php │ └── Bootstrap3Form.php ├── iIdentifyUser.php ├── Redirect.php └── Compose.php ├── behat.yml ├── vendor └── README.md ├── features ├── examples │ ├── _014_oauth2_client.feature │ ├── _015_oauth3_server.feature │ ├── README.md │ ├── _004_error_response.feature │ ├── _005_protected_api.feature │ ├── _001_helloworld.feature │ ├── _011_versioning.feature │ ├── _002_minimal.feature │ ├── _013_html.feature │ ├── _012_vendor_mime.feature │ ├── _007_crud.feature │ ├── _003_multiformat.feature │ └── _006_routing.feature ├── README.md ├── restler │ ├── status_codes.feature │ ├── README.md │ ├── negotiation-charset.feature │ ├── negotiation-language.feature │ ├── annotations.feature │ └── negotiation-format.feature └── tests │ ├── README.md │ └── param │ ├── minmax.feature │ └── minmaxfix.feature ├── SECURITY.md ├── restler.php ├── .gitignore ├── server.php ├── package.ini └── FORMS.md /views/response.php: -------------------------------------------------------------------------------- 1 | Fork me on GitHub -------------------------------------------------------------------------------- /public/examples/_016_forms/Address.php: -------------------------------------------------------------------------------- 1 | 2 |
{{ text }}
3 | 4 |
5 | Edit 6 | Delete 7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /views/todo/list.blade.php: -------------------------------------------------------------------------------- 1 |
  • 2 |
    {{ $text }}
    3 | 4 |
    5 | Edit 6 | Delete 7 |
    8 | 9 |
  • 10 | -------------------------------------------------------------------------------- /views/todo/list.handlebar: -------------------------------------------------------------------------------- 1 |
  • 2 |
    {{ text }}
    3 | 4 |
    5 | Edit 6 | Delete 7 |
    8 | 9 |
  • 10 | -------------------------------------------------------------------------------- /public/examples/_005_protected_api/Simple.php: -------------------------------------------------------------------------------- 1 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors On 11 | -------------------------------------------------------------------------------- /public/examples/_013_html/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors On 11 | -------------------------------------------------------------------------------- /public/examples/resources/hacks.css: -------------------------------------------------------------------------------- 1 | .snippet-wrap pre.sh_sourceCode { 2 | padding: inherit; 3 | -moz-border-radius: 0; 4 | -webkit-border-radius: 0; 5 | border-radius: 0; 6 | box-shadow: none; 7 | -moz-box-shadow: none; 8 | -webkit-box-shadow: none; 9 | } 10 | 11 | .snippet-wrap .snippet-menu,.snippet-wrap .snippet-hide { 12 | font-size: .5em; 13 | } -------------------------------------------------------------------------------- /public/tests/request_data/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors On 11 | -------------------------------------------------------------------------------- /public/examples/_002_minimal/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors Off 11 | -------------------------------------------------------------------------------- /public/examples/_006_routing/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors On 11 | -------------------------------------------------------------------------------- /public/examples/_007_crud/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors Off 11 | -------------------------------------------------------------------------------- /public/examples/_016_forms/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors On 11 | -------------------------------------------------------------------------------- /views/todo/list.php: -------------------------------------------------------------------------------- 1 | 3 |
    {$text}
    4 | 5 |
    6 | Edit 7 | Delete 8 |
    9 | 10 | 11 | 12 | TEMPLATE; 13 | -------------------------------------------------------------------------------- /public/examples/_003_multiformat/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors Off 11 | -------------------------------------------------------------------------------- /public/examples/_005_protected_api/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors Off 11 | -------------------------------------------------------------------------------- /public/examples/_008_documentation/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors Off 11 | -------------------------------------------------------------------------------- /public/examples/_009_rate_limiting/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors On 11 | -------------------------------------------------------------------------------- /public/examples/_011_versioning/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors Off 11 | -------------------------------------------------------------------------------- /public/examples/_012_vendor_mime/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors Off 11 | -------------------------------------------------------------------------------- /public/examples/_014_oauth2_client/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors Off 11 | -------------------------------------------------------------------------------- /public/examples/_015_oauth2_server/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors Off 11 | -------------------------------------------------------------------------------- /public/examples/_004_error_response/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors Off 11 | -------------------------------------------------------------------------------- /public/examples/_010_access_control/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteRule ^$ index.php [QSA,L] 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule ^(.*)$ index.php [QSA,L] 8 | 9 | 10 | php_flag display_errors Off 11 | -------------------------------------------------------------------------------- /public/tests/request_data/index.php: -------------------------------------------------------------------------------- 1 | setSupportedFormats('JsonFormat','CsvFormat'); 12 | $r->addAPIClass('Data', ''); 13 | $r->addAPIClass('Resources'); 14 | $r->handle(); 15 | -------------------------------------------------------------------------------- /public/examples/_009_rate_limiting/Author.php: -------------------------------------------------------------------------------- 1 | 4 | RewriteEngine On 5 | RewriteRule ^$ index.php [QSA,L] 6 | RewriteCond %{REQUEST_FILENAME} !-f 7 | RewriteCond %{REQUEST_FILENAME} !-d 8 | RewriteRule ^(.*)$ index.php [QSA,L] 9 | 10 | 11 | php_flag display_errors Off 12 | -------------------------------------------------------------------------------- /src/iProvideMultiVersionApi.php: -------------------------------------------------------------------------------- 1 | Authorization Error 5 |

    6 | {{ response.error.error_description }} 7 | {% if response.error.error_uri is defined %} 8 | (more information) 9 | {% endif %} 10 |

    11 | back 12 | {% endblock %} -------------------------------------------------------------------------------- /src/compatibility/restler1.php: -------------------------------------------------------------------------------- 1 | 2 | var qp = null; 3 | if(window.location.hash) { 4 | qp = location.hash.substring(1); 5 | } 6 | else { 7 | qp = location.search.substring(1); 8 | } 9 | qp = qp ? JSON.parse('{"' + qp.replace(/&/g, '","').replace(/=/g,'":"') + '"}', 10 | function(key, value) { 11 | return key===""?value:decodeURIComponent(value) } 12 | ):{} 13 | window.opener.onOAuthComplete(qp); 14 | window.close(); 15 | -------------------------------------------------------------------------------- /public/tests/request_data/Data.php: -------------------------------------------------------------------------------- 1 | 12 | * @copyright 2010 Luracast 13 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 14 | * @link http://luracast.com/products/restler/ 15 | * 16 | */ 17 | class Invalid extends Exception 18 | { 19 | 20 | } -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 6.0.x | :white_check_mark: | 8 | | 5.0.x | :white_check_mark: | 9 | | 4.0.x | :white_check_mark: | 10 | | < 4.0 | :x: | 11 | 12 | ## Reporting a Vulnerability 13 | 14 | **DO NOT PUBLISH SECURITY REPORTS PUBLICLY.** 15 | 16 | If you found any issues that might have security implications, please send a report to arul[at]luracast.com 17 | -------------------------------------------------------------------------------- /features/tests/README.md: -------------------------------------------------------------------------------- 1 | # tests 2 | ### Tests that show the expected behaviour for each feature 3 | 4 | For Behavior Driven Development (BDD) we are using Behat to write down the 5 | features and test them against the API 6 | 7 | To run the tests just for `public/tests`, run the following using the terminal from 8 | the project root (where the vendor folder resides) 9 | 10 | bin/behat features/tests 11 | 12 | > **Note:-** This requires the dependencies for restler framework to be 13 | > installed -------------------------------------------------------------------------------- /features/examples/README.md: -------------------------------------------------------------------------------- 1 | # examples 2 | ### Expected features for Live Examples 3 | 4 | For Behavior Driven Development (BDD) we are using Behat to write down the 5 | features and test them against the API 6 | 7 | To run the tests just for examples (`public/examples`), run the following using the terminal from 8 | the project root (where the vendor folder resides) 9 | 10 | bin/behat features/examples 11 | 12 | > **Note:-** This requires the dependencies for restler framework to be 13 | > installed -------------------------------------------------------------------------------- /features/restler/README.md: -------------------------------------------------------------------------------- 1 | # restler 2 | ### *Expected features* for Restler Framework 3 | 4 | For Behavior Driven Development (BDD) we are using Behat to write down the 5 | features and test them against the API 6 | 7 | To run the restler framework tests against examples (`public/examples`), run 8 | the following using the terminal from the project root 9 | (where the vendor folder resides) 10 | 11 | bin/behat features/restler 12 | 13 | > **Note:-** This requires the dependecies for restler framework to be 14 | > installed first -------------------------------------------------------------------------------- /public/examples/_005_protected_api/SimpleAuth.php: -------------------------------------------------------------------------------- 1 | addAPIClass('MinMax'); 15 | $r->addAPIClass('MinMaxFix'); 16 | $r->addAPIClass('Type'); 17 | $r->addAPIClass('Validation'); 18 | //$r->addAPIClass('Resources'); 19 | $r->addAPIClass('Explorer','swagger'); 20 | $r->handle(); 21 | -------------------------------------------------------------------------------- /src/Explorer/v2/client/css/typography.css: -------------------------------------------------------------------------------- 1 | /* Google Font's Droid Sans */ 2 | @font-face { 3 | font-family: 'Droid Sans'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Droid Sans'), local('DroidSans'), url('../fonts/DroidSans.ttf') format('truetype'); 7 | } 8 | /* Google Font's Droid Sans Bold */ 9 | @font-face { 10 | font-family: 'Droid Sans'; 11 | font-style: normal; 12 | font-weight: 700; 13 | src: local('Droid Sans Bold'), local('DroidSans-Bold'), url('../fonts/DroidSans-Bold.ttf') format('truetype'); 14 | } 15 | -------------------------------------------------------------------------------- /src/Explorer/v2/client/o2c.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/oauth2/client/granted.twig: -------------------------------------------------------------------------------- 1 | {% extends "oauth2/client/base.twig" %} 2 | 3 | {% block content %} 4 |

    Authorization Granted!

    5 |
      Access Token: {{ response.token }}  
    6 |

    7 | Here are your friends: 8 |

    9 | 14 |
    The API call can be seen at {{ response.endpoint }}
    15 | {% endblock %} -------------------------------------------------------------------------------- /src/InvalidAuthCredentials.php: -------------------------------------------------------------------------------- 1 | 12 | * @copyright 2010 Luracast 13 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 14 | * @link http://luracast.com/products/restler/ 15 | * 16 | */ 17 | 18 | 19 | class InvalidAuthCredentials extends RestException 20 | { 21 | 22 | } -------------------------------------------------------------------------------- /features/restler/negotiation-charset.feature: -------------------------------------------------------------------------------- 1 | @restler 2 | Feature: Content Negotiation - Charset 3 | 4 | Scenario: Verify Charset support 5 | Given that "Accept-Charset" header is set to "iso-8859-1" 6 | When I request "examples/_002_minimal/math/add" 7 | Then the response status code should be 200 8 | And the response charset is "iso-8859-1" 9 | 10 | Scenario: Unsuported Charset should return 406 11 | Given that "Accept-Charset" header is set to "iso-8859-5" 12 | When I request "examples/_002_minimal/math/add" 13 | Then the response status code should be 406 -------------------------------------------------------------------------------- /views/oauth2/analytics.twig: -------------------------------------------------------------------------------- 1 | {% if googleAnalyticsCode is defined %} 2 | 15 | {% endif %} -------------------------------------------------------------------------------- /features/restler/negotiation-language.feature: -------------------------------------------------------------------------------- 1 | @restler 2 | Feature: Content Negotiation - Language 3 | 4 | Scenario: Supported Language should be used when specified 5 | Given that "Accept-Language" header is set to "en-US" 6 | When I request "examples/_002_minimal/math/add" 7 | Then the response status code should be 200 8 | And the response language is "en-US" 9 | 10 | Scenario: Unsupported Language should be ignored 11 | Given that "Accept-Language" header is set to "fr" 12 | When I request "examples/_002_minimal/math/add" 13 | Then the response status code should be 200 14 | And the response language is "en" -------------------------------------------------------------------------------- /public/examples/_010_access_control/Access.php: -------------------------------------------------------------------------------- 1 | Demo App 5 |

    6 | We would like to use your information in order to integrate with your friends, 7 | use your personal information for nefarious purposes, and to make your life better somehow. 8 |

    9 |

    10 | Click below to integrate with that service you belong to: 11 |

    12 | Authorize 13 | {% endblock %} -------------------------------------------------------------------------------- /public/examples/_002_minimal/Math.php: -------------------------------------------------------------------------------- 1 | ($n1 * $n2) 25 | ); 26 | } 27 | 28 | /** 29 | * @url GET sum/* 30 | */ 31 | function sum() 32 | { 33 | return array_sum(func_get_args()); 34 | } 35 | } -------------------------------------------------------------------------------- /src/Format/TsvFormat.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2010 Luracast 12 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 13 | * @link http://luracast.com/products/restler/ 14 | * 15 | */ 16 | class TsvFormat extends CsvFormat 17 | { 18 | const MIME = 'text/csv'; 19 | const EXTENSION = 'csv'; 20 | public static $delimiter = "\t"; 21 | public static $enclosure = '"'; 22 | public static $escape = '\\'; 23 | public static $haveHeaders = null; 24 | } -------------------------------------------------------------------------------- /public/examples/common/SessionCache.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2010 Luracast 12 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 13 | * @link http://luracast.com/products/restler/ 14 | * 15 | */ 16 | interface iAuthenticate extends iFilter 17 | { 18 | /** 19 | * @return string string to be used with WWW-Authenticate header 20 | * @example Basic 21 | * @example Digest 22 | * @example OAuth 23 | */ 24 | public function __getWWWAuthenticateString(); 25 | } 26 | -------------------------------------------------------------------------------- /restler.php: -------------------------------------------------------------------------------- 1 | Sign In} 12 | */ 13 | function postSignIn($email, $password) 14 | { 15 | return func_get_args(); 16 | } 17 | 18 | /** 19 | * @param string $firstName 20 | * @param string $lastName 21 | * @param string $email 22 | * @param string $password 23 | * @param Address $address 24 | * 25 | * @return array 26 | * 27 | * @view users 28 | */ 29 | function postSignUp($firstName, $lastName, $email, $password, $address) 30 | { 31 | return func_get_args(); 32 | } 33 | } -------------------------------------------------------------------------------- /views/oauth2/client/denied.twig: -------------------------------------------------------------------------------- 1 | {% extends "oauth2/client/base.twig" %} 2 | 3 | {% block content %} 4 |

    Authorization Failed!

    5 |

    6 | It seems authorization has been denied for the following reasons: 7 |

    8 | 21 | {% endblock %} -------------------------------------------------------------------------------- /features/examples/_004_error_response.feature: -------------------------------------------------------------------------------- 1 | @example4 @error-response 2 | Feature: Testing Error Response 3 | 4 | Scenario: Calling currency format without a number 5 | When I request "examples/_004_error_response/currency/format" 6 | Then the response status code should be 400 7 | 8 | Scenario: Calling currency format with invalid number 9 | When I request "examples/_004_error_response/currency/format?number=not_a_number" 10 | Then the response status code should be 400 11 | 12 | Scenario: Calling currency format with invalid number 13 | When I request "examples/_004_error_response/currency/format?number=55" 14 | Then the response status code should be 200 15 | And the response is JSON 16 | And the type is "string" 17 | And the value equals "$55.00" 18 | -------------------------------------------------------------------------------- /public/examples/_004_error_response/Currency.php: -------------------------------------------------------------------------------- 1 | formatCurrency($number, 'USD'); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /public/examples/_001_helloworld/index.php: -------------------------------------------------------------------------------- 1 | = 5.4 7 | Description: Basic hello world example to get started with Restler 5. 8 | Example 1: GET say/hello returns "Hello world!" 9 | Example 2: GET say/hello?to=R.Arul%20Kumaran returns "Hello R.Arul Kumaran!" 10 | Example 3: GET say/hi?to=restler3.1 returns "Hi restler3.1!" 11 | Content: > **Note:-** If you have used Restler 2 before, you will wonder why 12 | the generated routes are lesser with Restler 5. 13 | Look at [Routes](../_006_routing/readme.html) example to understand. 14 | */ 15 | require_once '../../../restler.php'; 16 | use Luracast\Restler\Restler; 17 | 18 | $r = new Restler(); 19 | $r->addAPIClass('Say'); 20 | $r->handle(); 21 | 22 | -------------------------------------------------------------------------------- /src/Explorer/v1/client/lib/jquery.wiggle.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | jQuery Wiggle 3 | Author: WonderGroup, Jordan Thomas 4 | URL: http://labs.wondergroup.com/demos/mini-ui/index.html 5 | License: MIT (http://en.wikipedia.org/wiki/MIT_License) 6 | */ 7 | jQuery.fn.wiggle=function(o){var d={speed:50,wiggles:3,travel:5,callback:null};var o=jQuery.extend(d,o);return this.each(function(){var cache=this;var wrap=jQuery(this).wrap('
    ').css("position","relative");var calls=0;for(i=1;i<=o.wiggles;i++){jQuery(this).animate({left:"-="+o.travel},o.speed).animate({left:"+="+o.travel*2},o.speed*2).animate({left:"-="+o.travel},o.speed,function(){calls++;if(jQuery(cache).parent().hasClass('wiggle-wrap')){jQuery(cache).parent().replaceWith(cache);} 8 | if(calls==o.wiggles&&jQuery.isFunction(o.callback)){o.callback();}});}});}; -------------------------------------------------------------------------------- /src/Explorer/v2/client/lib/jquery.wiggle.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | jQuery Wiggle 3 | Author: WonderGroup, Jordan Thomas 4 | URL: http://labs.wondergroup.com/demos/mini-ui/index.html 5 | License: MIT (http://en.wikipedia.org/wiki/MIT_License) 6 | */ 7 | jQuery.fn.wiggle=function(o){var d={speed:50,wiggles:3,travel:5,callback:null};var o=jQuery.extend(d,o);return this.each(function(){var cache=this;var wrap=jQuery(this).wrap('
    ').css("position","relative");var calls=0;for(i=1;i<=o.wiggles;i++){jQuery(this).animate({left:"-="+o.travel},o.speed).animate({left:"+="+o.travel*2},o.speed*2).animate({left:"-="+o.travel},o.speed,function(){calls++;if(jQuery(cache).parent().hasClass('wiggle-wrap')){jQuery(cache).parent().replaceWith(cache);} 8 | if(calls==o.wiggles&&jQuery.isFunction(o.callback)){o.callback();}});}});}; -------------------------------------------------------------------------------- /src/iFilter.php: -------------------------------------------------------------------------------- 1 | 12 | * @copyright 2010 Luracast 13 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 14 | * @link http://luracast.com/products/restler/ 15 | * 16 | */ 17 | interface iFilter 18 | { 19 | /** 20 | * Access verification method. 21 | * 22 | * API access will be denied when this method returns false 23 | * 24 | * @abstract 25 | * @return boolean true when api access is allowed false otherwise 26 | */ 27 | public function __isAllowed(); 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /public/tests/request_data/explorer/lib/jquery.wiggle.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | jQuery Wiggle 3 | Author: WonderGroup, Jordan Thomas 4 | URL: http://labs.wondergroup.com/demos/mini-ui/index.html 5 | License: MIT (http://en.wikipedia.org/wiki/MIT_License) 6 | */ 7 | jQuery.fn.wiggle=function(o){var d={speed:50,wiggles:3,travel:5,callback:null};var o=jQuery.extend(d,o);return this.each(function(){var cache=this;var wrap=jQuery(this).wrap('
    ').css("position","relative");var calls=0;for(i=1;i<=o.wiggles;i++){jQuery(this).animate({left:"-="+o.travel},o.speed).animate({left:"+="+o.travel*2},o.speed*2).animate({left:"-="+o.travel},o.speed,function(){calls++;if(jQuery(cache).parent().hasClass('wiggle-wrap')){jQuery(cache).parent().replaceWith(cache);} 8 | if(calls==o.wiggles&&jQuery.isFunction(o.callback)){o.callback();}});}});}; -------------------------------------------------------------------------------- /src/Format/iDecodeStream.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2010 Luracast 12 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 13 | * @link http://luracast.com/products/restler/ 14 | * 15 | */ 16 | interface iDecodeStream 17 | { 18 | 19 | /** 20 | * Decode the given data stream 21 | * 22 | * @param string $stream A stream resource with data 23 | * sent from client to the api 24 | * in the given format. 25 | * 26 | * @return array associative array of the parsed data 27 | */ 28 | public function decodeStream($stream); 29 | 30 | } -------------------------------------------------------------------------------- /public/examples/_010_access_control/index.php: -------------------------------------------------------------------------------- 1 | = 5.4 7 | Description: 8 | This example shows how you can extend the authentication system to create 9 | a robust access control system. As a added bonus we also restrict api 10 | documentation based on the same. 11 | 12 | When the `api_key` is 13 | 14 | - blank you will see the public api 15 | - `12345` you will see the api that is accessible by an user 16 | - `67890` you will see all api as you have the admin rights 17 | 18 | Try it out yourself [here](explorer/index.html#!/v1) 19 | */ 20 | require_once '../../../restler.php'; 21 | use Luracast\Restler\Restler; 22 | 23 | $r = new Restler(); 24 | $r->addAPIClass('Access', ''); 25 | $r->addAPIClass('Explorer'); 26 | $r->addAuthenticationClass('AccessControl'); 27 | $r->handle(); 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .foundation 2 | *.tgz 3 | *.phar 4 | *.lock 5 | *tmp 6 | scratch/* 7 | test/reports 8 | bin/behat 9 | vendor/behat 10 | vendor/ChiperSoft 11 | vendor/composer 12 | vendor/guzzle 13 | vendor/Luracast/explorer 14 | vendor/autoload.php 15 | vendor/symfony 16 | vendor/mustache 17 | vendor/zendframework 18 | vendor/rodneyrehm 19 | vendor/twig 20 | vendor/illuminate 21 | vendor/bshaffer 22 | .idea 23 | tag.sh 24 | bin/* 25 | build 26 | public/examples/_014_oauth2_client/cache 27 | public/examples/_015_oauth2_server/cache 28 | public/examples/_015_oauth2_server/OAuth2/db 29 | public/examples/_013_html/cache 30 | vendor/bin 31 | public/examples/_016_forms/cache 32 | behat 33 | yaml-lint 34 | carbon 35 | vendor/guzzlehttp 36 | vendor/psr/log 37 | vendor/psr 38 | vendor/ralouphie 39 | vendor/voku 40 | vendor/rize 41 | vendor/nesbot 42 | vendor/doctrine 43 | behat-guzzle-cookie-data.json 44 | cache 45 | public/examples/_014_oauth2_client/cache -------------------------------------------------------------------------------- /src/Data/Arr.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2010 Luracast 11 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 12 | * @link http://luracast.com/products/restler/ 13 | * 14 | */ 15 | class Arr 16 | { 17 | /** 18 | * Deep copy given array 19 | * 20 | * @param array $arr 21 | * 22 | * @return array 23 | */ 24 | public static function copy(array $arr) 25 | { 26 | $copy = array(); 27 | foreach ($arr as $key => $value) { 28 | if (is_array($value)) $copy[$key] = static::copy($value); 29 | else if (is_object($value)) $copy[$key] = clone $value; 30 | else $copy[$key] = $value; 31 | } 32 | return $copy; 33 | } 34 | } -------------------------------------------------------------------------------- /public/tests/param/MinMax.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2010 Luracast 12 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 13 | * @link http://luracast.com/products/restler/ 14 | * 15 | */ 16 | interface iUseAuthentication 17 | { 18 | /** 19 | * This method will be called first for filter classes and api classes so 20 | * that they can respond accordingly for filer method call and api method 21 | * calls 22 | * 23 | * @abstract 24 | * 25 | * @param bool $isAuthenticated passes true when the authentication is 26 | * done false otherwise 27 | * 28 | * @return mixed 29 | */ 30 | public function __setAuthenticationStatus($isAuthenticated=false); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /public/examples/_015_oauth2_server/cache/05/ff/95fefb36f5f0d52efc57124c056b.php: -------------------------------------------------------------------------------- 1 | parent = false; 11 | 12 | $this->blocks = array( 13 | ); 14 | } 15 | 16 | protected function doDisplay(array $context, array $blocks = array()) 17 | { 18 | // line 1 19 | echo "\"Fork"; 20 | } 21 | 22 | public function getTemplateName() 23 | { 24 | return "oauth2/github.twig"; 25 | } 26 | 27 | public function getDebugInfo() 28 | { 29 | return array ( 26 => 5, 21 => 2, 19 => 1,); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Data/iValidate.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2010 Luracast 11 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 12 | * @link http://luracast.com/products/restler/ 13 | * 14 | */ 15 | interface iValidate { 16 | 17 | /** 18 | * method used for validation. 19 | * 20 | * @param mixed $input 21 | * data that needs to be validated 22 | * @param ValidationInfo $info 23 | * information to be used for validation 24 | * @return boolean false in case of failure or fixed value in the expected 25 | * type 26 | * @throws \Luracast\Restler\RestException 400 with information about the 27 | * failed 28 | * validation 29 | */ 30 | public static function validate($input, ValidationInfo $info); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/Format/YamlFormat.php: -------------------------------------------------------------------------------- 1 | 14 | * @copyright 2010 Luracast 15 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 16 | * @link http://luracast.com/products/restler/ 17 | * 18 | */ 19 | class YamlFormat extends DependentFormat 20 | { 21 | const MIME = 'text/plain'; 22 | const EXTENSION = 'yaml'; 23 | 24 | const PACKAGE_NAME = 'symfony/yaml:*'; 25 | const EXTERNAL_CLASS = 'Symfony\Component\Yaml\Yaml'; 26 | 27 | public function encode($data, $humanReadable = false) 28 | { 29 | return @Yaml::dump(Obj::toArray($data), $humanReadable ? 10 : 4); 30 | } 31 | 32 | public function decode($data) 33 | { 34 | return Yaml::parse($data); 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /features/examples/_005_protected_api.feature: -------------------------------------------------------------------------------- 1 | @example5 @protected-api 2 | Feature: Testing Protected Api 3 | 4 | Scenario: Calling restricted api without a key 5 | When I request "examples/_005_protected_api/restricted" 6 | Then the response status code should be 401 7 | 8 | Scenario: Calling restricted api with invalid key 9 | When I request "examples/_005_protected_api/restricted?key=not-valid" 10 | Then the response status code should be 401 11 | 12 | Scenario: Calling restricted api with valid key 13 | When I request "examples/_005_protected_api/restricted?key=rEsTlEr3" 14 | Then the response status code should be 200 15 | And the response is JSON 16 | And the type is "string" 17 | And the value equals "protected method" 18 | 19 | Scenario: Calling restricted api class with valid key 20 | When I request "examples/_005_protected_api/secured?key=rEsTlEr3" 21 | Then the response status code should be 200 22 | And the response is JSON 23 | And the type is "string" 24 | And the value equals "protected class" 25 | -------------------------------------------------------------------------------- /public/tests/param/MinMaxFix.php: -------------------------------------------------------------------------------- 1 | 13 | * @copyright 2010 Luracast 14 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 15 | * @link http://luracast.com/products/restler/ 16 | * 17 | */ 18 | interface iCompose { 19 | /** 20 | * Result of an api call is passed to this method 21 | * to create a standard structure for the data 22 | * 23 | * @param mixed $result can be a primitive or array or object 24 | */ 25 | public function response($result); 26 | 27 | /** 28 | * When the api call results in RestException this method 29 | * will be called to return the error message 30 | * 31 | * @param RestException $exception exception that has reasons for failure 32 | * 33 | * @return 34 | */ 35 | public function message(RestException $exception); 36 | } -------------------------------------------------------------------------------- /public/tests/param/Validation.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2010 Luracast 12 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 13 | * @link http://luracast.com/products/restler/ 14 | * 15 | */ 16 | interface iValueObject 17 | { 18 | 19 | /** 20 | * This static method is called for creating an instance of the class by 21 | * passing the initiation values as an array. 22 | * 23 | * @static 24 | * @abstract 25 | * 26 | * @param array $properties 27 | * 28 | * @return iValueObject 29 | */ 30 | public static function __set_state(array $properties); 31 | 32 | /** 33 | * This method provides a string representation for the instance 34 | * 35 | * @return string 36 | */ 37 | public function __toString(); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /package.ini: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "Restler" 3 | vendor = "Luracast" 4 | summary = "

    Restler is a simple and effective multi-protocol REST API Server written in PHP.
    5 | Just deal with your business logic in php, restler will take care of the REST!

    " 6 | desc = "

    Restler is a simple and effective multi-protocol REST API Server written in PHP.
    7 | Just deal with your business logic in php, restler will take care of the REST!

    " 8 | version = "3.0.0" 9 | stability = "alpha" 10 | channel = "" 11 | homepage = "http://luracast.com/products/restler/" 12 | license = "LGPL-2.1" 13 | author = "Luracast " 14 | authors[] = "Nick Lombard " 15 | contributors[] = "Luracast " 16 | contributors[] = "Nick Lombard " 17 | 18 | [require] 19 | php = "5.3" 20 | pearinstaller = "1.4.1" 21 | ChiperSoft/CFPropertyList = "dev-master", 22 | mustache/mustache = "dev-master", 23 | zendframework/zendamf = "dev-master", 24 | symfony/yaml = "*" 25 | 26 | [roles] 27 | vendor = "src" 28 | test = "test" 29 | config = "cfg" 30 | bin = "bin" 31 | public = "www" 32 | 33 | -------------------------------------------------------------------------------- /public/examples/_004_error_response/index.php: -------------------------------------------------------------------------------- 1 | = 5.4 7 | Description: API methods can make use of RestException class to provide 8 | error information to the user. 9 | 10 | use `throw new RestException($httpStatusCode)` to send the error response 11 | to the client. 12 | 13 | For the list of HTTP Status codes and their meaning take a look at 14 | [Wikipedia](http://en.wikipedia.org/wiki/Http_status_codes) 15 | 16 | Example 1: GET currency/format returns 17 | 18 | { 19 | "error": { 20 | "code": 400, 21 | "message": "Bad Request" 22 | } 23 | } 24 | 25 | Example 2: GET currency/format?number=not_a_number returns 26 | 27 | { 28 | "error": { 29 | "code": 400, 30 | "message": "Bad Request: not a valid number" 31 | } 32 | } 33 | 34 | Example 3: GET currency/format?number=55 returns "USD55.00" 35 | */ 36 | 37 | require_once '../../../restler.php'; 38 | use Luracast\Restler\Restler; 39 | 40 | $r = new Restler(); 41 | $r->addAPIClass('Currency'); 42 | $r->handle(); 43 | 44 | -------------------------------------------------------------------------------- /public/examples/_013_html/DB/iTasks.php: -------------------------------------------------------------------------------- 1 | parent = false; 11 | 12 | $this->blocks = array( 13 | ); 14 | } 15 | 16 | protected function doDisplay(array $context, array $blocks = array()) 17 | { 18 | // line 1 19 | echo "\"Fork"; 20 | } 21 | 22 | public function getTemplateName() 23 | { 24 | return "oauth2/github.twig"; 25 | } 26 | 27 | public function getDebugInfo() 28 | { 29 | return array ( 26 => 5, 19 => 1, 117 => 56, 114 => 55, 92 => 34, 83 => 27, 80 => 26, 71 => 57, 69 => 55, 63 => 51, 61 => 26, 56 => 23, 53 => 22, 51 => 21, 40 => 14, 35 => 13, 21 => 2,); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Format/DependentMultiFormat.php: -------------------------------------------------------------------------------- 1 | packagist package name as an associative array 11 | * 12 | * @return array list of dependencies for the format 13 | * 14 | * @example return ['Illuminate\\View\\View' => 'illuminate/view:4.2.*'] 15 | */ 16 | abstract public function getDependencyMap(); 17 | 18 | protected function checkDependency($class = null) 19 | { 20 | if (empty($class)) { 21 | $class = key($this->getDependencyMap()); 22 | } 23 | if (!class_exists($class, true)) { 24 | $map = $this->getDependencyMap(); 25 | $package = $map[$class]; 26 | throw new RestException( 27 | 500, 28 | get_called_class() . ' has external dependency. Please run `composer require ' . 29 | $package . '` from the project root. Read https://getcomposer.org for more info' 30 | ); 31 | } 32 | } 33 | 34 | public function __construct() 35 | { 36 | $this->checkDependency(); 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /public/examples/_002_minimal/index.php: -------------------------------------------------------------------------------- 1 | = 5.4 6 | Description: Shows the bare minimum code needed to get your RESTful api server 7 | up and running 8 | 9 | Example 1: GET math/add returns 2 10 | Example 2: GET math/add?n1=6&n2=4 returns 10 11 | Example 3: GET math/multiply/4/3 returns {"result":12} 12 | Example 4: GET math/multiply/4/NaN returns 13 | { 14 | "error": { 15 | "code": 400, 16 | "message": "Bad Request: invalid value specified for n2" 17 | } 18 | } 19 | Example 5: GET math/sum/1/2/3/4/5 returns 15 20 | 21 | Content: 22 | 23 | > **Note:-** 24 | > 25 | > 1. Take note of the php doc comments, they make sure the data is sent in the 26 | > right type and validated automatically before calling the api method. 27 | > 2. Sum method accepts variable number of parameters with the help of 28 | > wildcard manual route. Read the [Routes](../_006_routing/readme.html) 29 | > example for better understanding 30 | 31 | */ 32 | 33 | require_once '../../../restler.php'; 34 | //smart auto loader helps loading a namespaced class with just the name part 35 | use Luracast\Restler\Restler; 36 | 37 | $r = new Restler(); 38 | $r->addAPIClass('Math'); 39 | $r->handle(); 40 | 41 | -------------------------------------------------------------------------------- /features/examples/_001_helloworld.feature: -------------------------------------------------------------------------------- 1 | @example1 @helloworld 2 | Feature: Testing Helloworld Example 3 | 4 | Scenario: Saying Hello world 5 | When I request "examples/_001_helloworld/say/hello" 6 | Then the response status code should be 200 7 | And the response is JSON 8 | And the type is "string" 9 | And the value equals "Hello world!" 10 | 11 | Scenario: Saying Hello Restler 12 | Given that "to" is set to "Restler" 13 | When I request "examples/_001_helloworld/say/hello{?to}" 14 | Then the response status code should be 200 15 | And the response is JSON 16 | And the type is "string" 17 | And the value equals "Hello Restler!" 18 | 19 | Scenario: Saying 20 | When I request "examples/_001_helloworld/say" 21 | Then the response status code should be 404 22 | And the response is JSON 23 | And the type is "array" 24 | 25 | Scenario: Saying Hi 26 | When I request "examples/_001_helloworld/say/hi" 27 | Then the response status code should be 400 28 | And the response is JSON 29 | And the type is "array" 30 | 31 | Scenario: Saying Hi Arul 32 | Given that "to" is set to "Arul" 33 | When I request "examples/_001_helloworld/say/hi{?to}" 34 | Then the response status code should be 200 35 | And the response is JSON 36 | And the type is "string" 37 | And the value equals "Hi Arul!" 38 | -------------------------------------------------------------------------------- /views/oauth2/server/authorize.twig: -------------------------------------------------------------------------------- 1 | {% extends "oauth2/server/base.twig" %} 2 | 3 | {% block content %} 4 |

    5 | Demo App would like to access the following data: 6 |

    7 |
      8 |
    • friends
    • 9 |
    • memories
    • 10 |
    • hopes, dreams, passions, etc.
    • 11 |
    • sock drawer
    • 12 |
    13 |

    It will use this data to:

    14 |
      15 |
    • integrate with friends
    • 16 |
    • make your life better
    • 17 |
    • miscellaneous nefarious purposes
    • 18 |
    19 |
      20 |
    • 21 |
      22 | 24 | 25 |
      26 |
    • 27 |
    • 28 |
      30 | cancel 32 | 33 |
      34 |
    • 35 |
    36 | {% endblock %} -------------------------------------------------------------------------------- /public/examples/_013_html/DB/Task.php: -------------------------------------------------------------------------------- 1 | id = Util::nestedValue($properties, 'id'); 36 | $task->position = Util::nestedValue($properties, 'position'); 37 | $task->text = Util::nestedValue($properties, 'text'); 38 | return $task; 39 | } 40 | 41 | /** 42 | * This method provides a string representation for the instance 43 | * 44 | * @return string 45 | */ 46 | public function __toString() 47 | { 48 | return "Task(id = $this->id, position = $this->position, text = $this->text)"; 49 | } 50 | 51 | public function jsonSerialize() 52 | { 53 | return (array)$this; 54 | } 55 | } -------------------------------------------------------------------------------- /public/examples/_014_oauth2_client/css/shared.css: -------------------------------------------------------------------------------- 1 | .button { 2 | color: #333; 3 | text-shadow: 0 1px 0 white; 4 | border: 1px solid #D4D4D4; 5 | border-bottom-color: #BCBCBC; 6 | background: #FAFAFA; 7 | background: -moz-linear-gradient(#FAFAFA, #EAEAEA); 8 | background: -webkit-linear-gradient(#FAFAFA, #EAEAEA); 9 | -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#fafafa', endColorstr='#eaeaea')"; 10 | position: relative; 11 | display: inline-block; 12 | padding: 0 10px 0 10px; 13 | font-family: Helvetica, arial, freesans, clean, sans-serif; 14 | font-size: 13px; 15 | font-weight: bold; 16 | line-height: 24px; 17 | white-space: nowrap; 18 | border-radius: 3px; 19 | cursor: pointer; 20 | -webkit-touch-callout: none; 21 | -webkit-user-select: none; 22 | -khtml-user-select: none; 23 | -moz-user-select: none; 24 | -ms-user-select: none; 25 | user-select: none; 26 | text-decoration: none; 27 | } 28 | 29 | .button:hover { 30 | color: white; 31 | text-decoration: none; 32 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3); 33 | border-color: #518CC6; 34 | border-bottom-color: #2A65A0; 35 | background: #599BDC; 36 | background: -moz-linear-gradient(#599BDC, #3072B3); 37 | background: -webkit-linear-gradient(#599BDC, #3072B3); 38 | -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#599bdc', endColorstr='#3072b3')"; 39 | } -------------------------------------------------------------------------------- /public/examples/_015_oauth2_server/css/shared.css: -------------------------------------------------------------------------------- 1 | .button { 2 | color: #333; 3 | text-shadow: 0 1px 0 white; 4 | border: 1px solid #D4D4D4; 5 | border-bottom-color: #BCBCBC; 6 | background: #FAFAFA; 7 | background: -moz-linear-gradient(#FAFAFA, #EAEAEA); 8 | background: -webkit-linear-gradient(#FAFAFA, #EAEAEA); 9 | -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#fafafa', endColorstr='#eaeaea')"; 10 | position: relative; 11 | display: inline-block; 12 | padding: 0 10px 0 10px; 13 | font-family: Helvetica, arial, freesans, clean, sans-serif; 14 | font-size: 13px; 15 | font-weight: bold; 16 | line-height: 24px; 17 | white-space: nowrap; 18 | border-radius: 3px; 19 | cursor: pointer; 20 | -webkit-touch-callout: none; 21 | -webkit-user-select: none; 22 | -khtml-user-select: none; 23 | -moz-user-select: none; 24 | -ms-user-select: none; 25 | user-select: none; 26 | text-decoration: none; 27 | } 28 | 29 | .button:hover { 30 | color: white; 31 | text-decoration: none; 32 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3); 33 | border-color: #518CC6; 34 | border-bottom-color: #2A65A0; 35 | background: #599BDC; 36 | background: -moz-linear-gradient(#599BDC, #3072B3); 37 | background: -webkit-linear-gradient(#599BDC, #3072B3); 38 | -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#599bdc', endColorstr='#3072b3')"; 39 | } -------------------------------------------------------------------------------- /src/Format/AmfFormat.php: -------------------------------------------------------------------------------- 1 | 17 | * @copyright 2010 Luracast 18 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 19 | * @link http://luracast.com/products/restler/ 20 | * 21 | */ 22 | class AmfFormat extends DependentFormat 23 | { 24 | const MIME = 'application/x-amf'; 25 | const EXTENSION = 'amf'; 26 | 27 | const PACKAGE_NAME = 'zendframework/zendamf:dev-master'; 28 | const EXTERNAL_CLASS = 'ZendAmf\\Parser\\Amf3\\Deserializer'; 29 | 30 | public function encode($data, $humanReadable = false) 31 | { 32 | 33 | $stream = new OutputStream(); 34 | $serializer = new Serializer($stream); 35 | $serializer->writeTypeMarker($data); 36 | 37 | return $stream->getStream(); 38 | } 39 | 40 | public function decode($data) 41 | { 42 | $stream = new InputStream(substr($data, 1)); 43 | $deserializer = new Deserializer($stream); 44 | 45 | return $deserializer->readTypeMarker(); 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/compatibility/restler2.php: -------------------------------------------------------------------------------- 1 | isFile() 15 | && 'php' === $fileInfo->getExtension() 16 | && ctype_lower($fileInfo->getBasename('.php')) 17 | && preg_match( 18 | '/^ *(class|interface|abstract +class)' 19 | . ' +([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)/m', 20 | file_get_contents($fileInfo->getPathname()), 21 | $matches 22 | ) 23 | ) 24 | $classMap[$matches[2]] = $fileInfo->getPathname(); 25 | 26 | AutoLoader::seen($classMap); 27 | 28 | //changes in iAuthenticate 29 | Defaults::$authenticationMethod = '__isAuthenticated'; 30 | 31 | include __DIR__ . '/iAuthenticate.php'; 32 | 33 | //changes in auto routing 34 | Defaults::$smartAutoRouting = false; 35 | Defaults::$smartParameterParsing = false; 36 | Defaults::$autoValidationEnabled = false; 37 | 38 | //changes in parsing embedded data in comments 39 | CommentParser::$embeddedDataPattern = '/\((\S+)\)/ms'; 40 | CommentParser::$embeddedDataIndex = 1; -------------------------------------------------------------------------------- /public/examples/_005_protected_api/index.php: -------------------------------------------------------------------------------- 1 | = 5.4 7 | Description: Not all the API exposed needs to be public, we need to protect 8 | some of our API. 9 | Here are three ways to protect a method 10 | 11 | 12 | 1. Change it to a `protected function` 13 | 2. Add a PHPDoc comment `@access protected` to the method 14 | 3. Add `@access protected` comment to the class to protect all methods of that 15 | class 16 | 17 | 18 | In order to provide access to those protected methods we use a class that 19 | implements `iAuthenticate`. Also note that An Authentication class is also an 20 | API class so all public methods that does not begin with `_` will be exposed as 21 | API for example [SimpleAuth::key](simpleauth/key). It can be used to create 22 | login/logout methods. 23 | 24 | Example 1: GET restricted returns 25 | 26 | { 27 | "error": { 28 | "code": 401, 29 | "message": "Unauthorized" 30 | } 31 | } 32 | 33 | Example 2: GET restricted?key=rEsTlEr3 returns "protected method" 34 | 35 | Example 3: GET secured?key=rEsTlEr3 returns "protected class" 36 | */ 37 | 38 | require_once '../../../restler.php'; 39 | use Luracast\Restler\Restler; 40 | 41 | $r = new Restler(); 42 | 43 | $r->addAPIClass('Simple', ''); //map it to root 44 | $r->addAPIClass('Secured'); 45 | $r->addAuthenticationClass('SimpleAuth'); 46 | $r->handle(); 47 | 48 | -------------------------------------------------------------------------------- /src/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"restler/framework", 3 | "description":"Just the Restler Framework without the tests and examples", 4 | "type":"library", 5 | "keywords":["server","api","framework","REST"], 6 | "homepage":"https://luracast.com/products/restler/", 7 | "license":"LGPL-2.1-or-later", 8 | "authors":[ 9 | { 10 | "name":"Luracast", 11 | "email":"arul@luracast.com" 12 | } 13 | ], 14 | "suggest":{ 15 | "rodneyrehm/plist":"If you need Apple plist binary/xml format", 16 | "zendframework/zendamf":"If you need AMF format", 17 | "symfony/yaml":"If you need YAML format", 18 | "twig/twig":"If you want to use twig templates with Html format", 19 | "mustache/mustache":"If you want to use mustache/handlebar templates with Html format", 20 | "illuminate/view":"If you want to use laravel blade templates with Html format", 21 | "bshaffer/oauth2-server-php":"If you want to use OAuth2 for authentication" 22 | }, 23 | "require":{ 24 | "php":">=5.4.0", 25 | "ext-json": "*" 26 | }, 27 | "repositories":[ 28 | { 29 | "type":"vcs", 30 | "url":"https://github.com/zendframework/ZendAmf.git" 31 | } 32 | ], 33 | "autoload":{ 34 | "psr-4":{ 35 | "Luracast\\Restler\\":"/" 36 | } 37 | }, 38 | "replace": { 39 | "luracast/restler":"3.*" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /public/examples/_003_multiformat/BMI.php: -------------------------------------------------------------------------------- 1 | bmi = round($kg / ($meter * $meter), 2); 24 | $lb = round($kg / 0.45359237, 2); 25 | 26 | if ($result->bmi < 18.5) { 27 | $result->message = 'Underweight'; 28 | } elseif ($result->bmi <= 24.9) { 29 | $result->message = 'Normal weight'; 30 | } elseif ($result->bmi <= 29.9) { 31 | $result->message = 'Overweight'; 32 | } else { 33 | $result->message = 'Obesity'; 34 | } 35 | $result->metric = array( 36 | 'height' => "$cm centimeter", 37 | 'weight' => "$weight kilograms" 38 | ); 39 | $result->imperial = array( 40 | 'height' => "$feet feet $inches inches", 41 | 'weight' => "$lb pounds" 42 | ); 43 | return $result; 44 | } 45 | } -------------------------------------------------------------------------------- /public/examples/_007_crud/Authors.php: -------------------------------------------------------------------------------- 1 | dp = new DB_PDO_Sqlite(); 14 | * $this->dp = new DB_PDO_MySQL(); 15 | * $this->dp = new DB_Serialized_File(); 16 | */ 17 | $this->dp = new SessionDataProvider(); 18 | } 19 | 20 | function index() 21 | { 22 | return $this->dp->getAll(); 23 | } 24 | 25 | function get($id) 26 | { 27 | return $this->dp->get($id); 28 | } 29 | 30 | function post($request_data = null) 31 | { 32 | return $this->dp->insert($this->_validate($request_data)); 33 | } 34 | 35 | function put($id, $request_data = null) 36 | { 37 | return $this->dp->update($id, $this->_validate($request_data)); 38 | } 39 | 40 | function delete($id) 41 | { 42 | return $this->dp->delete($id); 43 | } 44 | 45 | private function _validate($data) 46 | { 47 | $author = array(); 48 | foreach (authors::$FIELDS as $field) { 49 | //you may also validate the data here 50 | if (!isset($data[$field])) { 51 | throw new RestException(400, "$field field missing"); 52 | } 53 | $author[$field] = $data[$field]; 54 | } 55 | return $author; 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /public/examples/resources/highlight.css: -------------------------------------------------------------------------------- 1 | /* 2 | IR_Black style (c) Vasily Mikhailitchenko 3 | */ 4 | 5 | .hljs { 6 | display: block; 7 | overflow-x: auto; 8 | padding: 0.5em; 9 | background: #000; 10 | color: #f8f8f8; 11 | } 12 | 13 | .hljs-comment, 14 | .hljs-quote, 15 | .hljs-meta { 16 | color: #7c7c7c; 17 | } 18 | 19 | .hljs-keyword, 20 | .hljs-selector-tag, 21 | .hljs-tag, 22 | .hljs-name { 23 | color: #96cbfe; 24 | } 25 | 26 | .hljs-attribute, 27 | .hljs-selector-id { 28 | color: #ffffb6; 29 | } 30 | 31 | .hljs-string, 32 | .hljs-selector-attr, 33 | .hljs-selector-pseudo, 34 | .hljs-addition { 35 | color: #a8ff60; 36 | } 37 | 38 | .hljs-subst { 39 | color: #daefa3; 40 | } 41 | 42 | .hljs-regexp, 43 | .hljs-link { 44 | color: #e9c062; 45 | } 46 | 47 | .hljs-title, 48 | .hljs-section, 49 | .hljs-type, 50 | .hljs-doctag { 51 | color: #ffffb6; 52 | } 53 | 54 | .hljs-symbol, 55 | .hljs-bullet, 56 | .hljs-variable, 57 | .hljs-template-variable, 58 | .hljs-literal { 59 | color: #c6c5fe; 60 | } 61 | 62 | .hljs-number, 63 | .hljs-deletion { 64 | color:#ff73fd; 65 | } 66 | 67 | .hljs-emphasis { 68 | font-style: italic; 69 | } 70 | 71 | .hljs-strong { 72 | font-weight: bold; 73 | } 74 | 75 | pre .number { 76 | color:#FF73FD; 77 | } 78 | 79 | pre .coffeescript .javascript, 80 | pre .javascript .xml, 81 | pre .tex .formula, 82 | pre .xml .javascript, 83 | pre .xml .vbscript, 84 | pre .xml .css, 85 | pre .xml .cdata { 86 | opacity: 0.7; 87 | } 88 | -------------------------------------------------------------------------------- /public/examples/resources/facebox.css: -------------------------------------------------------------------------------- 1 | #facebox { 2 | position: absolute; 3 | top: 0; 4 | left: 0; 5 | z-index: 100; 6 | text-align: left; 7 | } 8 | 9 | 10 | #facebox .popup{ 11 | position:relative; 12 | border:3px solid rgba(0,0,0,0); 13 | -webkit-border-radius:5px; 14 | -moz-border-radius:5px; 15 | border-radius:5px; 16 | -webkit-box-shadow:0 0 18px rgba(0,0,0,0.4); 17 | -moz-box-shadow:0 0 18px rgba(0,0,0,0.4); 18 | box-shadow:0 0 18px rgba(0,0,0,0.4); 19 | } 20 | 21 | #facebox .content { 22 | display:table; 23 | width: 370px; 24 | padding: 10px; 25 | background: #fff; 26 | -webkit-border-radius:4px; 27 | -moz-border-radius:4px; 28 | border-radius:4px; 29 | } 30 | 31 | #facebox .content > p:first-child{ 32 | margin-top:0; 33 | } 34 | #facebox .content > p:last-child{ 35 | margin-bottom:0; 36 | } 37 | 38 | #facebox .close{ 39 | position:absolute; 40 | top:5px; 41 | right:5px; 42 | padding:2px; 43 | background:#fff; 44 | } 45 | #facebox .close img{ 46 | opacity:0.3; 47 | } 48 | #facebox .close:hover img{ 49 | opacity:1.0; 50 | } 51 | 52 | #facebox .loading { 53 | text-align: center; 54 | } 55 | 56 | #facebox .image { 57 | text-align: center; 58 | } 59 | 60 | #facebox img { 61 | border: 0; 62 | margin: 0; 63 | } 64 | 65 | #facebox_overlay { 66 | position: fixed; 67 | top: 0px; 68 | left: 0px; 69 | height:100%; 70 | width:100%; 71 | } 72 | 73 | .facebox_hide { 74 | z-index:-100; 75 | } 76 | 77 | .facebox_overlayBG { 78 | background-color: #000; 79 | z-index: 99; 80 | } -------------------------------------------------------------------------------- /views/oauth2/server/base.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | {% include 'oauth2/analytics.twig' %} 22 | {% include 'oauth2/github.twig' %} 23 | {% include 'oauth2/server/header.html' %} 24 | 25 |
    26 |
    27 |
    28 | {% block content %} 29 | {% endblock %} 30 |
    31 |
    32 |
    33 | 34 | 35 | -------------------------------------------------------------------------------- /public/examples/_006_routing/Api.php: -------------------------------------------------------------------------------- 1 | 9 | * @copyright 2010 Luracast 10 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 11 | * @link http://luracast.com/products/restler/ 12 | * 13 | */ 14 | interface iCache 15 | { 16 | /** 17 | * store data in the cache 18 | * 19 | * @abstract 20 | * 21 | * @param string $name 22 | * @param mixed $data 23 | * 24 | * @return boolean true if successful 25 | */ 26 | public function set($name, $data); 27 | 28 | /** 29 | * retrieve data from the cache 30 | * 31 | * @abstract 32 | * 33 | * @param string $name 34 | * @param bool $ignoreErrors 35 | * 36 | * @return mixed 37 | */ 38 | public function get($name, $ignoreErrors = false); 39 | 40 | /** 41 | * delete data from the cache 42 | * 43 | * @abstract 44 | * 45 | * @param string $name 46 | * @param bool $ignoreErrors 47 | * 48 | * @return boolean true if successful 49 | */ 50 | public function clear($name, $ignoreErrors = false); 51 | 52 | /** 53 | * check if the given name is cached 54 | * 55 | * @abstract 56 | * 57 | * @param string $name 58 | * 59 | * @return boolean true if cached 60 | */ 61 | public function isCached($name); 62 | } 63 | 64 | -------------------------------------------------------------------------------- /src/Format/JsFormat.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2010 Luracast 12 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 13 | * @link http://luracast.com/products/restler/ 14 | * 15 | */ 16 | class JsFormat extends JsonFormat 17 | { 18 | const MIME = 'text/javascript'; 19 | const EXTENSION = 'js'; 20 | 21 | public static $callbackMethodName = 'parseResponse'; 22 | public static $callbackOverrideQueryString = 'callback'; 23 | public static $includeHeaders = true; 24 | 25 | public function encode($data, $human_readable = false) 26 | { 27 | $r = array(); 28 | if (static::$includeHeaders) { 29 | $r['meta'] = array(); 30 | foreach (headers_list() as $header) { 31 | list($h, $v) = explode(': ', $header, 2); 32 | $r['meta'][$h] = $v; 33 | } 34 | } 35 | $r['data'] = $data; 36 | if (isset($_GET[static::$callbackOverrideQueryString])) { 37 | static::$callbackMethodName 38 | = (string) $_GET[static::$callbackOverrideQueryString]; 39 | } 40 | return static::$callbackMethodName . '(' 41 | . parent::encode($r, $human_readable) . ');'; 42 | } 43 | 44 | public function isReadable() 45 | { 46 | return false; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /public/examples/resources/getsource.php: -------------------------------------------------------------------------------- 1 | ' . htmlspecialchars($text) . ""); 17 | } else { 18 | die('no file specified'); 19 | } 20 | function strip_comments($fileStr) 21 | { 22 | $newStr = ''; 23 | $commentTokens = array(T_COMMENT); 24 | 25 | //if (defined('T_DOC_COMMENT')) 26 | //$commentTokens[] = T_DOC_COMMENT; // PHP 5 27 | 28 | $tokens = token_get_all($fileStr); 29 | $result = array(); 30 | foreach ($tokens as $token) { 31 | if (is_array($token)) { 32 | if (in_array($token[0], $commentTokens)) { 33 | if (!trim(end($result))) { 34 | array_pop($result); 35 | array_push($result, PHP_EOL); 36 | } 37 | continue; 38 | } 39 | 40 | $token = $token[1]; 41 | } 42 | 43 | $result [] = $token; 44 | } 45 | $newStr = implode('', $result); 46 | return preg_replace("/\n\n+/s", "\n", $newStr); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/Explorer/v2/client/lang/translator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Translator for documentation pages. 5 | * 6 | * To enable translation you should include one of language-files in your index.html 7 | * after . 8 | * For example - 9 | * 10 | * If you wish to translate some new texsts you should do two things: 11 | * 1. Add a new phrase pair ("New Phrase": "New Translation") into your language file (for example lang/ru.js). It will be great if you add it in other language files too. 12 | * 2. Mark that text it templates this way New Phrase or . 13 | * The main thing here is attribute data-sw-translate. Only inner html, title-attribute and value-attribute are going to translate. 14 | * 15 | */ 16 | window.SwaggerTranslator = { 17 | 18 | _words:[], 19 | 20 | translate: function(sel) { 21 | var $this = this; 22 | sel = sel || '[data-sw-translate]'; 23 | 24 | $(sel).each(function() { 25 | $(this).html($this._tryTranslate($(this).html())); 26 | 27 | $(this).val($this._tryTranslate($(this).val())); 28 | $(this).attr('title', $this._tryTranslate($(this).attr('title'))); 29 | }); 30 | }, 31 | 32 | _tryTranslate: function(word) { 33 | return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word; 34 | }, 35 | 36 | learn: function(wordsMap) { 37 | this._words = wordsMap; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /src/Format/DependentFormat.php: -------------------------------------------------------------------------------- 1 | packagist package name as an associative array 25 | * 26 | * @return array list of dependencies for the format 27 | */ 28 | public function getDependencyMap() 29 | { 30 | return array( 31 | static::EXTERNAL_CLASS => static::PACKAGE_NAME 32 | ); 33 | } 34 | 35 | protected function checkDependency($class = null) 36 | { 37 | if (empty($class)) { 38 | $class = key($this->getDependencyMap()); 39 | } 40 | if (!class_exists($class, true)) { 41 | $map = $this->getDependencyMap(); 42 | $package = $map[$class]; 43 | throw new RestException( 44 | 500, 45 | get_called_class() . ' has external dependency. Please run `composer require ' . 46 | $package . '` from the project root. Read https://getcomposer.org for more info' 47 | ); 48 | } 49 | } 50 | 51 | public function __construct() 52 | { 53 | $this->checkDependency(); 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /features/examples/_011_versioning.feature: -------------------------------------------------------------------------------- 1 | @example11 @versioning 2 | Feature: Testing Versioning 3 | 4 | Scenario: Access version 1 as default 5 | When I request "examples/_011_versioning/bmi?height=190" 6 | Then the response status code should be 200 7 | And the response is JSON 8 | And the type is "array" 9 | And the response has a "bmi" property 10 | And the "message" property equals "Normal weight" 11 | And the "metric.height" property equals "190 centimeters" 12 | 13 | Scenario: Access version 1 by url 14 | When I request "examples/_011_versioning/v1/bmi?height=190" 15 | Then the response status code should be 200 16 | And the response is JSON 17 | And the type is "array" 18 | And the response has a "bmi" property 19 | And the "message" property equals "Normal weight" 20 | And the "metric.height" property equals "190 centimeters" 21 | 22 | Scenario: Access version 2 by url and passing invalid argument 23 | When I request "examples/_011_versioning/v2/bmi?height=190" 24 | Then the response status code should be 400 25 | And the response is JSON 26 | And the type is "array" 27 | And the "error.message" property equals "Bad Request: invalid height unit" 28 | 29 | Scenario: Access version 2 by url 30 | When I request "examples/_011_versioning/v2/bmi?height=190cm" 31 | Then the response status code should be 200 32 | And the response is JSON 33 | And the type is "array" 34 | And the response has a "bmi" property 35 | And the "message" property equals "Normal weight" 36 | And the "metric.height" property equals "190 centimeters" 37 | -------------------------------------------------------------------------------- /public/examples/_008_documentation/index.php: -------------------------------------------------------------------------------- 1 | = 5.4 7 | Description: How to document and let your users explore your API. 8 | We have modified SwaggerUI to create 9 | [Restler API Explorer](https://github.com/Luracast/Restler-API-Explorer) 10 | which is used [here](explorer/index.html#!/authors-v1). 11 | 12 | [![Restler API Explorer](../resources/explorer1.png)](explorer/index.html#!/authors-v1) 13 | 14 | We are progressively improving the Authors class from CRUD example 15 | to Rate Limiting Example to show Best Practices and Restler 5 Features. 16 | 17 | Make sure you compare them to understand. 18 | 19 | Even though API Explorer is created with API consumers in mind, it will help the 20 | API developer with routing information and commenting assistance when our API 21 | class is not fully commented as in this example. This works only on the debug 22 | mode. Try changing rester to run in production mode (`$r = new Restler(true)`) 23 | 24 | > **Note:-** production mode writes human readable cache file for the routes in 25 | > the cache directory by default. So make sure cache folder has necessary 26 | > write permission. 27 | 28 | Happy Exploring! :) 29 | */ 30 | 31 | require_once '../../../restler.php'; 32 | use Luracast\Restler\Restler; 33 | 34 | $r = new Restler(); 35 | // comment the line above and uncomment the line below for production mode 36 | // $r = new Restler(true); 37 | 38 | $r->addAPIClass('improved\\Authors'); 39 | $r->addAPIClass('Explorer'); 40 | $r->handle(); 41 | -------------------------------------------------------------------------------- /src/Data/ApiMethodInfo.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2010 Luracast 12 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 13 | * @link http://luracast.com/products/restler/ 14 | * 15 | */ 16 | class ApiMethodInfo extends ValueObject 17 | { 18 | /** 19 | * @var string target url 20 | */ 21 | public $url; 22 | /** 23 | * @var string 24 | */ 25 | public $className; 26 | /** 27 | * @var string 28 | */ 29 | public $methodName; 30 | /** 31 | * @var array parameters to be passed to the api method 32 | */ 33 | public $parameters = array(); 34 | /** 35 | * @var array information on parameters in the form of array(name => index) 36 | */ 37 | public $arguments = array(); 38 | /** 39 | * @var array default values for parameters if any 40 | * in the form of array(index => value) 41 | */ 42 | public $defaults = array(); 43 | /** 44 | * @var array key => value pair of method meta information 45 | */ 46 | public $metadata = array(); 47 | /** 48 | * @var int access level 49 | * 0 - @public - available for all 50 | * 1 - @hybrid - both public and protected (enhanced info for authorized) 51 | * 2 - @protected comment - only for authenticated users 52 | * 3 - protected method - only for authenticated users 53 | */ 54 | public $accessLevel = 0; 55 | } -------------------------------------------------------------------------------- /public/examples/_010_access_control/AccessControl.php: -------------------------------------------------------------------------------- 1 | role for brevity 14 | $roles = array('12345' => 'user', '67890' => 'admin'); 15 | $userClass = Defaults::$userIdentifierClass; 16 | 17 | if (isset($_GET['api_key'])) { 18 | if (!array_key_exists($_GET['api_key'], $roles)) { 19 | $userClass::setCacheIdentifier($_GET['api_key']); 20 | return false; 21 | } 22 | } else { 23 | return false; 24 | } 25 | static::$role = $roles[$_GET['api_key']]; 26 | $userClass::setCacheIdentifier(static::$role); 27 | Defaults::$accessControlFunction = 'AccessControl::verifyAccess'; 28 | return static::$requires == static::$role || static::$role == 'admin'; 29 | } 30 | 31 | public function __getWWWAuthenticateString() 32 | { 33 | return 'Query name="api_key"'; 34 | } 35 | 36 | /** 37 | * @access private 38 | */ 39 | public static function verifyAccess(array $m) 40 | { 41 | $requires = 42 | isset($m['class']['AccessControl']['properties']['requires']) 43 | ? $m['class']['AccessControl']['properties']['requires'] 44 | : false; 45 | return $requires 46 | ? static::$role == 'admin' || static::$role == $requires 47 | : true; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /views/todo/index.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | {$title} 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |

    {$title}

    23 | 24 |

    25 | Go 26 | Back to the Examples »

    27 | 28 |
    29 | 30 |
      31 | {$_('include','todo/list.php','response')} 32 |
    33 | 34 | Add a Task 35 | 36 |
    37 | 38 | 39 |
    Are you sure you want to 40 | delete this task? 41 |
    42 | 43 | 44 |

    {$description}

    45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | TEMPLATE; 55 | -------------------------------------------------------------------------------- /views/todo/index.handlebar: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | {{ title }} 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |

    {{ title }}

    22 | 23 |

    24 | Go 25 | Back to the Examples »

    26 | 27 |
    28 | 29 |
      30 | {{# response }} 31 | {{> todo/list }} 32 | {{/ response }} 33 |
    34 | 35 | Add a Task 36 | 37 |
    38 | 39 | 40 |
    Are you sure you want to 41 | delete this task? 42 |
    43 | 44 |

    {{ description }}

    45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /views/todo/index.blade.php: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | {{ $title }} 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |

    {{ $title }}

    22 | 23 |

    24 | Go 25 | Back to the Examples »

    26 | 27 |
    28 | 29 |
      30 | @foreach ($response as $res) 31 | @include('todo.list', $res->jsonSerialize()) 32 | @endforeach 33 |
    34 | 35 | Add a Task 36 | 37 |
    38 | 39 | 40 |
    Are you sure you want to 41 | delete this task? 42 |
    43 | 44 |

    {{ $description }}

    45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /views/todo/index.twig: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | {{ title }} 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |

    {{ title }}

    22 | 23 |

    24 | Go 25 | Back to the Examples »

    26 | 27 |
    28 | 29 |
      30 | {% for res in response%} 31 | {{ include('todo/list.twig', res.jsonSerialize()) }} 32 | {% endfor %} 33 |
    34 | 35 | Add a Task 36 | 37 |
    38 | 39 | 40 |
    Are you sure you want to 41 | delete this task? 42 |
    43 | 44 |

    {{ description }}

    45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/Format/UrlEncodedFormat.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2010 Luracast 12 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 13 | * @link http://luracast.com/products/restler/ 14 | * 15 | */ 16 | class UrlEncodedFormat extends Format 17 | { 18 | const MIME = 'application/x-www-form-urlencoded'; 19 | const EXTENSION = 'post'; 20 | 21 | public function encode($data, $humanReadable = false) 22 | { 23 | return http_build_query(static::encoderTypeFix($data)); 24 | } 25 | 26 | public function decode($data) 27 | { 28 | parse_str($data, $r); 29 | return self::decoderTypeFix($r); 30 | } 31 | 32 | public static function encoderTypeFix(array $data) 33 | { 34 | foreach ($data as $k => $v) { 35 | if (is_bool($v)) { 36 | $data[$k] = $v = $v ? 'true' : 'false'; 37 | } elseif (is_array($v)) { 38 | $data[$k] = $v = static::decoderTypeFix($v); 39 | } 40 | } 41 | return $data; 42 | } 43 | 44 | public static function decoderTypeFix(array $data) 45 | { 46 | foreach ($data as $k => $v) { 47 | if ($v === 'true' || $v === 'false') { 48 | $data[$k] = $v = $v === 'true'; 49 | } elseif (is_array($v)) { 50 | $data[$k] = $v = static::decoderTypeFix($v); 51 | } elseif (empty($v) && $v != 0 && !($v === '')) { 52 | unset($data[$k]); 53 | } 54 | } 55 | return $data; 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /src/UI/Foundation5Form.php: -------------------------------------------------------------------------------- 1 | input.radio[name=$name# value=$value# type=radio checked=$selected# required=$required# disabled=$disabled#]+{$text#}'; 14 | const select = 'label{$label#}+select[id=$id# name=$name# required=$required#]>option[value]+option[value=$value# selected=$selected# disabled=$disabled#]{$text#}*options'; 15 | const submit = 'button.button[id=$id# type=submit disabled=$disabled#]{$label#}'; 16 | const fieldset = 'fieldset>legend{$label#}'; 17 | const checkbox = 'label>input[id=$id# name=$name# value=$value# type=checkbox checked=$selected# required=$required# autofocus=$autofocus# disabled=$disabled#]+{ $label#}'; 18 | //------------- TYPE BASED STYLES ---------------------// 19 | const checkbox_array = 'fieldset>legend{$label#}+label*options>input[name=$name# value=$value# type=checkbox checked=$selected# required=$required# autofocus=$autofocus#]+{ $text#}'; 20 | const select_array = 'label{$label#}+select[name=$name# required=$required# multiple style="height: auto;background-image: none; outline: inherit;"]>option[value=$value# selected=$selected#]{$text#}*options'; 21 | } 22 | -------------------------------------------------------------------------------- /src/Explorer/v1/client/css/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 */ 2 | html, 3 | body, 4 | div, 5 | span, 6 | applet, 7 | object, 8 | iframe, 9 | h1, 10 | h2, 11 | h3, 12 | h4, 13 | h5, 14 | h6, 15 | p, 16 | blockquote, 17 | pre, 18 | a, 19 | abbr, 20 | acronym, 21 | address, 22 | big, 23 | cite, 24 | code, 25 | del, 26 | dfn, 27 | em, 28 | img, 29 | ins, 30 | kbd, 31 | q, 32 | s, 33 | samp, 34 | small, 35 | strike, 36 | strong, 37 | sub, 38 | sup, 39 | tt, 40 | var, 41 | b, 42 | u, 43 | i, 44 | center, 45 | dl, 46 | dt, 47 | dd, 48 | ol, 49 | ul, 50 | li, 51 | fieldset, 52 | form, 53 | label, 54 | legend, 55 | table, 56 | caption, 57 | tbody, 58 | tfoot, 59 | thead, 60 | tr, 61 | th, 62 | td, 63 | article, 64 | aside, 65 | canvas, 66 | details, 67 | embed, 68 | figure, 69 | figcaption, 70 | footer, 71 | header, 72 | hgroup, 73 | menu, 74 | nav, 75 | output, 76 | ruby, 77 | section, 78 | summary, 79 | time, 80 | mark, 81 | audio, 82 | video { 83 | margin: 0; 84 | padding: 0; 85 | border: 0; 86 | font-size: 100%; 87 | font: inherit; 88 | vertical-align: baseline; 89 | } 90 | /* HTML5 display-role reset for older browsers */ 91 | article, 92 | aside, 93 | details, 94 | figcaption, 95 | figure, 96 | footer, 97 | header, 98 | hgroup, 99 | menu, 100 | nav, 101 | section { 102 | display: block; 103 | } 104 | body { 105 | line-height: 1; 106 | } 107 | ol, 108 | ul { 109 | list-style: none; 110 | } 111 | blockquote, 112 | q { 113 | quotes: none; 114 | } 115 | blockquote:before, 116 | blockquote:after, 117 | q:before, 118 | q:after { 119 | content: ''; 120 | content: none; 121 | } 122 | table { 123 | border-collapse: collapse; 124 | border-spacing: 0; 125 | } 126 | -------------------------------------------------------------------------------- /src/Explorer/v2/client/css/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 */ 2 | html, 3 | body, 4 | div, 5 | span, 6 | applet, 7 | object, 8 | iframe, 9 | h1, 10 | h2, 11 | h3, 12 | h4, 13 | h5, 14 | h6, 15 | p, 16 | blockquote, 17 | pre, 18 | a, 19 | abbr, 20 | acronym, 21 | address, 22 | big, 23 | cite, 24 | code, 25 | del, 26 | dfn, 27 | em, 28 | img, 29 | ins, 30 | kbd, 31 | q, 32 | s, 33 | samp, 34 | small, 35 | strike, 36 | strong, 37 | sub, 38 | sup, 39 | tt, 40 | var, 41 | b, 42 | u, 43 | i, 44 | center, 45 | dl, 46 | dt, 47 | dd, 48 | ol, 49 | ul, 50 | li, 51 | fieldset, 52 | form, 53 | label, 54 | legend, 55 | table, 56 | caption, 57 | tbody, 58 | tfoot, 59 | thead, 60 | tr, 61 | th, 62 | td, 63 | article, 64 | aside, 65 | canvas, 66 | details, 67 | embed, 68 | figure, 69 | figcaption, 70 | footer, 71 | header, 72 | hgroup, 73 | menu, 74 | nav, 75 | output, 76 | ruby, 77 | section, 78 | summary, 79 | time, 80 | mark, 81 | audio, 82 | video { 83 | margin: 0; 84 | padding: 0; 85 | border: 0; 86 | font-size: 100%; 87 | font: inherit; 88 | vertical-align: baseline; 89 | } 90 | /* HTML5 display-role reset for older browsers */ 91 | article, 92 | aside, 93 | details, 94 | figcaption, 95 | figure, 96 | footer, 97 | header, 98 | hgroup, 99 | menu, 100 | nav, 101 | section { 102 | display: block; 103 | } 104 | body { 105 | line-height: 1; 106 | } 107 | ol, 108 | ul { 109 | list-style: none; 110 | } 111 | blockquote, 112 | q { 113 | quotes: none; 114 | } 115 | blockquote:before, 116 | blockquote:after, 117 | q:before, 118 | q:after { 119 | content: ''; 120 | content: none; 121 | } 122 | table { 123 | border-collapse: collapse; 124 | border-spacing: 0; 125 | } 126 | -------------------------------------------------------------------------------- /features/examples/_002_minimal.feature: -------------------------------------------------------------------------------- 1 | @example2 @minimal 2 | Feature: Testing Minimal Example 3 | 4 | Scenario: Add using Default Values 5 | When I request "examples/_002_minimal/math/add" 6 | Then the response status code should be 200 7 | And the response is JSON 8 | And the type is "int" 9 | And the value equals 2 10 | 11 | Scenario: Add 5 and 10 12 | Given that "n1" is set to "5" 13 | And "n2" is set to "10" 14 | When I request "examples/_002_minimal/math/add{?n1,n2}" 15 | Then the response status code should be 200 16 | And the response is JSON 17 | And the type is "int" 18 | And the value equals 15 19 | 20 | Scenario: Verify Validation 21 | Given that "n1" is set to "NaN" 22 | When I request "examples/_002_minimal/math/add{?n1,n2}" 23 | Then the response status code should be 400 24 | And the response is JSON 25 | And the response has a "error" property 26 | 27 | Scenario: Multiply 28 | Given that "n1" is set to "10" 29 | And "n2" is set to "5" 30 | When I request "examples/_002_minimal/math/multiply/{n1}/{n2}" 31 | And the response is JSON 32 | And the response has a "result" property 33 | And the "result" property equals 50 34 | 35 | Scenario: Multiply without value 36 | When I request "examples/_002_minimal/math/multiply" 37 | Then the response status code should be 404 38 | And the response is JSON 39 | And the type is "array" 40 | And the response has a "error" property 41 | 42 | Scenario: Verify Validation for multiplication 43 | Given that "n1" is set to "NaN" 44 | And "n2" is set to "5" 45 | When I request "examples/_002_minimal/math/multiply/{n1}/{n2}" 46 | Then the response status code should be 400 47 | And the response is JSON 48 | And the response has a "error" property 49 | -------------------------------------------------------------------------------- /features/examples/_013_html.feature: -------------------------------------------------------------------------------- 1 | @example13 @html 2 | Feature: Testing Html 3 | 4 | Scenario: Resetting data to begin tests 5 | When I request "PATCH examples/_013_html/tasks/reset" 6 | Then the response status code should be 200 7 | And the response is JSON 8 | And the value equals true 9 | 10 | Scenario: Getting Html response 11 | When I request "examples/_013_html/tasks.html" 12 | Then the response status code should be 200 13 | And the response is HTML 14 | 15 | Scenario: Getting Json response 16 | When I request "examples/_013_html/tasks.json" 17 | Then the response status code should be 200 18 | And the response is JSON 19 | 20 | Scenario: Getting Html response for a tag 21 | When I request "examples/_013_html/tasks/1.html" 22 | Then the response status code should be 200 23 | And the response is HTML 24 | 25 | Scenario: Getting Json response for a tag 26 | When I request "examples/_013_html/tasks/2.json" 27 | Then the response status code should be 200 28 | And the response is JSON 29 | 30 | Scenario: Deleting a task 31 | Given that I want to delete a "Task" 32 | And its "id" is 1 33 | When I request "examples/_013_html/tasks/{id}.json" 34 | Then the response status code should be 200 35 | And the response should be JSON 36 | And the response has an "id" property 37 | 38 | Scenario: Getting Html response for a missing tag 39 | When I request "examples/_013_html/tasks/1.html" 40 | Then the response status code should be 404 41 | And the response is HTML 42 | 43 | Scenario: Getting Json response for a deleted tag 44 | When I request "examples/_013_html/tasks/1.json" 45 | Then the response status code should be 404 46 | And the response is JSON 47 | And the response has a "error" property 48 | 49 | 50 | -------------------------------------------------------------------------------- /public/examples/_015_oauth2_server/cache/b4/4f/d31d4fe40b2a78ec7d0795f97050.php: -------------------------------------------------------------------------------- 1 | parent = false; 11 | 12 | $this->blocks = array( 13 | ); 14 | } 15 | 16 | protected function doDisplay(array $context, array $blocks = array()) 17 | { 18 | // line 1 19 | if (array_key_exists("googleAnalyticsCode", $context)) { 20 | // line 2 21 | echo " 38 | "; 39 | } 40 | } 41 | 42 | public function getTemplateName() 43 | { 44 | return "oauth2/analytics.twig"; 45 | } 46 | 47 | public function isTraitable() 48 | { 49 | return false; 50 | } 51 | 52 | public function getDebugInfo() 53 | { 54 | return array ( 26 => 5, 21 => 2, 19 => 1,); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /features/examples/_012_vendor_mime.feature: -------------------------------------------------------------------------------- 1 | @example12 @versioning 2 | Feature: Testing Versioning with vendor MIME 3 | 4 | Scenario: Access version 1 by vendor media type 5 | Given that "Accept" header is set to "application/vnd.SomeVendor-v1+json" 6 | When I request "examples/_012_vendor_mime/bmi?height=190" 7 | Then the response status code should be 200 8 | And the response "Content-Type" header should be "application/vnd.SomeVendor-v1+json; charset=utf-8" 9 | And the response is JSON 10 | And the type is "array" 11 | And the response has a "bmi" property 12 | And the "message" property equals "Normal weight" 13 | And the "metric.height" property equals "190 centimeters" 14 | 15 | Scenario: Access version 2 by vendor media type and passing invalid argument 16 | Given that "Accept" header is set to "application/vnd.SomeVendor-v2+json" 17 | When I request "examples/_012_vendor_mime/bmi?height=190" 18 | Then the response status code should be 400 19 | And the response "Content-Type" header should be "application/vnd.SomeVendor-v2+json; charset=utf-8" 20 | And the response is JSON 21 | And the type is "array" 22 | And the "error.message" property equals "Bad Request: invalid height unit" 23 | 24 | Scenario: Access version 2 by vendor media type 25 | Given that "Accept" header is set to "application/vnd.SomeVendor-v2+json" 26 | When I request "examples/_012_vendor_mime/bmi?height=190cm" 27 | Then the response status code should be 200 28 | And the response "Content-Type" header should be "application/vnd.SomeVendor-v2+json; charset=utf-8" 29 | And the response is JSON 30 | And the type is "array" 31 | And the response has a "bmi" property 32 | And the "message" property equals "Normal weight" 33 | And the "metric.height" property equals "190 centimeters" 34 | -------------------------------------------------------------------------------- /src/UI/HtmlForm.php: -------------------------------------------------------------------------------- 1 | section>label{$label#}^input[id=$id# name=$name# value=$value# type=$type# required=$required# autofocus=$autofocus# placeholder=$default# accept=$accept# disabled=$disabled#]'; 11 | const password = self::input; 12 | const textarea = '.row>label{$label#}^textarea[id=$id# name=$name# required=$required# autofocus=$autofocus# placeholder=$default# rows=3 disabled=$disabled#]{$value#}'; 13 | const radio = '.row>section>label{$label#}^span>label*options>input[id=$id# name=$name# value=$value# type=radio checked=$selected# required=$required# disabled=$disabled#]+{ $text#}'; 14 | const select = '.row>label{$label#}^select[id=$id# name=$name# required=$required#]>option[value]+option[value=$value# selected=$selected# disabled=$disabled#]{$text#}*options'; 15 | const submit = '.row>label{   }^button[id=$id# type=submit disabled=$disabled#]{$label#}'; 16 | const fieldset = 'fieldset>legend{$label#}'; 17 | const checkbox = '.row>label>input[id=$id# name=$name# value=$value# type=checkbox checked=$selected# required=$required# autofocus=$autofocus# accept=$accept# disabled=$disabled#]+{$label#}'; 18 | //------------- TYPE BASED STYLES ---------------------// 19 | const checkbox_array = 'fieldset>legend{$label#}+section*options>label>input[name=$name# value=$value# type=checkbox checked=$selected# required=$required# autofocus=$autofocus# accept=$accept#]+{ $text#}'; 20 | const select_array = 'label{$label#}+select[name=$name# required=$required# multiple style="height: auto;background-image: none; outline: inherit;"]>option[value=$value# selected=$selected#]{$text#}*options'; 21 | } 22 | -------------------------------------------------------------------------------- /features/restler/annotations.feature: -------------------------------------------------------------------------------- 1 | @restler @annotation 2 | Feature: Annotations 3 | 4 | Scenario: @class should set the property correctly 5 | When I request "examples/_010_access_control/admin" 6 | Then the response status code should be 401 7 | 8 | Scenario: @cache should reflect in the header 9 | When I request "examples/_009_rate_limiting/authors" 10 | Then the response "Cache-Control" header should be "public, max-age=30, max-stale=3000, must-revalidate" 11 | 12 | Scenario: @expires should set correct time difference between Date and Expires headers 13 | When I request "examples/_009_rate_limiting/authors" 14 | Then the response "Expires" header should be Date+30 seconds 15 | 16 | Scenario: @status should set respective status code 17 | Given that I want to make a new "Author" 18 | And his "name" is "Superman" 19 | And his "email" is "super@man.world" 20 | When I request "examples/_009_rate_limiting/authors" 21 | Then the response status code should be 201 22 | 23 | Scenario: @throttle should correctly delay the response 24 | When I request "examples/_009_rate_limiting/authors" 25 | Then the response time should at least be 200 milliseconds 26 | 27 | Scenario: Normal call should default to RateLimiter class static values 28 | When I request "examples/_009_rate_limiting/authors/1" 29 | Then the response "X-RateLimit-Limit" header should be "10 per hour" 30 | 31 | Scenario: @class RateLimiter properties should reflect in the header 32 | When I request "examples/_009_rate_limiting/authors" 33 | Then the response "X-RateLimit-Limit" header should be "1 per second" 34 | 35 | Scenario: Normal call should default to RateLimiter class static values 36 | When I request "examples/_009_rate_limiting/authors/1" 37 | Then the response "X-RateLimit-Limit" header should be "10 per hour" 38 | 39 | -------------------------------------------------------------------------------- /public/examples/_011_versioning/v1/BMI.php: -------------------------------------------------------------------------------- 1 | bmi = round($kg / ($meter * $meter), 2); 39 | $lb = round($kg / 0.45359237, 2); 40 | 41 | if ($result->bmi < 18.5) { 42 | $result->message = 'Underweight'; 43 | } elseif ($result->bmi <= 24.9) { 44 | $result->message = 'Normal weight'; 45 | } elseif ($result->bmi <= 29.9) { 46 | $result->message = 'Overweight'; 47 | } else { 48 | $result->message = 'Obesity'; 49 | } 50 | $result->metric = array( 51 | 'height' => "$cm centimeters", 52 | 'weight' => "$weight kilograms" 53 | ); 54 | $result->imperial = array( 55 | 'height' => "$feet feet $inches inches", 56 | 'weight' => "$lb pounds" 57 | ); 58 | return $result; 59 | } 60 | } -------------------------------------------------------------------------------- /public/examples/_012_vendor_mime/SomeVendor/v1/BMI.php: -------------------------------------------------------------------------------- 1 | bmi = round($kg / ($meter * $meter), 2); 39 | $lb = round($kg / 0.45359237, 2); 40 | 41 | if ($result->bmi < 18.5) { 42 | $result->message = 'Underweight'; 43 | } elseif ($result->bmi <= 24.9) { 44 | $result->message = 'Normal weight'; 45 | } elseif ($result->bmi <= 29.9) { 46 | $result->message = 'Overweight'; 47 | } else { 48 | $result->message = 'Obesity'; 49 | } 50 | $result->metric = array( 51 | 'height' => "$cm centimeters", 52 | 'weight' => "$weight kilograms" 53 | ); 54 | $result->imperial = array( 55 | 'height' => "$feet feet $inches inches", 56 | 'weight' => "$lb pounds" 57 | ); 58 | return $result; 59 | } 60 | } -------------------------------------------------------------------------------- /src/Explorer/v2/client/lang/zh-cn.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"警告:已过时", 6 | "Implementation Notes":"实现备注", 7 | "Response Class":"响应类", 8 | "Status":"状态", 9 | "Parameters":"参数", 10 | "Parameter":"参数", 11 | "Value":"值", 12 | "Description":"描述", 13 | "Parameter Type":"参数类型", 14 | "Data Type":"数据类型", 15 | "Response Messages":"响应消息", 16 | "HTTP Status Code":"HTTP状态码", 17 | "Reason":"原因", 18 | "Response Model":"响应模型", 19 | "Request URL":"请求URL", 20 | "Response Body":"响应体", 21 | "Response Code":"响应码", 22 | "Response Headers":"响应头", 23 | "Hide Response":"隐藏响应", 24 | "Headers":"头", 25 | "Try it out!":"试一下!", 26 | "Show/Hide":"显示/隐藏", 27 | "List Operations":"显示操作", 28 | "Expand Operations":"展开操作", 29 | "Raw":"原始", 30 | "can't parse JSON. Raw result":"无法解析JSON. 原始结果", 31 | "Model Schema":"模型架构", 32 | "Model":"模型", 33 | "apply":"应用", 34 | "Username":"用户名", 35 | "Password":"密码", 36 | "Terms of service":"服务条款", 37 | "Created by":"创建者", 38 | "See more at":"查看更多:", 39 | "Contact the developer":"联系开发者", 40 | "api version":"api版本", 41 | "Response Content Type":"响应Content Type", 42 | "fetching resource":"正在获取资源", 43 | "fetching resource list":"正在获取资源列表", 44 | "Explore":"浏览", 45 | "Show Swagger Petstore Example Apis":"显示 Swagger Petstore 示例 Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"无法从服务器读取。可能没有正确设置access-control-origin。", 47 | "Please specify the protocol for":"请指定协议:", 48 | "Can't read swagger JSON from":"无法读取swagger JSON于", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"已加载资源信息。正在渲染Swagger UI", 50 | "Unable to read api":"无法读取api", 51 | "from path":"从路径", 52 | "server returned":"服务器返回" 53 | }); 54 | -------------------------------------------------------------------------------- /src/Data/ValueObject.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2010 Luracast 12 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 13 | * @link http://luracast.com/products/restler/ 14 | * 15 | */ 16 | class ValueObject implements iValueObject 17 | { 18 | 19 | public function __toString() 20 | { 21 | return ' new ' . get_called_class() . '() '; 22 | } 23 | 24 | public static function __set_state(array $properties) 25 | { 26 | $class = get_called_class(); 27 | $instance = new $class (); 28 | $vars = get_object_vars($instance); 29 | foreach ($properties as $property => $value) { 30 | if (property_exists($instance, $property)) { 31 | // see if the property is accessible 32 | if (array_key_exists($property, $vars)) { 33 | $instance->{$property} = $value; 34 | } else { 35 | $method = 'set' . ucfirst($property); 36 | if (method_exists($instance, $method)) { 37 | call_user_func(array( 38 | $instance, 39 | $method 40 | ), $value); 41 | } 42 | } 43 | } 44 | } 45 | return $instance; 46 | } 47 | 48 | public function __toArray() 49 | { 50 | $r = get_object_vars($this); 51 | $methods = get_class_methods($this); 52 | foreach ($methods as $m) { 53 | if (substr($m, 0, 3) === 'get') { 54 | $r [lcfirst(substr($m, 3))] = @$this->{$m} (); 55 | } 56 | } 57 | return $r; 58 | } 59 | 60 | } 61 | 62 | -------------------------------------------------------------------------------- /public/examples/_014_oauth2_client/cache/b4/4f/d31d4fe40b2a78ec7d0795f97050.php: -------------------------------------------------------------------------------- 1 | parent = false; 11 | 12 | $this->blocks = array( 13 | ); 14 | } 15 | 16 | protected function doDisplay(array $context, array $blocks = array()) 17 | { 18 | // line 1 19 | if (array_key_exists("googleAnalyticsCode", $context)) { 20 | // line 2 21 | echo " 38 | "; 39 | } 40 | } 41 | 42 | public function getTemplateName() 43 | { 44 | return "oauth2/analytics.twig"; 45 | } 46 | 47 | public function isTraitable() 48 | { 49 | return false; 50 | } 51 | 52 | public function getDebugInfo() 53 | { 54 | return array ( 26 => 5, 19 => 1, 117 => 56, 114 => 55, 92 => 34, 83 => 27, 80 => 26, 71 => 57, 69 => 55, 63 => 51, 61 => 26, 56 => 23, 53 => 22, 51 => 21, 40 => 14, 35 => 13, 21 => 2,); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /features/examples/_007_crud.feature: -------------------------------------------------------------------------------- 1 | @example7 @crud 2 | Feature: Testing CRUD Example 3 | 4 | Scenario: Creating new Author by POSTing vars 5 | Given that I want to make a new "Author" 6 | And his "name" is "Chris" 7 | And his "email" is "chris@world.com" 8 | When I request "examples/_007_crud/authors" 9 | Then the response status code should be 200 10 | And the response should be JSON 11 | And the response has a "id" property 12 | 13 | Scenario: Creating new Author with JSON 14 | Given that I want to make a new "Author" 15 | And his "name" is "Chris" 16 | And his "email" is "chris@world.com" 17 | And the request is sent as JSON 18 | When I request "examples/_007_crud/authors" 19 | Then the response status code should be 200 20 | And the response should be JSON 21 | And the response has a "id" property 22 | 23 | Scenario: Updating Author with JSON 24 | Given that I want to update "Author" 25 | And his "name" is "Jac" 26 | And his "email" is "jac@wright.com" 27 | And his "id" is 1 28 | And the request is sent as JSON 29 | When I request "examples/_007_crud/authors/{id}" 30 | Then the response status code should be 200 31 | And the response should be JSON 32 | And the response has a "id" property 33 | 34 | Scenario: Given url is valid for other http method(s) 35 | Given that I want to update "Author" 36 | And his "name" is "Jac" 37 | And his "email" is "jac@wright.com" 38 | And his "id" is 1 39 | And the request is sent as JSON 40 | When I request "examples/_007_crud/authors" 41 | Then the response status code should be 405 42 | And the response "Allow" header should be "GET, POST" 43 | 44 | Scenario: Deleting Author 45 | Given that I want to delete an "Author" 46 | And his "id" is 1 47 | When I request "examples/_007_crud/authors/{id}" 48 | Then the response status code should be 200 49 | And the response should be JSON 50 | And the response has an "id" property -------------------------------------------------------------------------------- /src/Explorer/Info.php: -------------------------------------------------------------------------------- 1 | static::$title, 25 | 'description' => static::$description, 26 | 'termsOfServiceUrl' => static::$termsOfServiceUrl, 27 | 'contact' => static::$contactEmail, 28 | 'license' => static::$license, 29 | 'licenseUrl' => static::$licenseUrl, 30 | ); 31 | case 2: 32 | case 3: 33 | return array( 34 | 'title' => static::$title, 35 | 'description' => static::$description, 36 | 'termsOfService' => static::$termsOfServiceUrl, 37 | 'contact' => array( 38 | 'name' => static::$contactName, 39 | 'email' => static::$contactEmail, 40 | 'url' => static::$contactUrl, 41 | ), 42 | 'license' => array( 43 | 'name' => static::$license, 44 | 'url' => static::$licenseUrl, 45 | ), 46 | ); 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/iIdentifyUser.php: -------------------------------------------------------------------------------- 1 | 12 | * @copyright 2010 Luracast 13 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 14 | * @link http://luracast.com/products/restler/ 15 | * 16 | */ 17 | interface iIdentifyUser 18 | { 19 | /** 20 | * A way to uniquely identify the current api consumer 21 | * 22 | * When his user id is known it should be used otherwise ip address 23 | * can be used 24 | * 25 | * @param bool $includePlatform Should we consider user alone or should 26 | * consider the application/platform/device 27 | * as well for generating unique id 28 | * 29 | * @return string 30 | */ 31 | public static function getUniqueIdentifier($includePlatform = false); 32 | 33 | /** 34 | * User identity to be used for caching purpose 35 | * 36 | * When the dynamic cache service places an object in the cache, it needs to 37 | * label it with a unique identifying string known as a cache ID. This 38 | * method gives that identifier 39 | * 40 | * @return string 41 | */ 42 | public static function getCacheIdentifier(); 43 | 44 | /** 45 | * Authentication classes should call this method 46 | * 47 | * @param string $id user id as identified by the authentication classes 48 | * 49 | * @return void 50 | */ 51 | public static function setUniqueIdentifier($id); 52 | 53 | /** 54 | * User identity for caching purpose 55 | * 56 | * In a role based access control system this will be based on role 57 | * 58 | * @param $id 59 | * 60 | * @return void 61 | */ 62 | public static function setCacheIdentifier($id); 63 | } -------------------------------------------------------------------------------- /public/examples/common/SessionDataProvider.php: -------------------------------------------------------------------------------- 1 | reset(); 12 | } 13 | } 14 | private function pk () 15 | { 16 | return $_SESSION['pk'] ++; 17 | } 18 | private function find ($id) 19 | { 20 | foreach ($_SESSION['rs'] as $index => $rec) { 21 | if ($rec['id'] == $id) { 22 | return $index; 23 | } 24 | } 25 | return FALSE; 26 | } 27 | function get ($id) 28 | { 29 | $index = $this->find($id); 30 | if ($index === FALSE) 31 | return FALSE; 32 | return $_SESSION['rs'][$index]; 33 | } 34 | function getAll () 35 | { 36 | return $_SESSION['rs']; 37 | } 38 | function insert ($rec) 39 | { 40 | $rec['id'] = $this->pk(); 41 | array_push($_SESSION['rs'], $rec); 42 | return $rec; 43 | } 44 | function update ($id, $rec) 45 | { 46 | $index = $this->find($id); 47 | if ($index === FALSE) 48 | return FALSE; 49 | $rec['id'] = $id; 50 | $_SESSION['rs'][$index] = $rec; 51 | return $rec; 52 | } 53 | function delete ($id) 54 | { 55 | $index = $this->find($id); 56 | if ($index === FALSE) 57 | return FALSE; 58 | $record = array_splice($_SESSION['rs'], $index, 1); 59 | return array_shift($record); 60 | } 61 | 62 | function reset() 63 | { 64 | /** install initial data **/ 65 | $_SESSION['pk'] = 5; 66 | $_SESSION['rs'] = array( 67 | array('id' => 1, 'name' => 'Jac Wright', 68 | 'email' => 'jacwright@gmail.com'), 69 | array('id' => 2, 'name' => 'Arul Kumaran', 70 | 'email' => 'arul@luracast.com')); 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /src/Explorer/v2/client/lang/ja.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"警告: 廃止予定", 6 | "Implementation Notes":"実装メモ", 7 | "Response Class":"レスポンスクラス", 8 | "Status":"ステータス", 9 | "Parameters":"パラメータ群", 10 | "Parameter":"パラメータ", 11 | "Value":"値", 12 | "Description":"説明", 13 | "Parameter Type":"パラメータタイプ", 14 | "Data Type":"データタイプ", 15 | "Response Messages":"レスポンスメッセージ", 16 | "HTTP Status Code":"HTTPステータスコード", 17 | "Reason":"理由", 18 | "Response Model":"レスポンスモデル", 19 | "Request URL":"リクエストURL", 20 | "Response Body":"レスポンスボディ", 21 | "Response Code":"レスポンスコード", 22 | "Response Headers":"レスポンスヘッダ", 23 | "Hide Response":"レスポンスを隠す", 24 | "Headers":"ヘッダ", 25 | "Try it out!":"実際に実行!", 26 | "Show/Hide":"表示/非表示", 27 | "List Operations":"操作一覧", 28 | "Expand Operations":"操作の展開", 29 | "Raw":"Raw", 30 | "can't parse JSON. Raw result":"JSONへ解釈できません. 未加工の結果", 31 | "Model Schema":"モデルスキーマ", 32 | "Model":"モデル", 33 | "apply":"実行", 34 | "Username":"ユーザ名", 35 | "Password":"パスワード", 36 | "Terms of service":"サービス利用規約", 37 | "Created by":"Created by", 38 | "See more at":"See more at", 39 | "Contact the developer":"開発者に連絡", 40 | "api version":"APIバージョン", 41 | "Response Content Type":"レスポンス コンテンツタイプ", 42 | "fetching resource":"リソースの取得", 43 | "fetching resource list":"リソース一覧の取得", 44 | "Explore":"Explore", 45 | "Show Swagger Petstore Example Apis":"SwaggerペットストアAPIの表示", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"サーバから読み込めません. 適切なaccess-control-origin設定を持っていない可能性があります.", 47 | "Please specify the protocol for":"プロトコルを指定してください", 48 | "Can't read swagger JSON from":"次からswagger JSONを読み込めません", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"リソース情報の読み込みが完了しました. Swagger UIを描画しています", 50 | "Unable to read api":"APIを読み込めません", 51 | "from path":"次のパスから", 52 | "server returned":"サーバからの返答" 53 | }); 54 | -------------------------------------------------------------------------------- /public/examples/_015_oauth2_server/Auth/db/rebuild_db.php: -------------------------------------------------------------------------------- 1 | setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 21 | $db->exec('CREATE TABLE oauth_clients (client_id TEXT, client_secret TEXT, redirect_uri TEXT)'); 22 | $db->exec('CREATE TABLE oauth_access_tokens (access_token TEXT, client_id TEXT, user_id TEXT, expires TIMESTAMP, scope TEXT)'); 23 | $db->exec('CREATE TABLE oauth_authorization_codes (authorization_code TEXT, client_id TEXT, user_id TEXT, redirect_uri TEXT, expires TIMESTAMP, scope TEXT, id_token TEXT)'); 24 | $db->exec('CREATE TABLE oauth_refresh_tokens (refresh_token TEXT, client_id TEXT, user_id TEXT, expires TIMESTAMP, scope TEXT)'); 25 | $db->exec('CREATE TABLE oauth_scopes (scope TEXT, is_default BOOLEAN);'); 26 | $db->exec('CREATE TABLE oauth_users (username VARCHAR(255) NOT NULL, password VARCHAR(2000), first_name VARCHAR(255), last_name VARCHAR(255), CONSTRAINT username_pk PRIMARY KEY (username));'); 27 | $db->exec('CREATE TABLE oauth_public_keys (client_id VARCHAR(80), public_key VARCHAR(8000), private_key VARCHAR(8000), encryption_algorithm VARCHAR(80) DEFAULT "RS256")'); 28 | 29 | // add test data 30 | $db->exec('INSERT INTO oauth_clients (client_id, client_secret) VALUES ("demoapp", "demopass")'); 31 | $db->exec(sprintf('INSERT INTO oauth_users (username, password) VALUES ("demouser", "%s")', sha1("testpass"))); 32 | 33 | chmod($dbfile, 0777); 34 | // $db->exec('INSERT INTO oauth_access_tokens (access_token, client_id) VALUES ("testtoken", "Some Client")'); 35 | // $db->exec('INSERT INTO oauth_authorization_codes (authorization_code, client_id) VALUES ("testcode", "Some Client")'); 36 | -------------------------------------------------------------------------------- /features/examples/_003_multiformat.feature: -------------------------------------------------------------------------------- 1 | @example3 @multiformat 2 | Feature: Testing Multi-format Example 3 | 4 | Scenario: Default format, when not specified 5 | When I request "examples/_003_multiformat/bmi" 6 | Then the response status code should be 200 7 | And the response is JSON 8 | And the type is "array" 9 | And the response has a "bmi" property 10 | And the "message" property equals "Obesity" 11 | 12 | Scenario: Use XML format when specified as extension 13 | When I request "examples/_003_multiformat/bmi.xml" 14 | Then the response status code should be 200 15 | And the response is XML 16 | And the type is "array" 17 | And the response has a "bmi" property 18 | And the "message" property equals "Obesity" 19 | 20 | Scenario: Use XML format through content negotiation 21 | When I accept "text/html; q=1.0, application/xml; q=0.8, application/json; q=0.5, */*; q=0.1" 22 | And accept language "de; q=1.0, en; q=0.5" 23 | And request "examples/_003_multiformat/bmi" 24 | Then the response status code should be 200 25 | And the response is XML 26 | And the type is "array" 27 | And the response has a "bmi" property 28 | And the "message" property equals "Obesity" 29 | 30 | Scenario: Use XML format through content negotiation even with reverse order 31 | When I accept "*/*; q=0.1, application/json; q=0.5, application/xml; q=0.8, text/html; q=1.0" 32 | And accept language "de; q=1.0, en; q=0.5" 33 | And request "examples/_003_multiformat/bmi" 34 | Then the response status code should be 200 35 | And the response is XML 36 | And the type is "array" 37 | And the response has a "bmi" property 38 | And the "message" property equals "Obesity" 39 | 40 | Scenario: Correct weight and height should yield 'Normal weight' as result 41 | Given that "height" is set to 180 42 | And "weight" is set to 80 43 | When I request "examples/_003_multiformat/bmi.xml{?height,weight}" 44 | Then the response status code should be 200 45 | And the "message" property equals "Normal weight" 46 | -------------------------------------------------------------------------------- /features/examples/_006_routing.feature: -------------------------------------------------------------------------------- 1 | @example6 @routing 2 | Feature: Testing Routing Example 3 | 4 | Scenario: Testing So Many Ways 5 | Given that "p2" is set to 2 6 | When I request "examples/_006_routing/api/somanyways/1{?p2}" 7 | Then the response status code should be 200 8 | And the response is JSON 9 | And the type is "string" 10 | And the value equals "you have called Api::soManyWays()" 11 | 12 | Scenario: Testing So Many Ways with two params 13 | When I request "examples/_006_routing/api/somanyways/1/2" 14 | Then the response status code should be 200 15 | And the response is JSON 16 | And the type is "string" 17 | And the value equals "you have called Api::soManyWays()" 18 | 19 | Scenario: Testing So Many Ways with three params 20 | When I request "examples/_006_routing/api/somanyways/1/2/3" 21 | Then the response status code should be 200 22 | And the response is JSON 23 | And the type is "string" 24 | And the value equals "you have called Api::soManyWays()" 25 | 26 | Scenario: Testing So Many Ways with more params 27 | When I request "examples/_006_routing/api/somanyways/1/2/3/4" 28 | Then the response status code should be 404 29 | And the response is JSON 30 | 31 | Scenario: Ignoring required parameter should throw 400 32 | When I request "examples/_006_routing/api/what/ever/you/want" 33 | Then the response status code should be 400 34 | And the response is JSON 35 | 36 | Scenario: Testing Wildcard route with 7 parameters 37 | When I request "examples/_006_routing/api/all/1/2/3/4/5/6/7" 38 | Then the response status code should be 200 39 | And the response is JSON 40 | And the type is "string" 41 | And the value equals "you have called Api::allIsMine(1, 2, 3, 4, 5, 6, 7)" 42 | 43 | Scenario: Testing Wildcard route with 0 parameters 44 | When I request "examples/_006_routing/api/all" 45 | Then the response status code should be 200 46 | And the response is JSON 47 | And the type is "string" 48 | And the value equals "you have called Api::allIsMine()" 49 | -------------------------------------------------------------------------------- /FORMS.md: -------------------------------------------------------------------------------- 1 | # Forms 2 | 3 | Forms class generates html forms from http method and target url. 4 | 5 | Following attributes can be used for customizing the generated forms. 6 | 7 | ## @label 8 | 9 | ### With @param 10 | 11 | **Syntax:** 12 | 13 | @param type $name [Description] {@label Custom Name} 14 | 15 | **Example:** 16 | 17 | @param string $name [Description] {@label Customer's Name} 18 | 19 | Restler automatically creates a label for each param by using camelCasing and underscore in parameter names. For example `$firstName`, `$first_name` to `First Name`. If you want to override and specify a label yourself use the above annotation. 20 | 21 | ------------ 22 | 23 | ### With @return 24 | 25 | **Syntax:** 26 | 27 | @return type {@label Custom Name} 28 | 29 | **Example:** 30 | 31 | @return array {@label Sign In} 32 | 33 | Restler by default uses `Submit` as the default text for form submit buttons. You can customize that using the above annotation. 34 | 35 | 36 | ## @field 37 | 38 | **Syntax:** 39 | 40 | @param type $name [Description] {@field InputType} 41 | 42 | **Example:** 43 | 44 | @param int $age [Description] {@field number} {@min 6} {@max 22} 45 | 46 | Html field type used for capturing the value. 47 | Some possible values are, 48 | - input 49 | - checkbox (for boolean) 50 | - radio (requires @choice) 51 | - password 52 | - select (requires @choice) 53 | - text 54 | - hidden 55 | 56 | When not specified, it will try to guess the field type 57 | 58 | 59 | ## @message 60 | 61 | **Syntax:** 62 | 63 | @param type $name [Description] {@message text} 64 | 65 | **Example:** 66 | 67 | @param int $age [Description] {@message age restriction requires age between 6 and 22} {@min 6} {@max 22} 68 | 69 | Custom error message to display when validation fails. 70 | 71 | ## Emmet Templates 72 | 73 | ### @form, @input, @textarea, @radio, @select, @submit, and @fieldset 74 | 75 | Allows you to customize how a form element rendering from the selected form style. 76 | Use Emmet syntax for that purpose. Take a look at FormStyles.php for an example. 77 | 78 | -------------------------------------------------------------------------------- /public/examples/_009_rate_limiting/index.php: -------------------------------------------------------------------------------- 1 | = 5.4 7 | Description: How to Rate Limit API access using a Filter class that implements 8 | `iFilter` interface. 9 | 10 | This example also shows how to use Defaults class to customize defaults, how to create your own 11 | iCache implementation, and how to make a hybrid filter class that behaves differently 12 | when the user is Authenticated 13 | 14 | [![Restler API Explorer](../resources/explorer1.png)](explorer/index.html#!/authors-v1) 15 | 16 | Key in `r3rocks` as the API key in the Explorer to see how rate limit changes 17 | 18 | We are progressively improving the Authors class from CRUD example 19 | to show Best Practices and Restler 5 Features. 20 | 21 | Make sure you compare them to understand. 22 | 23 | > **Note:-** 24 | > 25 | > 1. Using session variables as DB and Cache is useless for real life and wrong. We are using it 26 | > Only for demo purpose. Since API Explorer is browser based it works well with that. 27 | > 28 | > 2. We are using Author.php to document return type of `GET authors/{id}` using `@return` comment 29 | 30 | If you have hit the API Rate Limit or screwed up the Authors DB, you can easily reset by deleting 31 | PHP_SESSION cookie using the Developer Tools in your browser. 32 | 33 | Helpers: Author 34 | 35 | Footer: 36 | *[Author.php]: _009_rate_limiting/Author.php 37 | */ 38 | 39 | use Luracast\Restler\Defaults; 40 | use Luracast\Restler\Explorer; 41 | use Luracast\Restler\Filter\RateLimit; 42 | 43 | require_once '../../../restler.php'; 44 | 45 | //used only for demo, comment the following line 46 | Defaults::$cacheClass = 'SessionCache'; 47 | //set extreme value for quick testing 48 | RateLimit::setLimit('hour', 10); 49 | 50 | Explorer\v2\Explorer::$hideProtected = false; 51 | 52 | $r = new Restler(); 53 | 54 | $r->addAPIClass('ratelimited\\Authors'); 55 | $r->addAPIClass('Explorer'); 56 | $r->addFilterClass('RateLimit'); 57 | $r->addAuthenticationClass('KeyAuth'); 58 | $r->handle(); 59 | -------------------------------------------------------------------------------- /public/examples/_003_multiformat/index.php: -------------------------------------------------------------------------------- 1 | = 5.4 7 | Description: This BMI calculator service shows how you can serve data in different 8 | formats using Restler. This example uses JsonFormat (default) and XmlFormat. 9 | 10 | First format specified in `Restler::setSupportedFormats` is used as the 11 | default format when client does not specify the format. 12 | 13 | Client can specify the format either using extension like .json or specify 14 | the MIME type in HTTP Accept Header. 15 | 16 | When we make the request from the browser we will get xml when we 17 | skip the extension because XML is one of the requested formats specified in 18 | the HTTP Accept Header where as a AJAX request or CURL will return JSON. 19 | 20 | Example 1: GET bmi returns 21 | 22 | 23 | 24 | 31.77 25 | Obesity 26 | 27 | 162.6 centimeter 28 | 84 kilograms 29 | 30 | 31 | 5 feet 4 inches 32 | 185.19 pounds 33 | 34 | 35 | 36 | Example 2: GET bmi.xml returns 37 | 38 | 39 | 40 | 31.77 41 | Obesity 42 | 43 | 162.6 centimeter 44 | 84 kilograms 45 | 46 | 47 | 5 feet 4 inches 48 | 185.19 pounds 49 | 50 | 51 | 52 | Example 3: GET bmi.json returns 53 | 54 | { 55 | "bmi": 31.77, 56 | "message": "Obesity", 57 | "metric": { 58 | "height": "162.6 centimeter", 59 | "weight": "84 kilograms" 60 | }, 61 | "imperial": { 62 | "height": "5 feet 4 inches", 63 | "weight": "185.19 pounds" 64 | } 65 | } 66 | */ 67 | require_once '../../../restler.php'; 68 | use Luracast\Restler\Restler; 69 | 70 | $r = new Restler(); 71 | $r->setSupportedFormats('JsonFormat', 'XmlFormat'); 72 | $r->addAPIClass('BMI'); 73 | $r->handle(); 74 | 75 | -------------------------------------------------------------------------------- /src/UI/Bootstrap3Form.php: -------------------------------------------------------------------------------- 1 | label{$label#}+input.form-control[id=$id# name=$name# value=$value# type=$type# required=$required# autofocus=$autofocus# placeholder=$default# accept=$accept# disabled=$disabled#]+small.help-block>{$message#}'; 11 | const password = self::input; 12 | const textarea = '.form-group>label{$label#}+textarea.form-control[id=$id# name=$name# required=$required# autofocus=$autofocus# placeholder=$default# rows=3 disabled=$disabled#]{$value#}+small.help-block>{$message#}'; 13 | const radio = 'fieldset>legend{$label#}>.radio*options>label>input.radio[name=$name# value=$value# type=radio checked=$selected# required=$required# disabled=$disabled#]{$text#}+p.help-block>{$message#}'; 14 | const select = '.form-group>label{$label#}+select.form-control[id=$id# name=$name# multiple=$multiple# required=$required#]>option[value]+option[value=$value# selected=$selected# disabled=$disabled#]{$text#}*options'; 15 | const submit = 'button.btn.btn-primary[id=$id# type=submit]{$label#} disabled=$disabled#'; 16 | const fieldset = 'fieldset>legend{$label#}'; 17 | const checkbox = '.checkbox>label>input[id=$id# name=$name# value=$value# type=checkbox checked=$selected# required=$required# autofocus=$autofocus# disabled=$disabled#]+{$label#}^p.help-block>{$error#}'; 18 | //------------- TYPE BASED STYLES ---------------------// 19 | const checkbox_array = 'fieldset>legend{$label#}>.checkbox*options>label>input[name=$name# value=$value# type=checkbox checked=$selected# required=$required#]{$text#}'; 20 | const select_array = '.form-group>label{$label#}+select.form-control[name=$name# multiple=$multiple# required=$required#] size=$options#>option[value=$value# selected=$selected#]{$text#}*options'; 21 | //------------- CUSTOM STYLES ---------------------// 22 | const radio_inline = '.form-group>label{$label# :  }+label.radio-inline*options>input.radio[name=$name# value=$value# type=radio checked=$selected# required=$required#]+{$text#}'; 23 | } 24 | -------------------------------------------------------------------------------- /features/tests/param/minmax.feature: -------------------------------------------------------------------------------- 1 | @param @min @max 2 | Feature: Minimum and Maximum 3 | 4 | Scenario Outline: Int 5 | When I request "tests/param/minmax/int/" 6 | Then the response status code should be 200 7 | And the response is JSON 8 | And the type is "int" 9 | And the value equals 10 | 11 | Examples: 12 | | number | 13 | | 2 | 14 | | 3 | 15 | | 4 | 16 | | 5 | 17 | 18 | Scenario: Int lower than the minimum 19 | When I request "tests/param/minmax/int/1" 20 | Then the response status code should be 400 21 | And the response is JSON 22 | 23 | Scenario: Int higher than maximum 24 | When I request "tests/param/minmax/int/6" 25 | Then the response status code should be 400 26 | And the response is JSON 27 | 28 | Scenario: String 29 | When I request "tests/param/minmax/string/me" 30 | Then the response status code should be 200 31 | And the response is JSON 32 | And the type is "string" 33 | And the value equals "me" 34 | 35 | Scenario: Short String 36 | When I request "tests/param/minmax/string/i" 37 | Then the response status code should be 400 38 | And the response is JSON 39 | 40 | Scenario: Lengthy String 41 | When I request "tests/param/minmax/string/arulkumaran" 42 | Then the response status code should be 400 43 | And the response is JSON 44 | 45 | Scenario Outline: Array 46 | Given that I send 47 | And the request is sent as JSON 48 | When I request "tests/param/minmax/array" 49 | Then the response status code should be 200 50 | And the response is JSON 51 | 52 | Examples: 53 | | data | 54 | | [1,2] | 55 | | [1,2,3] | 56 | | [1,2,3,4] | 57 | | [1,2,3,4,5] | 58 | 59 | Scenario Outline: Array out of range 60 | Given that I send 61 | And the request is sent as JSON 62 | When I request "tests/param/minmax/array" 63 | Then the response status code should be 400 64 | And the response is JSON 65 | 66 | Examples: 67 | | data | 68 | | [] | 69 | | [1] | 70 | | [1,2,3,4,5,6] | 71 | | [1,2,3,4,5,6,7] | 72 | | [1,2,3,4,5,6,7,8] | 73 | -------------------------------------------------------------------------------- /src/Redirect.php: -------------------------------------------------------------------------------- 1 | 12 | * @copyright 2010 Luracast 13 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 14 | * @link http://luracast.com/products/restler/ 15 | * 16 | */ 17 | class Redirect 18 | { 19 | /** 20 | * Redirect to given url 21 | * 22 | * @param string $url relative path or full url 23 | * @param array $params associative array of query parameters 24 | * @param array $flashData associative array of properties to be set in $_SESSION for one time use 25 | * @param int $status http status code to send the response with ideally 301 or 302 26 | * 27 | * @return array 28 | */ 29 | public static function to($url, array $params = array(), array $flashData = array(), $status = 302) 30 | { 31 | $url = ltrim($url, '/'); 32 | /** @var $r Restler */ 33 | $r = Scope::get('Restler'); 34 | $base = $r->getBaseUrl() . '/'; 35 | if (0 !== strpos($url, 'http')) { 36 | $url = $base . $url; 37 | } 38 | if (!empty($flashData) || $base . $r->url !== $url || Util::getRequestMethod() != 'GET') { 39 | if ($r->responseFormat instanceof JsonFormat) { 40 | return array('redirect' => $url); 41 | } 42 | if (!empty($params)) { 43 | $url .= '?' . http_build_query($params); 44 | } 45 | Flash::set($flashData); 46 | header( 47 | "{$_SERVER['SERVER_PROTOCOL']} $status " . 48 | (isset(RestException::$codes[$status]) ? RestException::$codes[$status] : '') 49 | ); 50 | header("Location: $url"); 51 | die(''); 52 | } 53 | 54 | return array(); 55 | } 56 | 57 | /** 58 | * Redirect back to the previous page 59 | * 60 | * Makes use of http referrer for redirection 61 | * 62 | * @return array 63 | */ 64 | public static function back() 65 | { 66 | return static::to($_SERVER['HTTP_REFERER']); 67 | } 68 | } -------------------------------------------------------------------------------- /public/examples/_014_oauth2_client/cache/e0/91/88a66f88d48558825932c7326987.php: -------------------------------------------------------------------------------- 1 | parent = $this->env->loadTemplate("oauth2/client/base.twig"); 11 | 12 | $this->blocks = array( 13 | 'content' => array($this, 'block_content'), 14 | ); 15 | } 16 | 17 | protected function doGetParent(array $context) 18 | { 19 | return "oauth2/client/base.twig"; 20 | } 21 | 22 | protected function doDisplay(array $context, array $blocks = array()) 23 | { 24 | $this->parent->display($context, array_merge($this->blocks, $blocks)); 25 | } 26 | 27 | // line 3 28 | public function block_content($context, array $blocks = array()) 29 | { 30 | // line 4 31 | echo "

    Demo App

    32 |

    33 | We would like to use your information in order to integrate with your friends, 34 | use your personal information for nefarious purposes, and to make your life better somehow. 35 |

    36 |

    37 | Click below to integrate with that service you belong to: 38 |

    39 | env, $this->getAttribute($_response_, "authorize_url"), "html", null, true); 43 | echo "?response_type=code&client_id=demoapp&redirect_uri="; 44 | if (isset($context["response"])) { $_response_ = $context["response"]; } else { $_response_ = null; } 45 | echo twig_escape_filter($this->env, twig_urlencode_filter($this->getAttribute($_response_, "authorize_redirect_url")), "html", null, true); 46 | echo "\">Authorize 47 | "; 48 | } 49 | 50 | public function getTemplateName() 51 | { 52 | return "oauth2/client/index.twig"; 53 | } 54 | 55 | public function isTraitable() 56 | { 57 | return false; 58 | } 59 | 60 | public function getDebugInfo() 61 | { 62 | return array ( 41 => 12, 31 => 4, 28 => 3,); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /features/tests/param/minmaxfix.feature: -------------------------------------------------------------------------------- 1 | @param @min @max @fix 2 | Feature: Minimum and Maximum with Fix 3 | 4 | Scenario Outline: Int 5 | When I request "tests/param/minmaxfix/int/" 6 | Then the response status code should be 200 7 | And the response is JSON 8 | And the type is "int" 9 | And the response equals 10 | 11 | Examples: 12 | | number | expected | 13 | | 0 | 2 | 14 | | 1 | 2 | 15 | | 2 | 2 | 16 | | 3 | 3 | 17 | | 4 | 4 | 18 | | 5 | 5 | 19 | | 6 | 5 | 20 | | 7 | 5 | 21 | 22 | Scenario Outline: String 23 | Given that I send {"string":} 24 | And the request is sent as JSON 25 | When I request "tests/param/minmaxfix/string" 26 | Then the response status code should be 200 27 | And the response is JSON 28 | And the type is "string" 29 | And the response equals 30 | 31 | Examples: 32 | | string | expected | 33 | | "a" | "aa" | 34 | | "ab" | "ab" | 35 | | "abc" | "abc" | 36 | | "abcd" | "abcd" | 37 | | "abcde" | "abcde" | 38 | | "abcdef" | "abcde" | 39 | | "abcdefg" | "abcde" | 40 | | "abcdefh" | "abcde" | 41 | 42 | 43 | Scenario Outline: Array out of maximum range 44 | Given that I send 45 | And the request is sent as JSON 46 | When I request "tests/param/minmaxfix/array" 47 | Then the response status code should be 200 48 | And the response is JSON 49 | And the response equals 50 | 51 | Examples: 52 | | array | expected | 53 | | [1,2] | [1,2] | 54 | | [1,2,3] | [1,2,3] | 55 | | [1,2,3,4] | [1,2,3,4] | 56 | | [1,2,3,4,5] | [1,2,3,4,5] | 57 | | [1,2,3,4,5,6] | [1,2,3,4,5] | 58 | | [1,2,3,4,5,6,7] | [1,2,3,4,5] | 59 | | [1,2,3,4,5,6,7,8] | [1,2,3,4,5] | 60 | 61 | Scenario Outline: Array short of minimum is not expected 62 | Given that I send 63 | And the request is sent as JSON 64 | When I request "tests/param/minmaxfix/array" 65 | Then the response status code should be 400 66 | And the response is JSON 67 | 68 | Examples: 69 | | array | 70 | | [] | 71 | | [1] | 72 | -------------------------------------------------------------------------------- /src/Compose.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2010 Luracast 12 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 13 | * @link http://luracast.com/products/restler/ 14 | * 15 | */ 16 | class Compose implements iCompose 17 | { 18 | /** 19 | * @var bool When restler is not running in production mode, this value will 20 | * be checked to include the debug information on error response 21 | */ 22 | public static $includeDebugInfo = true; 23 | /** 24 | * Current Restler instance 25 | * Injected at runtime 26 | * 27 | * @var Restler 28 | */ 29 | public $restler; 30 | 31 | /** 32 | * Result of an api call is passed to this method 33 | * to create a standard structure for the data 34 | * 35 | * @param mixed $result can be a primitive or array or object 36 | * 37 | * @return mixed 38 | */ 39 | public function response($result) 40 | { 41 | //TODO: check Defaults::language and change result accordingly 42 | return $result; 43 | } 44 | 45 | /** 46 | * When the api call results in RestException this method 47 | * will be called to return the error message 48 | * 49 | * @param RestException $exception exception that has reasons for failure 50 | * 51 | * @return array 52 | */ 53 | public function message(RestException $exception) 54 | { 55 | //TODO: check Defaults::language and change result accordingly 56 | $r = array( 57 | 'error' => array( 58 | 'code' => $exception->getCode(), 59 | 'message' => $exception->getErrorMessage(), 60 | ) + $exception->getDetails() 61 | ); 62 | if (!Scope::get('Restler')->getProductionMode() && self::$includeDebugInfo) { 63 | $r += array( 64 | 'debug' => array( 65 | 'source' => $exception->getSource(), 66 | 'stages' => $exception->getStages(), 67 | ) 68 | ); 69 | } 70 | return $r; 71 | } 72 | } -------------------------------------------------------------------------------- /public/examples/_013_html/Tasks.php: -------------------------------------------------------------------------------- 1 | db) { 17 | $this->setDB(new TasksInSession()); 18 | } 19 | HtmlFormat::$data['title'] = 'What\'s Next on Restler 5?'; 20 | HtmlFormat::$data['description'] = 'What should we focus on as the next?'; 21 | } 22 | 23 | private function setDB(iTasks $db) 24 | { 25 | $this->db = $db; 26 | } 27 | 28 | /** 29 | * @view todo/index 30 | */ 31 | function index() 32 | { 33 | return $this->db->getAll(); 34 | } 35 | 36 | /** 37 | * Get task by id 38 | * 39 | * @param int $id 40 | * 41 | * @return \DB\Task 42 | * 43 | * @view todo/list {@value response} 44 | */ 45 | function get($id) 46 | { 47 | return $this->db->get($id); 48 | } 49 | 50 | /** 51 | * Create new task 52 | * 53 | * @param string $text {@from body} 54 | * 55 | * @return \DB\Task 56 | * 57 | * @view todo/list {@value response} 58 | */ 59 | function post($text) 60 | { 61 | return $this->db->insert(compact('text')); 62 | } 63 | 64 | /** 65 | * @param int $id 66 | * @param string $text {@from body} 67 | * @param int $position {@from body} 68 | * 69 | * @return \DB\Task 70 | * 71 | * @view todo/list {@value response} 72 | */ 73 | function patch($id, $text = null, $position = null) 74 | { 75 | return $this->db->update($id, compact('text', 'position')); 76 | } 77 | 78 | /** 79 | * delete a task by id 80 | * 81 | * @param int $id 82 | * 83 | * @return \DB\Task 84 | * 85 | * @view todo/list {@value response} 86 | */ 87 | function delete($id) 88 | { 89 | return $this->db->delete($id); 90 | } 91 | 92 | /** 93 | * reset for tests 94 | */ 95 | function patchReset() 96 | { 97 | $this->db->reset(); 98 | return true; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/Explorer/v2/client/lang/tr.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Uyarı: Deprecated", 6 | "Implementation Notes":"Gerçekleştirim Notları", 7 | "Response Class":"Dönen Sınıf", 8 | "Status":"Statü", 9 | "Parameters":"Parametreler", 10 | "Parameter":"Parametre", 11 | "Value":"Değer", 12 | "Description":"Açıklama", 13 | "Parameter Type":"Parametre Tipi", 14 | "Data Type":"Veri Tipi", 15 | "Response Messages":"Dönüş Mesajı", 16 | "HTTP Status Code":"HTTP Statü Kodu", 17 | "Reason":"Gerekçe", 18 | "Response Model":"Dönüş Modeli", 19 | "Request URL":"İstek URL", 20 | "Response Body":"Dönüş İçeriği", 21 | "Response Code":"Dönüş Kodu", 22 | "Response Headers":"Dönüş Üst Bilgileri", 23 | "Hide Response":"Dönüşü Gizle", 24 | "Headers":"Üst Bilgiler", 25 | "Try it out!":"Dene!", 26 | "Show/Hide":"Göster/Gizle", 27 | "List Operations":"Operasyonları Listele", 28 | "Expand Operations":"Operasyonları Aç", 29 | "Raw":"Ham", 30 | "can't parse JSON. Raw result":"JSON çözümlenemiyor. Ham sonuç", 31 | "Model Schema":"Model Şema", 32 | "Model":"Model", 33 | "apply":"uygula", 34 | "Username":"Kullanıcı Adı", 35 | "Password":"Parola", 36 | "Terms of service":"Servis şartları", 37 | "Created by":"Oluşturan", 38 | "See more at":"Daha fazlası için", 39 | "Contact the developer":"Geliştirici ile İletişime Geçin", 40 | "api version":"api versiyon", 41 | "Response Content Type":"Dönüş İçerik Tipi", 42 | "fetching resource":"kaynak getiriliyor", 43 | "fetching resource list":"kaynak listesi getiriliyor", 44 | "Explore":"Keşfet", 45 | "Show Swagger Petstore Example Apis":"Swagger Petstore Örnek Api'yi Gör", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Sunucudan okuma yapılamıyor. Sunucu access-control-origin ayarlarınızı kontrol edin.", 47 | "Please specify the protocol for":"Lütfen istenen adres için protokol belirtiniz", 48 | "Can't read swagger JSON from":"Swagger JSON bu kaynaktan okunamıyor", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Kaynak baglantısı tamamlandı. Swagger UI gösterime hazırlanıyor", 50 | "Unable to read api":"api okunamadı", 51 | "from path":"yoldan", 52 | "server returned":"sunucuya dönüldü" 53 | }); 54 | -------------------------------------------------------------------------------- /features/restler/negotiation-format.feature: -------------------------------------------------------------------------------- 1 | @restler 2 | Feature: Content Negotiation - Media Type 3 | 4 | Scenario: One with more `q` should be selected, q = 1 when not defined 5 | Given that "Accept" header is set to "application/json;q=0.8,application/xml" 6 | When I request "examples/_003_multiformat/bmi" 7 | Then the response status code should be 200 8 | And the response is XML 9 | And the type is "array" 10 | 11 | Scenario: One with more `q` should be selected 12 | Given that "Accept" header is set to "application/json;q=0.8,application/xml;q=0.4" 13 | When I request "examples/_003_multiformat/bmi" 14 | Then the response status code should be 200 15 | And the response is JSON 16 | And the type is "array" 17 | 18 | Scenario: Choose first format when both are OK 19 | Given that "Accept" header is set to "application/xml,application/json" 20 | When I request "examples/_003_multiformat/bmi" 21 | Then the response status code should be 200 22 | And the response is XML 23 | And the type is "array" 24 | And the response has a "bmi" property 25 | 26 | Scenario: Choose first format when both are OK 27 | Given that "Accept" header is set to "application/json,application/xml" 28 | When I request "examples/_003_multiformat/bmi" 29 | Then the response status code should be 200 30 | And the response is JSON 31 | And the type is "array" 32 | And the response has a "bmi" property 33 | 34 | Scenario: JSON format by extension 35 | When I request "examples/_003_multiformat/bmi.json" 36 | Then the response status code should be 200 37 | And the response is JSON 38 | 39 | Scenario: XML format by extension 40 | When I request "examples/_003_multiformat/bmi.xml" 41 | Then the response status code should be 200 42 | And the response is XML 43 | And the type is "array" 44 | 45 | Scenario: XML format by Accept Header 46 | Given that "Accept" header is set to "application/xml" 47 | When I request "examples/_003_multiformat/bmi" 48 | Then the response status code should be 200 49 | And the response is XML 50 | And the type is "array" 51 | 52 | Scenario: Extension should be preferred when both are specified 53 | Given that "Accept" header is set to "application/json" 54 | When I request "examples/_003_multiformat/bmi.xml" 55 | Then the response status code should be 200 56 | And the response is XML 57 | And the type is "array" -------------------------------------------------------------------------------- /src/Explorer/v2/client/lang/pl.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Uwaga: Wycofane", 6 | "Implementation Notes":"Uwagi Implementacji", 7 | "Response Class":"Klasa Odpowiedzi", 8 | "Status":"Status", 9 | "Parameters":"Parametry", 10 | "Parameter":"Parametr", 11 | "Value":"Wartość", 12 | "Description":"Opis", 13 | "Parameter Type":"Typ Parametru", 14 | "Data Type":"Typ Danych", 15 | "Response Messages":"Wiadomości Odpowiedzi", 16 | "HTTP Status Code":"Kod Statusu HTTP", 17 | "Reason":"Przyczyna", 18 | "Response Model":"Model Odpowiedzi", 19 | "Request URL":"URL Wywołania", 20 | "Response Body":"Treść Odpowiedzi", 21 | "Response Code":"Kod Odpowiedzi", 22 | "Response Headers":"Nagłówki Odpowiedzi", 23 | "Hide Response":"Ukryj Odpowiedź", 24 | "Headers":"Nagłówki", 25 | "Try it out!":"Wypróbuj!", 26 | "Show/Hide":"Pokaż/Ukryj", 27 | "List Operations":"Lista Operacji", 28 | "Expand Operations":"Rozwiń Operacje", 29 | "Raw":"Nieprzetworzone", 30 | "can't parse JSON. Raw result":"nie można przetworzyć pliku JSON. Nieprzetworzone dane", 31 | "Model Schema":"Schemat Modelu", 32 | "Model":"Model", 33 | "apply":"użyj", 34 | "Username":"Nazwa użytkownika", 35 | "Password":"Hasło", 36 | "Terms of service":"Warunki używania", 37 | "Created by":"Utworzone przez", 38 | "See more at":"Zobacz więcej na", 39 | "Contact the developer":"Kontakt z deweloperem", 40 | "api version":"wersja api", 41 | "Response Content Type":"Typ Zasobu Odpowiedzi", 42 | "fetching resource":"ładowanie zasobu", 43 | "fetching resource list":"ładowanie listy zasobów", 44 | "Explore":"Eksploruj", 45 | "Show Swagger Petstore Example Apis":"Pokaż Przykładowe Api Swagger Petstore", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Brak połączenia z serwerem. Może on nie mieć odpowiednich ustawień access-control-origin.", 47 | "Please specify the protocol for":"Proszę podać protokół dla", 48 | "Can't read swagger JSON from":"Nie można odczytać swagger JSON z", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Ukończono Ładowanie Informacji o Zasobie. Renderowanie Swagger UI", 50 | "Unable to read api":"Nie można odczytać api", 51 | "from path":"ze ścieżki", 52 | "server returned":"serwer zwrócił" 53 | }); 54 | -------------------------------------------------------------------------------- /src/Explorer/v2/client/lang/pt.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Aviso: Depreciado", 6 | "Implementation Notes":"Notas de Implementação", 7 | "Response Class":"Classe de resposta", 8 | "Status":"Status", 9 | "Parameters":"Parâmetros", 10 | "Parameter":"Parâmetro", 11 | "Value":"Valor", 12 | "Description":"Descrição", 13 | "Parameter Type":"Tipo de parâmetro", 14 | "Data Type":"Tipo de dados", 15 | "Response Messages":"Mensagens de resposta", 16 | "HTTP Status Code":"Código de status HTTP", 17 | "Reason":"Razão", 18 | "Response Model":"Modelo resposta", 19 | "Request URL":"URL requisição", 20 | "Response Body":"Corpo da resposta", 21 | "Response Code":"Código da resposta", 22 | "Response Headers":"Cabeçalho da resposta", 23 | "Headers":"Cabeçalhos", 24 | "Hide Response":"Esconder resposta", 25 | "Try it out!":"Tente agora!", 26 | "Show/Hide":"Mostrar/Esconder", 27 | "List Operations":"Listar operações", 28 | "Expand Operations":"Expandir operações", 29 | "Raw":"Cru", 30 | "can't parse JSON. Raw result":"Falha ao analisar JSON. Resulto cru", 31 | "Model Schema":"Modelo esquema", 32 | "Model":"Modelo", 33 | "apply":"Aplicar", 34 | "Username":"Usuário", 35 | "Password":"Senha", 36 | "Terms of service":"Termos do serviço", 37 | "Created by":"Criado por", 38 | "See more at":"Veja mais em", 39 | "Contact the developer":"Contate o desenvolvedor", 40 | "api version":"Versão api", 41 | "Response Content Type":"Tipo de conteúdo da resposta", 42 | "fetching resource":"busca recurso", 43 | "fetching resource list":"buscando lista de recursos", 44 | "Explore":"Explorar", 45 | "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Não é possível ler do servidor. Pode não ter as apropriadas configurações access-control-origin", 47 | "Please specify the protocol for":"Por favor especifique o protocolo", 48 | "Can't read swagger JSON from":"Não é possível ler o JSON Swagger de", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Carregar informação de recurso finalizada. Renderizando Swagger UI", 50 | "Unable to read api":"Não foi possível ler api", 51 | "from path":"do caminho", 52 | "server returned":"servidor retornou" 53 | }); 54 | -------------------------------------------------------------------------------- /src/Explorer/v2/client/lang/en.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Warning: Deprecated", 6 | "Implementation Notes":"Implementation Notes", 7 | "Response Class":"Response Class", 8 | "Status":"Status", 9 | "Parameters":"Parameters", 10 | "Parameter":"Parameter", 11 | "Value":"Value", 12 | "Description":"Description", 13 | "Parameter Type":"Parameter Type", 14 | "Data Type":"Data Type", 15 | "Response Messages":"Response Messages", 16 | "HTTP Status Code":"HTTP Status Code", 17 | "Reason":"Reason", 18 | "Response Model":"Response Model", 19 | "Request URL":"Request URL", 20 | "Response Body":"Response Body", 21 | "Response Code":"Response Code", 22 | "Response Headers":"Response Headers", 23 | "Hide Response":"Hide Response", 24 | "Headers":"Headers", 25 | "Try it out!":"Try it out!", 26 | "Show/Hide":"Show/Hide", 27 | "List Operations":"List Operations", 28 | "Expand Operations":"Expand Operations", 29 | "Raw":"Raw", 30 | "can't parse JSON. Raw result":"can't parse JSON. Raw result", 31 | "Model Schema":"Model Schema", 32 | "Model":"Model", 33 | "Click to set as parameter value":"Click to set as parameter value", 34 | "apply":"apply", 35 | "Username":"Username", 36 | "Password":"Password", 37 | "Terms of service":"Terms of service", 38 | "Created by":"Created by", 39 | "See more at":"See more at", 40 | "Contact the developer":"Contact the developer", 41 | "api version":"api version", 42 | "Response Content Type":"Response Content Type", 43 | "Parameter content type:":"Parameter content type:", 44 | "fetching resource":"fetching resource", 45 | "fetching resource list":"fetching resource list", 46 | "Explore":"Explore", 47 | "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", 48 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Can't read from server. It may not have the appropriate access-control-origin settings.", 49 | "Please specify the protocol for":"Please specify the protocol for", 50 | "Can't read swagger JSON from":"Can't read swagger JSON from", 51 | "Finished Loading Resource Information. Rendering Swagger UI":"Finished Loading Resource Information. Rendering Swagger UI", 52 | "Unable to read api":"Unable to read api", 53 | "from path":"from path", 54 | "server returned":"server returned" 55 | }); 56 | -------------------------------------------------------------------------------- /src/Explorer/v2/client/lang/ru.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Предупреждение: Устарело", 6 | "Implementation Notes":"Заметки", 7 | "Response Class":"Пример ответа", 8 | "Status":"Статус", 9 | "Parameters":"Параметры", 10 | "Parameter":"Параметр", 11 | "Value":"Значение", 12 | "Description":"Описание", 13 | "Parameter Type":"Тип параметра", 14 | "Data Type":"Тип данных", 15 | "HTTP Status Code":"HTTP код", 16 | "Reason":"Причина", 17 | "Response Model":"Структура ответа", 18 | "Request URL":"URL запроса", 19 | "Response Body":"Тело ответа", 20 | "Response Code":"HTTP код ответа", 21 | "Response Headers":"Заголовки ответа", 22 | "Hide Response":"Спрятать ответ", 23 | "Headers":"Заголовки", 24 | "Response Messages":"Что может прийти в ответ", 25 | "Try it out!":"Попробовать!", 26 | "Show/Hide":"Показать/Скрыть", 27 | "List Operations":"Операции кратко", 28 | "Expand Operations":"Операции подробно", 29 | "Raw":"В сыром виде", 30 | "can't parse JSON. Raw result":"Не удается распарсить ответ:", 31 | "Model Schema":"Структура", 32 | "Model":"Описание", 33 | "Click to set as parameter value":"Нажмите, чтобы испльзовать в качестве значения параметра", 34 | "apply":"применить", 35 | "Username":"Имя пользователя", 36 | "Password":"Пароль", 37 | "Terms of service":"Условия использования", 38 | "Created by":"Разработано", 39 | "See more at":"Еще тут", 40 | "Contact the developer":"Связаться с разработчиком", 41 | "api version":"Версия API", 42 | "Response Content Type":"Content Type ответа", 43 | "Parameter content type:":"Content Type параметра:", 44 | "fetching resource":"Получение ресурса", 45 | "fetching resource list":"Получение ресурсов", 46 | "Explore":"Показать", 47 | "Show Swagger Petstore Example Apis":"Показать примеры АПИ", 48 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Не удается получить ответ от сервера. Возможно, проблема с настройками доступа", 49 | "Please specify the protocol for":"Пожалуйста, укажите протокол для", 50 | "Can't read swagger JSON from":"Не получается прочитать swagger json из", 51 | "Finished Loading Resource Information. Rendering Swagger UI":"Загрузка информации о ресурсах завершена. Рендерим", 52 | "Unable to read api":"Не удалось прочитать api", 53 | "from path":"по адресу", 54 | "server returned":"сервер сказал" 55 | }); 56 | -------------------------------------------------------------------------------- /src/Explorer/v2/client/lang/es.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Advertencia: Obsoleto", 6 | "Implementation Notes":"Notas de implementación", 7 | "Response Class":"Clase de la Respuesta", 8 | "Status":"Status", 9 | "Parameters":"Parámetros", 10 | "Parameter":"Parámetro", 11 | "Value":"Valor", 12 | "Description":"Descripción", 13 | "Parameter Type":"Tipo del Parámetro", 14 | "Data Type":"Tipo del Dato", 15 | "Response Messages":"Mensajes de la Respuesta", 16 | "HTTP Status Code":"Código de Status HTTP", 17 | "Reason":"Razón", 18 | "Response Model":"Modelo de la Respuesta", 19 | "Request URL":"URL de la Solicitud", 20 | "Response Body":"Cuerpo de la Respuesta", 21 | "Response Code":"Código de la Respuesta", 22 | "Response Headers":"Encabezados de la Respuesta", 23 | "Hide Response":"Ocultar Respuesta", 24 | "Try it out!":"Pruébalo!", 25 | "Show/Hide":"Mostrar/Ocultar", 26 | "List Operations":"Listar Operaciones", 27 | "Expand Operations":"Expandir Operaciones", 28 | "Raw":"Crudo", 29 | "can't parse JSON. Raw result":"no puede parsear el JSON. Resultado crudo", 30 | "Model Schema":"Esquema del Modelo", 31 | "Model":"Modelo", 32 | "apply":"aplicar", 33 | "Username":"Nombre de usuario", 34 | "Password":"Contraseña", 35 | "Terms of service":"Términos de Servicio", 36 | "Created by":"Creado por", 37 | "See more at":"Ver más en", 38 | "Contact the developer":"Contactar al desarrollador", 39 | "api version":"versión de la api", 40 | "Response Content Type":"Tipo de Contenido (Content Type) de la Respuesta", 41 | "fetching resource":"buscando recurso", 42 | "fetching resource list":"buscando lista del recurso", 43 | "Explore":"Explorar", 44 | "Show Swagger Petstore Example Apis":"Mostrar Api Ejemplo de Swagger Petstore", 45 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"No se puede leer del servidor. Tal vez no tiene la configuración de control de acceso de origen (access-control-origin) apropiado.", 46 | "Please specify the protocol for":"Por favor, especificar el protocola para", 47 | "Can't read swagger JSON from":"No se puede leer el JSON de swagger desde", 48 | "Finished Loading Resource Information. Rendering Swagger UI":"Finalizada la carga del recurso de Información. Mostrando Swagger UI", 49 | "Unable to read api":"No se puede leer la api", 50 | "from path":"desde ruta", 51 | "server returned":"el servidor retornó" 52 | }); 53 | -------------------------------------------------------------------------------- /src/Explorer/v2/client/lang/fr.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Avertissement : Obsolète", 6 | "Implementation Notes":"Notes d'implementation", 7 | "Response Class":"Classe de la réponse", 8 | "Status":"Statut", 9 | "Parameters":"Paramètres", 10 | "Parameter":"Paramètre", 11 | "Value":"Valeur", 12 | "Description":"Description", 13 | "Parameter Type":"Type du paramètre", 14 | "Data Type":"Type de données", 15 | "Response Messages":"Messages de la réponse", 16 | "HTTP Status Code":"Code de statut HTTP", 17 | "Reason":"Raison", 18 | "Response Model":"Modèle de réponse", 19 | "Request URL":"URL appelée", 20 | "Response Body":"Corps de la réponse", 21 | "Response Code":"Code de la réponse", 22 | "Response Headers":"En-têtes de la réponse", 23 | "Hide Response":"Cacher la réponse", 24 | "Headers":"En-têtes", 25 | "Try it out!":"Testez !", 26 | "Show/Hide":"Afficher/Masquer", 27 | "List Operations":"Liste des opérations", 28 | "Expand Operations":"Développer les opérations", 29 | "Raw":"Brut", 30 | "can't parse JSON. Raw result":"impossible de décoder le JSON. Résultat brut", 31 | "Model Schema":"Définition du modèle", 32 | "Model":"Modèle", 33 | "apply":"appliquer", 34 | "Username":"Nom d'utilisateur", 35 | "Password":"Mot de passe", 36 | "Terms of service":"Conditions de service", 37 | "Created by":"Créé par", 38 | "See more at":"Voir plus sur", 39 | "Contact the developer":"Contacter le développeur", 40 | "api version":"version de l'api", 41 | "Response Content Type":"Content Type de la réponse", 42 | "fetching resource":"récupération de la ressource", 43 | "fetching resource list":"récupération de la liste de ressources", 44 | "Explore":"Explorer", 45 | "Show Swagger Petstore Example Apis":"Montrer les Apis de l'exemple Petstore de Swagger", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Impossible de lire à partir du serveur. Il se peut que les réglages access-control-origin ne soient pas appropriés.", 47 | "Please specify the protocol for":"Veuillez spécifier un protocole pour", 48 | "Can't read swagger JSON from":"Impossible de lire le JSON swagger à partir de", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Chargement des informations terminé. Affichage de Swagger UI", 50 | "Unable to read api":"Impossible de lire l'api", 51 | "from path":"à partir du chemin", 52 | "server returned":"réponse du serveur" 53 | }); 54 | -------------------------------------------------------------------------------- /src/Explorer/v2/client/lang/it.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Attenzione: Deprecato", 6 | "Implementation Notes":"Note di implementazione", 7 | "Response Class":"Classe della risposta", 8 | "Status":"Stato", 9 | "Parameters":"Parametri", 10 | "Parameter":"Parametro", 11 | "Value":"Valore", 12 | "Description":"Descrizione", 13 | "Parameter Type":"Tipo di parametro", 14 | "Data Type":"Tipo di dato", 15 | "Response Messages":"Messaggi della risposta", 16 | "HTTP Status Code":"Codice stato HTTP", 17 | "Reason":"Motivo", 18 | "Response Model":"Modello di risposta", 19 | "Request URL":"URL della richiesta", 20 | "Response Body":"Corpo della risposta", 21 | "Response Code":"Oggetto della risposta", 22 | "Response Headers":"Intestazioni della risposta", 23 | "Hide Response":"Nascondi risposta", 24 | "Try it out!":"Provalo!", 25 | "Show/Hide":"Mostra/Nascondi", 26 | "List Operations":"Mostra operazioni", 27 | "Expand Operations":"Espandi operazioni", 28 | "Raw":"Grezzo (raw)", 29 | "can't parse JSON. Raw result":"non è possibile parsare il JSON. Risultato grezzo (raw).", 30 | "Model Schema":"Schema del modello", 31 | "Model":"Modello", 32 | "apply":"applica", 33 | "Username":"Nome utente", 34 | "Password":"Password", 35 | "Terms of service":"Condizioni del servizio", 36 | "Created by":"Creato da", 37 | "See more at":"Informazioni aggiuntive:", 38 | "Contact the developer":"Contatta lo sviluppatore", 39 | "api version":"versione api", 40 | "Response Content Type":"Tipo di contenuto (content type) della risposta", 41 | "fetching resource":"recuperando la risorsa", 42 | "fetching resource list":"recuperando lista risorse", 43 | "Explore":"Esplora", 44 | "Show Swagger Petstore Example Apis":"Mostra le api di esempio di Swagger Petstore", 45 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Non è possibile leggere dal server. Potrebbe non avere le impostazioni di controllo accesso origine (access-control-origin) appropriate.", 46 | "Please specify the protocol for":"Si prega di specificare il protocollo per", 47 | "Can't read swagger JSON from":"Impossibile leggere JSON swagger da:", 48 | "Finished Loading Resource Information. Rendering Swagger UI":"Lettura informazioni risorse termianta. Swagger UI viene mostrata", 49 | "Unable to read api":"Impossibile leggere la api", 50 | "from path":"da cartella", 51 | "server returned":"il server ha restituito" 52 | }); 53 | -------------------------------------------------------------------------------- /views/oauth2/server/header.html: -------------------------------------------------------------------------------- 1 | 53 | -------------------------------------------------------------------------------- /views/oauth2/client/base.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | {% include 'oauth2/analytics.twig' %} 22 | {% include 'oauth2/github.twig' %} 23 | 24 |
    25 |
    26 | {% block header %} 27 |
    28 |

    Restler 3

    29 |

    OAuth 2 Demo App

    30 |
    31 | 50 | {% endblock %} 51 |
    52 | 53 |
    54 |
    55 | {% block content %} 56 | {% endblock %} 57 |
    58 |
    59 |
    60 | 61 | 62 | --------------------------------------------------------------------------------