Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: RESTful-Drupal/restful
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 7.x-2.x
Choose a base ref
...
head repository: RESTful-Drupal/restful
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: multiple-return
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
Loading
Showing with 1,508 additions and 395 deletions.
  1. +64 −31 .travis.yml
  2. +11 −7 README.md
  3. +76 −1 docs/api_url.md
  4. +3 −0 docs/documentation.md
  5. +5 −3 docs/plugin.md
  6. +2 −6 exceptions/RestfulBadRequestException.php
  7. +7 −0 exceptions/RestfulException.php
  8. +2 −6 exceptions/RestfulFloodException.php
  9. +2 −6 exceptions/RestfulForbiddenException.php
  10. +2 −6 exceptions/RestfulGoneException.php
  11. +2 −6 exceptions/RestfulNotFoundException.php
  12. +2 −6 exceptions/RestfulNotImplementedException.php
  13. +2 −6 exceptions/RestfulServerConfigurationException.php
  14. +2 −6 exceptions/RestfulServiceUnavailable.php
  15. +2 −6 exceptions/RestfulUnauthorizedException.php
  16. +2 −6 exceptions/RestfulUnprocessableEntityException.php
  17. +3 −7 exceptions/RestfulUnsupportedMediaTypeException.php
  18. +4 −0 includes/RestfulManager.php
  19. +6 −3 modules/restful_angular_example/components/restful-app/bower.json
  20. +40 −35 modules/restful_angular_example/components/restful-app/dist/restful-app.js
  21. +8 −1 modules/restful_angular_example/components/restful-app/dist/views/form.html
  22. +36 −32 modules/restful_angular_example/components/restful-app/src/controllers/form.js
  23. +8 −1 modules/restful_angular_example/components/restful-app/src/views/form.html
  24. +7 −8 modules/restful_angular_example/restful_angular_example.module
  25. +54 −0 ...s/restful_example/plugins/restful/db_query/node_user/1.0/RestfulExampleNodeUserResource.class.php
  26. +13 −0 modules/restful_example/plugins/restful/db_query/node_user/1.0/node_user__1_0.inc
  27. +1 −1 modules/restful_example/plugins/restful/db_query/watchdog/1.0/RestfulWatchdogResource.class.php
  28. +37 −5 modules/restful_token_auth/plugins/authentication/RestfulAuthenticationToken.class.php
  29. +17 −2 ...stful/restful_token_auth/token_auth/refresh_token/1.0/RestfulRefreshTokenAuthentication.class.php
  30. +30 −1 modules/restful_token_auth/restful_token_auth.module
  31. +75 −24 modules/restful_token_auth/tests/RestfulTokenAuthenticationTestCase.test
  32. +1 −0 plugins/authentication/RestfulAuthenticationBasic.class.php
  33. +109 −2 plugins/authentication/RestfulAuthenticationManager.php
  34. +76 −59 plugins/formatter/hal_json/RestfulFormatterHalJson.class.php
  35. +18 −6 plugins/restful/RestfulBase.php
  36. +1 −1 plugins/restful/RestfulDataProviderCToolsPlugins.php
  37. +55 −38 plugins/restful/RestfulDataProviderDbQuery.php
  38. +43 −5 plugins/restful/RestfulDataProviderEFQ.php
  39. +70 −23 plugins/restful/RestfulEntityBase.php
  40. +1 −1 plugins/restful/RestfulEntityBaseMultipleBundles.php
  41. +11 −0 plugins/restful/RestfulEntityBaseNode.php
  42. +11 −5 plugins/restful/user/login_cookie/1.0/RestfulUserLoginCookie.class.php
  43. +1 −1 plugins/restful/user/login_cookie/1.0/login_cookie__1_0.inc
  44. +9 −5 restful.admin.inc
  45. +1 −0 restful.info
  46. +101 −24 restful.module
  47. +82 −0 tests/RestfulAuthenticationTestCase.test
  48. +66 −0 tests/RestfulCreatePrivateNodeTestCase.test
  49. +30 −0 tests/RestfulDbQueryTestCase.test
  50. +1 −1 tests/RestfulDiscoveryTestCase.test
  51. +8 −0 tests/RestfulHookMenuTestCase.test
  52. +123 −0 tests/RestfulListTestCase.test
  53. +80 −1 tests/RestfulRenderCacheTestCase.test
  54. +33 −0 tests/RestfulUpdateEntityTestCase.test
  55. +1 −1 tests/RestfulViewModeAndFormatterTestCase.test
  56. +6 −0 tests/modules/restful_node_access_test/restful_node_access_test.info
  57. +41 −0 tests/modules/restful_node_access_test/restful_node_access_test.module
  58. +4 −0 ...es/restful_test/plugins/restful/node/test_articles/1.2/RestfulTestArticlesResource__1_2.class.php
