diff --git a/.travis.yml b/.travis.yml index a9e63469ff..361f4ffb6a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,3 +31,9 @@ script: - composer install - phpunit mainTest.php - phpunit utilTest.php + - cd ../.. + # run datastore tests + - cd datastore + - composer install + - phpunit test + - cd .. \ No newline at end of file diff --git a/datastore/README.md b/datastore/README.md new file mode 100644 index 0000000000..585ba3f242 --- /dev/null +++ b/datastore/README.md @@ -0,0 +1,82 @@ +# Google Datastore PHP Sample Application + +A simple app to make calls to the Datastore API + +## Register your application + +- Go to + [Google Developers Console](https://console.developers.google.com/project) + and create a new project. This will automatically enable an App + Engine application with the same ID as the project. + +- Enable the "Google Cloud Datastore API" under "APIs & auth > APIs." + +- edit `app.yaml` and change `MY_GCP_PROJECT_ID` to your App Engine project ID + +- For local development also follow the instructions below. + + - Go to "Credentials" and create a new Service Account. + + - Select "Generate new JSON key", then download a new JSON file. + + - Set the following environment variables: + + - `GOOGLE_APPLICATION_CREDENTIALS`: the file path to the downloaded JSON file. + - `GCP_PROJECT_ID`: Your app engine project ID + +## Prerequisites + +- Install [`composer`](https://getcomposer.org) +- Install Google API client library for PHP by running: + +```sh +composer install +``` + +## Run locally + +you can run locally using PHP's built-in web server: + +```sh +cd php-docs-samples/datastore +export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json +export GCP_PROJECT_ID=my-project-id +php -S localhost:8080 -t web/ +``` + +Now you can view the app running at [http://localhost:8080](http://localhost:8080) +in your browser. + +## Deploy to App Engine + +**Prerequisites** + +- Install the App Engine PHP SDK. + We recommend you install + [Cloud SDK](https://developers.google.com/cloud/sdk/) rather than + just installing App Engine SDK. + +**Deploy with gcloud** + +``` +$ gcloud preview app deploy app.yaml --set-default --project YOUR_GCP_PROJECT_ID +``` + +Then access the following URL: + https://{YOUR_GCP_PROJECT_ID}.appspot.com/ + +### Run for App Engine locally + +``` +$ dev_appserver.py -A your-project-id . +``` + +## Contributing changes + +* See [CONTRIBUTING.md](../CONTRIBUTING.md) + +## Licensing + +* See [LICENSE](../LICENSE) + + diff --git a/datastore/app.yaml b/datastore/app.yaml new file mode 100644 index 0000000000..6646c8e808 --- /dev/null +++ b/datastore/app.yaml @@ -0,0 +1,10 @@ +runtime: php55 +api_version: 1 +threadsafe: true + +handlers: +- url: /.* + script: web/index.php + +env_variables: + GCP_PROJECT_ID: "YOUR_GCP_PROJECT_ID" diff --git a/datastore/composer.json b/datastore/composer.json new file mode 100644 index 0000000000..38d703af09 --- /dev/null +++ b/datastore/composer.json @@ -0,0 +1,19 @@ +{ + "autoload": { + "psr-4": { + "Google\\Cloud\\Samples\\Datastore\\": "src" + } + }, + "require": { + "php": ">=5.4", + "silex/silex": "~1.3", + "twig/twig": "~1.8|~2.0", + "symfony/twig-bridge": "~2.7|3.0.*", + "google/apiclient": "~2.0@RC" + }, + "require-dev": { + "symfony/dom-crawler": "~2.0", + "symfony/css-selector": "~2.0", + "symfony/browser-kit": "~2.7" + } +} diff --git a/datastore/composer.lock b/datastore/composer.lock new file mode 100644 index 0000000000..2865279b2f --- /dev/null +++ b/datastore/composer.lock @@ -0,0 +1,1301 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "1a8ab170f40b5d4eb803df87e6460c30", + "content-hash": "e71f2fc2e646b073c9490f3f6c2ee311", + "packages": [ + { + "name": "firebase/php-jwt", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "fa8a06e96526eb7c0eeaa47e4f39be59d21f16e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/fa8a06e96526eb7c0eeaa47e4f39be59d21f16e1", + "reference": "fa8a06e96526eb7c0eeaa47e4f39be59d21f16e1", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "time": "2015-07-22 18:31:08" + }, + { + "name": "google/apiclient", + "version": "v2.0.0-RC2", + "source": { + "type": "git", + "url": "https://github.com/google/google-api-php-client.git", + "reference": "3905a254d513236810b2451b1805507782bde313" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/google/google-api-php-client/zipball/3905a254d513236810b2451b1805507782bde313", + "reference": "3905a254d513236810b2451b1805507782bde313", + "shasum": "" + }, + "require": { + "firebase/php-jwt": "~2.0|~3.0", + "google/auth": "~0.4", + "guzzlehttp/guzzle": "5.2.*", + "monolog/monolog": "^1.17", + "php": ">=5.4", + "phpseclib/phpseclib": "~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~4", + "squizlabs/php_codesniffer": "~2.3", + "symfony/css-selector": "~2.0", + "symfony/dom-crawler": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-0": { + "Google_": "src/" + }, + "classmap": [ + "src/Google/Service/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "Client library for Google APIs", + "homepage": "http://developers.google.com/api-client-library/php", + "keywords": [ + "google" + ], + "time": "2015-11-10 04:11:33" + }, + { + "name": "google/auth", + "version": "v0.4", + "source": { + "type": "git", + "url": "https://github.com/google/google-auth-library-php.git", + "reference": "b2d0e7bdcbe8ccdd0f83a7527ef23bcc202e331a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/google/google-auth-library-php/zipball/b2d0e7bdcbe8ccdd0f83a7527ef23bcc202e331a", + "reference": "b2d0e7bdcbe8ccdd0f83a7527ef23bcc202e331a", + "shasum": "" + }, + "require": { + "firebase/php-jwt": "~2.0|~3.0", + "guzzlehttp/guzzle": "5.2.*", + "php": ">=5.4" + }, + "require-dev": { + "phplint/phplint": "0.0.1", + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ], + "psr-4": { + "Google\\Auth\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "Google Auth Library for PHP", + "homepage": "http://github.com/google/google-auth-library-php", + "keywords": [ + "Authentication", + "google", + "oauth2" + ], + "time": "2015-11-03 23:16:35" + }, + { + "name": "guzzlehttp/guzzle", + "version": "5.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "475b29ccd411f2fa8a408e64576418728c032cfa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/475b29ccd411f2fa8a408e64576418728c032cfa", + "reference": "475b29ccd411f2fa8a408e64576418728c032cfa", + "shasum": "" + }, + "require": { + "guzzlehttp/ringphp": "~1.0", + "php": ">=5.4.0" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "~4.0", + "psr/log": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2015-01-28 01:03:29" + }, + { + "name": "guzzlehttp/ringphp", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/RingPHP.git", + "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "shasum": "" + }, + "require": { + "guzzlehttp/streams": "~3.0", + "php": ">=5.4.0", + "react/promise": "~2.0" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "ext-curl": "Guzzle will use specific adapters if cURL is present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Ring\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", + "time": "2015-05-20 03:37:09" + }, + { + "name": "guzzlehttp/streams", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/streams.git", + "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Provides a simple abstraction over streams of data", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "stream" + ], + "time": "2014-10-12 19:18:40" + }, + { + "name": "monolog/monolog", + "version": "1.17.2", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "bee7f0dc9c3e0b69a6039697533dca1e845c8c24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bee7f0dc9c3e0b69a6039697533dca1e845c8c24", + "reference": "bee7f0dc9c3e0b69a6039697533dca1e845c8c24", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9", + "doctrine/couchdb": "~1.0@dev", + "graylog2/gelf-php": "~1.0", + "jakub-onderka/php-parallel-lint": "0.9", + "php-console/php-console": "^3.1.3", + "phpunit/phpunit": "~4.5", + "phpunit/phpunit-mock-objects": "2.3.0", + "raven/raven": "^0.13", + "ruflin/elastica": ">=0.90 <3.0", + "swiftmailer/swiftmailer": "~5.3", + "videlalvaro/php-amqplib": "~2.4" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-mongo": "Allow sending log messages to a MongoDB server", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "php-console/php-console": "Allow sending log messages to Google Chrome", + "raven/raven": "Allow sending log messages to a Sentry server", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.16.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be/" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "http://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "time": "2015-10-14 12:51:02" + }, + { + "name": "phpseclib/phpseclib", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "a74aa9efbe61430fcb60157c8e025a48ec8ff604" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/a74aa9efbe61430fcb60157c8e025a48ec8ff604", + "reference": "a74aa9efbe61430fcb60157c8e025a48ec8ff604", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phing/phing": "~2.7", + "phpunit/phpunit": "~4.0", + "sami/sami": "~2.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "suggest": { + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.", + "pear-pear/PHP_Compat": "Install PHP_Compat to get phpseclib working on PHP < 5.0.0." + }, + "type": "library", + "autoload": { + "psr-4": { + "phpseclib\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "phpseclib/" + ], + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net/", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "time": "2015-08-04 04:48:03" + }, + { + "name": "pimple/pimple", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "2019c145fe393923f3441b23f29bbdfaa5c58c4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/2019c145fe393923f3441b23f29bbdfaa5c58c4d", + "reference": "2019c145fe393923f3441b23f29bbdfaa5c58c4d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-0": { + "Pimple": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", + "homepage": "http://pimple.sensiolabs.org/", + "keywords": [ + "container", + "dependency injection" + ], + "time": "2013-11-22 08:30:29" + }, + { + "name": "psr/log", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2012-12-21 11:40:51" + }, + { + "name": "react/promise", + "version": "v2.2.1", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/3b6fca09c7d56321057fa8867c8dbe1abf648627", + "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "React\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "time": "2015-07-03 13:48:55" + }, + { + "name": "silex/silex", + "version": "v1.3.4", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Silex.git", + "reference": "d6de62716fcda76084f3015165125f30b1563517" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Silex/zipball/d6de62716fcda76084f3015165125f30b1563517", + "reference": "d6de62716fcda76084f3015165125f30b1563517", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "pimple/pimple": "~1.0", + "symfony/event-dispatcher": "~2.3|3.0.*", + "symfony/http-foundation": "~2.3|3.0.*", + "symfony/http-kernel": "~2.3|3.0.*", + "symfony/routing": "~2.3|3.0.*" + }, + "require-dev": { + "doctrine/dbal": "~2.2", + "monolog/monolog": "^1.4.1", + "swiftmailer/swiftmailer": "~5", + "symfony/browser-kit": "~2.3|3.0.*", + "symfony/config": "~2.3|3.0.*", + "symfony/css-selector": "~2.3|3.0.*", + "symfony/debug": "~2.3|3.0.*", + "symfony/dom-crawler": "~2.3|3.0.*", + "symfony/finder": "~2.3|3.0.*", + "symfony/form": "~2.3|3.0.*", + "symfony/locale": "~2.3|3.0.*", + "symfony/monolog-bridge": "~2.3|3.0.*", + "symfony/options-resolver": "~2.3|3.0.*", + "symfony/phpunit-bridge": "~2.7", + "symfony/process": "~2.3|3.0.*", + "symfony/security": "~2.3|3.0.*", + "symfony/serializer": "~2.3|3.0.*", + "symfony/translation": "~2.3|3.0.*", + "symfony/twig-bridge": "~2.3|3.0.*", + "symfony/validator": "~2.3|3.0.*", + "twig/twig": "~1.8|~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Silex\\": "src/Silex" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "The PHP micro-framework based on the Symfony Components", + "homepage": "http://silex.sensiolabs.org/", + "keywords": [ + "microframework" + ], + "time": "2015-09-15 06:53:42" + }, + { + "name": "symfony/debug", + "version": "v2.7.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "fb9e6887db716939f41af0ba8ef38a1582eb501b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/fb9e6887db716939f41af0ba8ef38a1582eb501b", + "reference": "fb9e6887db716939f41af0ba8ef38a1582eb501b", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/class-loader": "~2.2", + "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com/", + "time": "2015-10-11 09:39:48" + }, + { + "name": "symfony/event-dispatcher", + "version": "v2.7.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "87a5db5ea887763fa3a31a5471b512ff1596d9b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/87a5db5ea887763fa3a31a5471b512ff1596d9b8", + "reference": "87a5db5ea887763fa3a31a5471b512ff1596d9b8", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.0,>=2.0.5", + "symfony/dependency-injection": "~2.6", + "symfony/expression-language": "~2.6", + "symfony/stopwatch": "~2.3" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com/", + "time": "2015-10-11 09:39:48" + }, + { + "name": "symfony/http-foundation", + "version": "v2.7.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "7598eea151ae3d4134df1f9957364b17809eea75" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/7598eea151ae3d4134df1f9957364b17809eea75", + "reference": "7598eea151ae3d4134df1f9957364b17809eea75", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/expression-language": "~2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com/", + "time": "2015-10-23 14:47:27" + }, + { + "name": "symfony/http-kernel", + "version": "v2.7.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "4260f2273a446a6715063dc9ca89fd0c475c2f77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/4260f2273a446a6715063dc9ca89fd0c475c2f77", + "reference": "4260f2273a446a6715063dc9ca89fd0c475c2f77", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "psr/log": "~1.0", + "symfony/debug": "~2.6,>=2.6.2", + "symfony/event-dispatcher": "~2.6,>=2.6.7", + "symfony/http-foundation": "~2.5,>=2.5.4" + }, + "conflict": { + "symfony/config": "<2.7" + }, + "require-dev": { + "symfony/browser-kit": "~2.3", + "symfony/class-loader": "~2.1", + "symfony/config": "~2.7", + "symfony/console": "~2.3", + "symfony/css-selector": "~2.0,>=2.0.5", + "symfony/dependency-injection": "~2.2", + "symfony/dom-crawler": "~2.0,>=2.0.5", + "symfony/expression-language": "~2.4", + "symfony/finder": "~2.0,>=2.0.5", + "symfony/process": "~2.0,>=2.0.5", + "symfony/routing": "~2.2", + "symfony/stopwatch": "~2.3", + "symfony/templating": "~2.2", + "symfony/translation": "~2.0,>=2.0.5", + "symfony/var-dumper": "~2.6" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/class-loader": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "", + "symfony/finder": "", + "symfony/var-dumper": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com/", + "time": "2015-10-27 19:07:21" + }, + { + "name": "symfony/routing", + "version": "v2.7.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "f353e1f588679c3ec987624e6c617646bd01ba38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/f353e1f588679c3ec987624e6c617646bd01ba38", + "reference": "f353e1f588679c3ec987624e6c617646bd01ba38", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "conflict": { + "symfony/config": "<2.7" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/common": "~2.2", + "psr/log": "~1.0", + "symfony/config": "~2.7", + "symfony/expression-language": "~2.4", + "symfony/http-foundation": "~2.3", + "symfony/yaml": "~2.0,>=2.0.5" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "https://symfony.com/", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2015-10-27 15:38:06" + }, + { + "name": "symfony/twig-bridge", + "version": "v2.7.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bridge.git", + "reference": "3dd44937b1e08af8c8f6b14850f4b9c4d1039c6f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/3dd44937b1e08af8c8f6b14850f4b9c4d1039c6f", + "reference": "3dd44937b1e08af8c8f6b14850f4b9c4d1039c6f", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "twig/twig": "~1.20|~2.0" + }, + "require-dev": { + "symfony/asset": "~2.7", + "symfony/console": "~2.7", + "symfony/expression-language": "~2.4", + "symfony/finder": "~2.3", + "symfony/form": "~2.7,>=2.7.6", + "symfony/http-kernel": "~2.3", + "symfony/intl": "~2.3", + "symfony/routing": "~2.2", + "symfony/security": "~2.6", + "symfony/security-acl": "~2.6", + "symfony/stopwatch": "~2.2", + "symfony/templating": "~2.1", + "symfony/translation": "~2.7", + "symfony/var-dumper": "~2.6", + "symfony/yaml": "~2.0,>=2.0.5" + }, + "suggest": { + "symfony/asset": "For using the AssetExtension", + "symfony/expression-language": "For using the ExpressionExtension", + "symfony/finder": "", + "symfony/form": "For using the FormExtension", + "symfony/http-kernel": "For using the HttpKernelExtension", + "symfony/routing": "For using the RoutingExtension", + "symfony/security": "For using the SecurityExtension", + "symfony/stopwatch": "For using the StopwatchExtension", + "symfony/templating": "For using the TwigEngine", + "symfony/translation": "For using the TranslationExtension", + "symfony/var-dumper": "For using the DumpExtension", + "symfony/yaml": "For using the YamlExtension" + }, + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Twig\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Twig Bridge", + "homepage": "https://symfony.com/", + "time": "2015-10-11 09:39:48" + }, + { + "name": "twig/twig", + "version": "v1.23.1", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "d9b6333ae8dd2c8e3fd256e127548def0bc614c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/d9b6333ae8dd2c8e3fd256e127548def0bc614c6", + "reference": "d9b6333ae8dd2c8e3fd256e127548def0bc614c6", + "shasum": "" + }, + "require": { + "php": ">=5.2.7" + }, + "require-dev": { + "symfony/debug": "~2.7", + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.23-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org/", + "role": "Lead Developer" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + }, + { + "name": "Twig Team", + "homepage": "http://twig.sensiolabs.org/contributors", + "role": "Contributors" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "http://twig.sensiolabs.org/", + "keywords": [ + "templating" + ], + "time": "2015-11-05 12:49:06" + } + ], + "packages-dev": [ + { + "name": "symfony/browser-kit", + "version": "v2.7.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "07d664a052572ccc28eb2ab7dbbe82155b1ad367" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/07d664a052572ccc28eb2ab7dbbe82155b1ad367", + "reference": "07d664a052572ccc28eb2ab7dbbe82155b1ad367", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/dom-crawler": "~2.0,>=2.0.5" + }, + "require-dev": { + "symfony/css-selector": "~2.0,>=2.0.5", + "symfony/process": "~2.3.34|~2.7,>=2.7.6" + }, + "suggest": { + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony BrowserKit Component", + "homepage": "https://symfony.com/", + "time": "2015-10-23 14:47:27" + }, + { + "name": "symfony/css-selector", + "version": "v2.7.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "e1b865b26be4a56d22a8dee398375044a80c865b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/e1b865b26be4a56d22a8dee398375044a80c865b", + "reference": "e1b865b26be4a56d22a8dee398375044a80c865b", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "https://symfony.com/", + "time": "2015-10-11 09:39:48" + }, + { + "name": "symfony/dom-crawler", + "version": "v2.7.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "5fef7d8b80d8f9992df99d8ee283f420484c9612" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/5fef7d8b80d8f9992df99d8ee283f420484c9612", + "reference": "5fef7d8b80d8f9992df99d8ee283f420484c9612", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/css-selector": "~2.3" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "https://symfony.com/", + "time": "2015-10-11 09:39:48" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "google/apiclient": 5 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.4" + }, + "platform-dev": [] +} diff --git a/datastore/php.ini b/datastore/php.ini new file mode 100644 index 0000000000..c9ec4d430a --- /dev/null +++ b/datastore/php.ini @@ -0,0 +1,2 @@ +google_app_engine.enable_functions = "php_sapi_name, php_uname" +extension = "curl.so" diff --git a/datastore/src/DatastoreHelper.php b/datastore/src/DatastoreHelper.php new file mode 100644 index 0000000000..e3de7beb95 --- /dev/null +++ b/datastore/src/DatastoreHelper.php @@ -0,0 +1,115 @@ +setDirection('descending'); + $property = new \Google_Service_Datastore_PropertyReference(); + $property->setName('created'); + $order->setProperty($property); + $query->setOrder([$order]); + + $kind = new \Google_Service_Datastore_KindExpression(); + $kind->setName(self::KIND); + $query->setKinds([$kind]); + + $query->setLimit($limit); + + $request->setQuery($query); + + return $request; + } + + /** + * Creates the request to store a DatastoreComment item in datastore + */ + public function createCommentRequest(\Google_Service_Datastore_Key $id, $name, $body) + { + $entity = $this->createEntity($id, $name, $body); + $mutation = new \Google_Service_Datastore_Mutation(); + $mutation->setUpsert([$entity]); + $req = new \Google_Service_Datastore_CommitRequest(); + $req->setMode('NON_TRANSACTIONAL'); + $req->setMutation($mutation); + + return $req; + } + + /** + * Creates the basic entity for DatastoreComment, with properties "created" + * "name", and "body" + */ + public function createEntity(\Google_Service_Datastore_Key $key, $name, $body) + { + $entity = new \Google_Service_Datastore_Entity(); + $entity->setKey($key); + $nameProp = new \Google_Service_Datastore_Property(); + $nameProp->setStringValue($name); + $bodyProp = new \Google_Service_Datastore_Property(); + $bodyProp->setStringValue($body); + $createdProp = new \Google_Service_Datastore_Property(); + $createdProp->setDateTimeValue(date('c')); + $properties = [ + 'name' => $nameProp, + 'body' => $bodyProp, + 'created' => $createdProp, + ]; + + $entity->setProperties($properties); + + return $entity; + } + + /** + * Fetches a unique key from Datastore + */ + public function createUniqueKeyRequest() + { + // retrieve a unique ID from datastore + $path = new \Google_Service_Datastore_KeyPathElement(); + $path->setKind(self::KIND); + $key = new \Google_Service_Datastore_Key(); + $key->setPath([$path]); + $idRequest = new \Google_Service_Datastore_AllocateIdsRequest(); + $idRequest->setKeys([$key]); + + return $idRequest; + } +} diff --git a/datastore/src/app.php b/datastore/src/app.php new file mode 100644 index 0000000000..16a3b0c101 --- /dev/null +++ b/datastore/src/app.php @@ -0,0 +1,110 @@ +register(new TwigServiceProvider()); +$app->register(new UrlGeneratorServiceProvider()); +$app['twig.path'] = [ __DIR__.'/../templates' ]; + +// create the google api client +$client = new Google_Client(); +$client->useApplicationDefaultCredentials(); +$client->addScope(Google_Service_Datastore::DATASTORE); +$client->addScope(Google_Service_Datastore::USERINFO_EMAIL); + +// add the api client and project id to our silex app +$app['google_client'] = $client; +$app['project_id'] = getenv('GCP_PROJECT_ID'); + +$app->get('/', function () use ($app) { + /** @var Google_Client $client */ + $client = $app['google_client']; + /** @var Twig_Environment $twig */ + $twig = $app['twig']; + + // run a simple query to retrieve the comments + // - last 20 items ordered by created DESC + $projectId = $app['project_id']; + $datastore = new Google_Service_Datastore($client); + $util = new DatastoreHelper(); + $query = $util->createSimpleQuery(); + $response = $datastore->datasets->runQuery($projectId, $query); + + // create an array of the queried DataStore comments + // and pass them to the view layer + $comments = []; + foreach ($response->getBatch()->getEntityResults() as $entityResult) { + $properties = $entityResult->getEntity()->getProperties(); + $comments[] = [ + 'name' => $properties['name']->getStringValue(), + 'body' => $properties['body']->getStringValue(), + 'created' => $properties['created']->getDateTimeValue(), + ]; + } + + return $twig->render('datastore.html.twig', [ + 'project' => $projectId, + 'comments' => $comments, + ]); +})->bind('home'); + +$app->post('/store', function(Request $request) use ($app) { + /** @var Google_Client $client */ + $client = $app['google_client']; + /** @var Symfony\Component\Routing\Generator\UrlGenerator $urlgen */ + $urlgen = $app['url_generator']; + + // pull the comment from the post body + $name = $request->get('name'); + $body = $request->get('body'); + + if (empty($name) || empty($body)) { + $error = 'Invalid Request: "name" and "body" are required'; + return new Response($error, 400); + } + + $util = new DatastoreHelper(); + + // use our project ID for our dataset ID + $datasetId = $app['project_id']; + + // create a datastore service object to call the APIs + $datastore = new Google_Service_Datastore($client); + + // generate a unique key to store this item using the APIs + $keyRequest = $util->createUniqueKeyRequest($datasetId); + $uniqueId = $datastore->datasets->allocateIds($datasetId, $keyRequest); + $key = $uniqueId->getKeys()[0]; + + // submit the changes to datastore + $request = $util->createCommentRequest($key, $name, $body); + $result = $datastore->datasets->commit($datasetId, $request); + + return new Response('', 301, ['Location' => $urlgen->generate('home')]); +})->bind('store'); + +return $app; diff --git a/datastore/templates/datastore.html.twig b/datastore/templates/datastore.html.twig new file mode 100644 index 0000000000..13015ab33a --- /dev/null +++ b/datastore/templates/datastore.html.twig @@ -0,0 +1,35 @@ + + + + Datastore Example + + + +