95 changes: 64 additions & 31 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,47 +1,80 @@
language: php

php:
- 5.3
- 5.4
- 5.5
- 5.6

env:
- PATH=$PATH:/home/travis/.composer/vendor/bin

# This will create the database
mysql:
database: restful
database: drupal
username: root
encoding: utf8

before_script:
# navigate out of module directory to prevent blown stack by recursive module lookup
- cd ../..

# install drush
- pear channel-discover pear.drush.org
- pear install drush/drush-5.8.0
install:
# Grab Drush
- composer global require "drush/drush:7.*"
- phpenv rehash
# Make sure we don't fail when checking out projects
- echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
# LAMP package installation (mysql is already started)
- sudo apt-get update
- sudo apt-get install apache2 libapache2-mod-fastcgi
# enable php-fpm, travis does not support any other method with php and apache
- sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf
- sudo a2enmod rewrite actions fastcgi alias
- echo "cgi.fix_pathinfo = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- ~/.phpenv/versions/$(phpenv version-name)/sbin/php-fpm
# Make sure the apache root is in our wanted directory
- echo "$(curl -fsSL https://gist.githubusercontent.com/nickveenhof/11386315/raw/b8abaf9304fe12b5cc7752d39c29c1edae8ac2e6/gistfile1.txt)" | sed -e "s,PATH,$TRAVIS_BUILD_DIR/../drupal,g" | sudo tee /etc/apache2/sites-available/default > /dev/null
# Set sendmail so drush doesn't throw an error during site install.
- echo "sendmail_path='true'" >> `php --ini | grep "Loaded Configuration" | awk '{print $4}'`
# Forward the errors to the syslog so we can print them
- echo "error_log=syslog" >> `php --ini | grep "Loaded Configuration" | awk '{print $4}'`
# Get latest drupal 8 core
- cd $TRAVIS_BUILD_DIR/..
- git clone --depth 1 --branch 7.x http://git.drupal.org/project/drupal.git
# Restart apache and test it
- sudo service apache2 restart
- curl -v "http://localhost"
# Re-enable when trying to get CodeSniffer doesn't return a 403 anymore.
#- composer global require drupal/coder:\>7

# install php packages required for running a web server from drush on php 5.3
- sudo apt-get update > /dev/null
- sudo apt-get install -y --force-yes php5-cgi php5-mysql

# create new site, stubbing sendmail path with true to prevent delivery errors and manually resolving drush path
- mysql -e 'create database restful'
- php -d sendmail_path=`which true` `pear config-get php_dir`/drush/drush.php --yes core-quick-drupal --profile=testing --no-server --db-url=mysql://root:@127.0.0.1/restful --enable=simpletest restful
before_script:
- cd $TRAVIS_BUILD_DIR/../drupal
# Update drupal core
- git pull origin 7.x
# Install the site
- drush -v site-install minimal --db-url=mysql://root:@localhost/drupal --yes
# Increase max_allowed_packet to avoid MySQL errors
- echo -e "[server]\nmax_allowed_packet=64M" | sudo tee -a /etc/mysql/conf.d/drupal.cnf
- sudo service mysql restart
- phpenv rehash

# reference and enable restful in build site
- ln -s $(readlink -e $(cd -)) restful/drupal/sites/all/modules/restful
- cd restful/drupal
- drush --yes pm-enable restful restful_token_auth restful_test
script:
# Go to our Drupal module directory
- mkdir $TRAVIS_BUILD_DIR/../drupal/sites/all/modules/restful
- cp -R $TRAVIS_BUILD_DIR/* $TRAVIS_BUILD_DIR/../drupal/sites/all/modules/restful/
# Go to our Drupal main directory
- cd $TRAVIS_BUILD_DIR/../drupal

# Download entity validator.
- drush dl entity_validator --dev --yes
# Download and enable module and its dependencies
- drush --yes dl ctools
- drush --yes dl entity_validator --dev
- drush --yes dl entity
- drush --yes dl entityreference

# Patch Entity API.
- curl -O https://www.drupal.org/files/issues/2086225-entity-access-check-node-create-3.patch
- patch -p1 /home/travis/build/restful/drupal/sites/all/modules/entity/modules/callbacks.inc < 2086225-entity-access-check-node-create-3.patch

- curl -O https://www.drupal.org/files/issues/2264079-entity-wrapper-access-single-entity-reference-2.patch
- patch -p1 /home/travis/build/restful/drupal/sites/all/modules/entity/includes/entity.wrapper.inc < 2264079-entity-wrapper-access-single-entity-reference-2.patch

# start a web server on port 8080, run in the background; wait for initialization
- drush runserver 127.0.0.1:8080 &
- until netstat -an 2>/dev/null | grep '8080.*LISTEN'; do true; done
- patch -p1 $TRAVIS_BUILD_DIR/../drupal/sites/all/modules/entity/modules/callbacks.inc < 2086225-entity-access-check-node-create-3.patch

script: drush test-run RESTful --uri=http://127.0.0.1:8080
# Enable the RESTful modules
- drush --yes pm-enable simpletest restful restful_token_auth
# Run the tests
- cd $TRAVIS_BUILD_DIR/../drupal
- php ./scripts/run-tests.sh --php $(which php) --concurrency 4 --verbose --color --url http://localhost RESTful 2>&1 | tee /tmp/simpletest-result.txt
- egrep -i "([1-9]+ fail)|(Fatal error)|([1-9]+ exception)" /tmp/simpletest-result.txt && exit 1
- exit 0
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
[![Build Status](https://travis-ci.org/RESTful-Drupal/restful.svg?branch=7.x-1.x)](https://travis-ci.org/RESTful-Drupal/restful)
**7.x-1.x** [![Build Status](https://travis-ci.org/RESTful-Drupal/restful.svg?branch=7.x-1.x)](https://travis-ci.org/RESTful-Drupal/restful)

**7.x-2.x** [![Build Status](https://travis-ci.org/RESTful-Drupal/restful.svg?branch=7.x-2.x)](https://travis-ci.org/RESTful-Drupal/restful)

# RESTful best practices for Drupal

@@ -7,7 +9,7 @@ practices for security, performance, and usability.


## Concept
Here are the differences between RESTful and other modules, such as RestWs and
These are the differences between RESTful and other modules, such as RestWs and
Services Entity:

* RESTful requires explicitly declaring the exposed API. When enabling
@@ -28,9 +30,8 @@ control.

## Module dependencies

* [Entity API](https://drupal.org/project/entity), with the following patches:
* [$wrapper->access() might be wrong for single entity reference field](https://www.drupal.org/node/2264079#comment-8911637)
* [Prevent notice in entity_metadata_no_hook_node_access() when node is not saved](https://drupal.org/node/2086225#comment-8768373)
* [Entity API](https://drupal.org/project/entity), with the following patch:
* [Prevent notice in entity_metadata_no_hook_node_access() when node is not saved](https://www.drupal.org/node/2086225#comment-9627407)

## Recipes
Read even more examples on how to use the RESTful module in the [module documentation
@@ -64,7 +65,7 @@ dependencies[] = restful
}
```

####restful\_custom/plugins/restful/myplugin.inc
####restful\_custom/plugins/restful/articles.inc
```php
$plugin = array(
'label' => t('Articles'),
@@ -76,6 +77,9 @@ $plugin = array(
'class' => 'RestfulCustomResource',
);
```
The `resource` key determines the root URL of the resource. The `name` key must match
the filename of the plugin: in this case, the name is `articles`, and therefore, the
filename is `articles.inc`.

####restful\_custom/plugins/restful/RestfulCustomResource.class.php
```php
@@ -241,7 +245,7 @@ documentation:
"required": false
},
"form_element": {
"type": "texfield",
"type": "textfield",
"default_value": "",
"placeholder": "",
"size": 255,
77 changes: 76 additions & 1 deletion docs/api_url.md
Original file line number Diff line number Diff line change
@@ -10,12 +10,22 @@ passed in the URL itself.

## Getting information about the resource


### Exploring the resource

Using a HTTP `GET` request on a resource's root URL will return information
about that resource, in addition to the data itself.

``` shell
curl https://example.com/api/
```
This will output all the available **latest** resources (of course, if you have enabled the "Discovery Resource" option). For example, if there are 3 different api version plugins for content type Article (1.0, 1.1, 2.0) it will display the latest only (2.0 in this case).

If you want to display all the versions of all the resources declared add the query **?all=true** like this.

``` shell
curl https://example.com/api?all=true
```

The data results are stored in the `data` property of the JSON response, while
the `self` and `next` objects contain information about the resource.

@@ -118,6 +128,21 @@ and another equal to 10.
curl https://example.com/api/articles?filter[integer_multiple][value][0]=5&filter[integer_multiple][value][1]=10&filter[integer_multiple][operator][0]=">"&filter[integer_multiple][operator][0]="="
```

## Applying a query sort
RESTful allows specifying of a sort property to the database query used to generate the list.

```php
# Handler v1.0
curl https://example.com/api/v1/articles?sort=label
```

The sort order will default to ascending, however it can be set to descending by prepending a minus (-) sign the sort parameter value.

```shell
# Handler v1.0
curl https://example.com/api/v1/articles?sort=-label
```

## Loading by an alternate ID.
Some times you need to load an entity by an alternate ID that is not the regular
entity ID, for example a unique ID title. All that you need to do is provide the
@@ -177,8 +202,58 @@ curl -u "username:password" https://example.com/api/login

# Call a "protected" with token resource (Articles resource version 1.3 in "Restful example")
curl https://example.com/api/v1.3/articles/1?access_token=YOUR_TOKEN

# Or use access-token instead of access_token for ensuring header is not going to be
# dropped out from $_SERVER so it remains compatible with other webservers different than apache.
curl -H "access-token: YOUR_TOKEN" https://example.com/api/v1.3/articles/1
```

## Change request formatter

By default Restful module allows for any **Content-type** requests by setting the ```Accept: */*```. This means that you can make requests in the format you want (of course if this format is available on the restful plugins).

For example let's say that we want to get a request in ```xml``` while by default we get the requests in ```hal+json```. All we have to do is set a Header parameter like this ```Accept: application/xml```.

```shell
curl -H 'Accept:application/xml' https://example.com/api/articles
```

And will return data in xml formatter.

```xml
<?xml version="1.0"?>
<api>
<articles>
<item0>
<id>1</id>
<label>Article title</label>
<_links>
<self>
<href>http://example.com/api/articles/1</href>
</self>
</_links>
</item0>
<item1>
<id>2</id>
<label>Article title</label>
<_links>
<self>
<href>http://example.com/api/articles/2</href>
</self>
</_links>
</item1>
<count>3</count>
<_links>
<self>
<title>Self</title>
<href>http://example.com/api/articles</href>
</self>
</_links>
</api>