Datastore Example

+ +

Project: {{ project }}

+ +
+ Your Name: +

+ Comment:
+ +

+ +
+ + +

Comments:

+ + + diff --git a/datastore/test/datastoreTest.php b/datastore/test/datastoreTest.php new file mode 100644 index 0000000000..567f1569fc --- /dev/null +++ b/datastore/test/datastoreTest.php @@ -0,0 +1,82 @@ +markTestSkipped('credentials not found'); + } + + // prevent HTML error exceptions + unset($app['exception_handler']); + + return $app; + } + + public function testHome() + { + $client = $this->createClient(); + + $crawler = $client->request('GET', '/'); + + $this->assertTrue($client->getResponse()->isOk()); + } + + public function testStore() + { + $client = $this->createClient(); + + $crawler = $client->request('POST', '/store', [ + 'name' => 'test-comment', + 'body' => 'body of comment' + ]); + + $response = $client->getResponse(); + $this->assertEquals(301, $response->getStatusCode()); + $this->assertEquals('/', $response->headers->get('location')); + } + + public function testStoreMissingParameters() + { + $client = $this->createClient(); + + $crawler = $client->request('POST', '/store'); + + $this->assertEquals(400, $client->getResponse()->getStatusCode()); + } +} \ No newline at end of file diff --git a/datastore/web/index.php b/datastore/web/index.php new file mode 100644 index 0000000000..48ea8e8b48 --- /dev/null +++ b/datastore/web/index.php @@ -0,0 +1,32 @@ +run();