```


## Error handling
If an error occurs when operating the REST endpoint via URL, A valid JSON object
with ``code``, ``message`` and ``description`` would be returned.
3 changes: 3 additions & 0 deletions docs/documentation.md
Original file line number Diff line number Diff line change
@@ -6,6 +6,9 @@ about the field itself. This includes basic information about the field,
information about the data the field holds, and information about the form
element to generate on the client side for this field.

Note that this data will usually be provided automatically by the entity's existing
property definitions, but can be overridden or added to here.

By declaring this information, you make it possible for clients to provide
form elements for your API using reusable form components.

8 changes: 5 additions & 3 deletions docs/plugin.md
Original file line number Diff line number Diff line change
@@ -52,6 +52,8 @@ resource.
If you need even more flexibility, you can use the `'callback'` key to name a
custom function to compute the field data.

For the DB query data provider, in case you want to filter a column of a query
with joins, see [this](https://github.com/RESTful-Drupal/restful/blob/7.x-1.x/modules/restful_example/plugins/restful/db_query/node_user/1.0/RestfulExampleNodeUserResource.class.php) example.

## Defining a view mode
You can leverage Drupal core's view modes to render an entity and expose it as a
@@ -195,9 +197,9 @@ public function publicFieldsInfo() {
}
```

Note that when you use the ``resource`` property, behind the scenes RESTful
initializes a second handler and calls that resource. In order to pass information
to the second handler (e.g. the access token), we pipe the original request
Note that when you use the ``resource`` property, behind the scenes RESTful
initializes a second handler and calls that resource. In order to pass information
to the second handler (e.g. the access token), we pipe the original request
array with some parameters removed. If you need to strip further parameters you can
override ``\RestfulBase::getRequestForSubRequest``.

8 changes: 2 additions & 6 deletions exceptions/RestfulBadRequestException.php
100644 → 100755
Original file line number Diff line number Diff line change
@@ -15,16 +15,12 @@ class RestfulBadRequestException extends RestfulException {
protected $code = 400;

/**
* Defines the description.
*
* @var string
* {@inheritdoc}
*/
protected $description = 'Bad Request.';

/**
* Defines the problem instance.
*
* @var string
* {@inheritdoc}
*/
protected $instance = 'help/restful/problem-instances-bad-request';

7 changes: 7 additions & 0 deletions exceptions/RestfulException.php
100644 → 100755
Original file line number Diff line number Diff line change
@@ -28,6 +28,13 @@ class RestfulException extends Exception {
*/
protected $headers = array();

/**
* Defines the description.
*
* @var string
*/
protected $description;

/**
* Gets the description of the exception.
*
8 changes: 2 additions & 6 deletions exceptions/RestfulFloodException.php
Original file line number Diff line number Diff line change
@@ -15,16 +15,12 @@ class RestfulFloodException extends RestfulException {
protected $code = 429;

/**
* Defines the description.
*
* @var string
* {@inheritdoc}
*/
protected $description = 'Too Many Requests.';

/**
* Defines the problem instance.
*
* @var string
* {@inheritdoc}
*/
protected $instance = 'help/restful/problem-instances-flood';

8 changes: 2 additions & 6 deletions exceptions/RestfulForbiddenException.php
Original file line number Diff line number Diff line change
@@ -15,16 +15,12 @@ class RestfulForbiddenException extends RestfulException {
protected $code = 403;

/**
* Defines the description.
*
* @var string
* {@inheritdoc}
*/
protected $description = 'Forbidden.';

/**
* Defines the problem instance.
*
* @var string
* {@inheritdoc}
*/
protected $instance = 'help/restful/problem-instances-forbidden';

8 changes: 2 additions & 6 deletions exceptions/RestfulGoneException.php
Original file line number Diff line number Diff line change
@@ -15,16 +15,12 @@ class RestfulGoneException extends Exception {
protected $code = 410;

/**
* Defines the description.
*
* @var string
* {@inheritdoc}
*/
protected $description = 'The resource at this end point is no longer available.';

/**
* Defines the problem instance.
*
* @var string
* {@inheritdoc}
*/
protected $instance = 'help/restful/problem-instances-gone';

Loading