diff --git a/appengine/flexible/pubsub/README.md b/appengine/flexible/pubsub/README.md index 9624e0a4d3..a9e5ada98e 100644 --- a/appengine/flexible/pubsub/README.md +++ b/appengine/flexible/pubsub/README.md @@ -5,40 +5,28 @@ This sample demonstrates how to invoke PubSub from Google App Engine Flexible Environment. -The sample code lives in [a parent pubsub directory](../../../pubsub). +The sample code lives in [a parent pubsub directory](../../../pubsub/app). Only two configuration files differ: `app.yaml` and `nginx-app.conf`. ## 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 Pub/Sub" API under "APIs & auth > APIs." -- Enable the "Google Cloud Datastore" API under "APIs & auth > APIs." -- 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 variable: - - `GOOGLE_APPLICATION_CREDENTIALS`: the file path to the downloaded JSON file. - - ## Configuration -- Edit `app.yaml`. Replace `your-google-project-id` with your google project id. +- Edit `app.yaml`. Replace `YOUR_PROJECT_ID` with your google project id. -- Copy `app.yaml` and `nginx-app.conf` into [../../../pubsub](../../../pubsub). Ex: +- Copy `app.yaml` and `nginx-app.conf` into [../../../pubsub/app](../../../pubsub/app). Ex: ```sh -~/gitrepos/php-docs-samples/appengine/flexible/pubsub$ cp -f app.yaml nginx-app.conf ../../../pubsub -~/gitrepos/php-docs-samples/appengine/flexible/pubsub$ cd ../../../pubsub/ -~/gitrepos/php-docs-samples/pubsub$ +~/gitrepos/php-docs-samples/appengine/flexible/pubsub$ cp -f app.yaml nginx-app.conf ../../../pubsub/app +~/gitrepos/php-docs-samples/appengine/flexible/pubsub$ cd ../../../pubsub/app +~/gitrepos/php-docs-samples/pubsub$ ``` +- Follow the [Prerequisite Instructions](../../../pubsub/app/README.md#prerequisites) + ## Deploy the application to App Engine ``` -$ gcloud app deploy app.yaml --set-default --project YOUR_PROJECT_NAME +$ gcloud app deploy --set-default --project YOUR_PROJECT_ID ``` Then access the following URL: diff --git a/appengine/flexible/pubsub/app.yaml b/appengine/flexible/pubsub/app.yaml index 01ac56496b..ac5a8420f7 100644 --- a/appengine/flexible/pubsub/app.yaml +++ b/appengine/flexible/pubsub/app.yaml @@ -1,8 +1,5 @@ runtime: php vm: true -runtime_config: - document_root: web - env_variables: - GOOGLE_PROJECT_NAME: your-google-project-id + GOOGLE_PROJECT_NAME: YOUR_PROJECT_ID diff --git a/pubsub/README.md b/pubsub/README.md deleted file mode 100644 index 0902ddb63c..0000000000 --- a/pubsub/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# Google PubSub PHP Sample Application - -## Description - -Note: The push endpoints don't work with the App Engine's local -devserver. The push notifications will go to an HTTP URL on the App -Engine server even when you run this sample locally. So we recommend -you deploy and run the app on App Engine. -TODO(tmatsuo): Better implementation for devserver. - -## 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 Pub/Sub" API under "APIs & auth > APIs." -- Enable the "Google Cloud Datastore" API under "APIs & auth > APIs." -- 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 variable: - - `GOOGLE_APPLICATION_CREDENTIALS`: the file path to the downloaded JSON file. - -## Prerequisites - -- Install [`composer`](https://getcomposer.org) -- Install the App Engine Python SDK. - We recommend you install - [Cloud SDK](https://developers.google.com/cloud/sdk/) rather than - just installing App Engine SDK. - -- Install Google API client library for PHP into 'lib' directory by running: - -``` -$ composer install -``` - -## Deploy the application to App Engine - -``` -$ gcloud app deploy app.yaml --set-default --project YOUR_PROJECT_NAME -``` - -Then access the following URL: - https://{YOUR_PROJECT_NAME}.appspot.com/ - -## Deploy the application to App Engine Flexible Environment. - -See the instructions [here](../appengine/flexible/pubsub/README.md). - -## Run the application locally - -``` -$ dev_appserver.py -A your-project-name . -``` - -## Contributing changes - -* See [CONTRIBUTING.md](../CONTRIBUTING.md) - -## Licensing - -* See [LICENSE](../LICENSE) - - diff --git a/pubsub/app.yaml b/pubsub/app.yaml deleted file mode 100644 index 453cdd7d12..0000000000 --- a/pubsub/app.yaml +++ /dev/null @@ -1,12 +0,0 @@ -runtime: php55 -api_version: 1 -threadsafe: true - -handlers: -- url: /js - static_dir: web/js -- url: /.* - script: web/index.php - -env_variables: - GOOGLE_PROJECT_NAME: "YOUR_PROJECT_NAME" \ No newline at end of file diff --git a/pubsub/app/README.md b/pubsub/app/README.md new file mode 100644 index 0000000000..08649b9d4b --- /dev/null +++ b/pubsub/app/README.md @@ -0,0 +1,85 @@ +# Google PubSub PHP Sample Application + +## Description + +Note: The push endpoints don't work with the App Engine's local +devserver. The push notifications will go to an HTTP URL on the App +Engine server even when you run this sample locally. So we recommend +you deploy and run the app on App Engine. + +## 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 Pub/Sub" API under "APIs & auth > APIs." + +## Prerequisites + +- Install [`composer`](https://getcomposer.org) +- Install the App Engine Python SDK. + We recommend you install + [Cloud SDK](https://developers.google.com/cloud/sdk/) rather than + just installing App Engine SDK. +- Create the topic "php-example-topic" and create a subscription to that topic + with the name "php-example-subscription". + - Use the [pubsub CLI](../cli) or the + [Developer Console](https://console.developer.google.com) + - To use Push Subscriptions, register your subscription with the + endpoint `https://{YOUR_PROJECT_NAME}.appspot.com/receive_message` +- Install dependencies by running: + +``` +$ composer install +``` + +## Local Development + +- Go to "Credentials" and create a new Service Account. +- Select "Generate new JSON key", then download a new JSON file. +- Set the following environment variable: + - `GOOGLE_APPLICATION_CREDENTIALS`: the file path to the downloaded JSON file. + - `GOOGLE_PROJECT_ID`: your project ID. + +Run the PHP build-in web server with the following command: + +``` +$ php -S localhost:8080 +``` + +Now browse to [localhost:8080](http://localhost:8080) in your browser. + +## Deploy to App Engine Standard + +- Change `YOUR_PROJECT_ID` in `app.yaml` to your project ID. + +Run the following gcloud command to deploy your app: + +``` +$ gcloud app deploy +``` + +Then access the following URL: + https://{YOUR_PROJECT_NAME}.appspot.com/ + +## Deploy to App Engine Flexible + +See the instructions [here](../appengine/flexible/pubsub/README.md). + +## Run using Dev Appserver + +``` +$ dev_appserver.py -A your-project-name . +``` + +## Contributing changes + +* See [CONTRIBUTING.md](../../CONTRIBUTING.md) + +## Licensing + +* See [LICENSE](../../LICENSE) + + diff --git a/pubsub/app/app.php b/pubsub/app/app.php new file mode 100644 index 0000000000..97295ca67b --- /dev/null +++ b/pubsub/app/app.php @@ -0,0 +1,103 @@ +register(new TwigServiceProvider()); +$app['twig.path'] = [ __DIR__ ]; + +$app->get('/', function () use ($app) { + return $app['twig']->render('pubsub.html.twig', [ + 'project_id' => $app['project_id'], + ]); +}); + +$app->get('/fetch_messages', function () use ($app) { + $messages = $app['get_pull_messages'](true); + $builder = new ServiceBuilder([ + 'projectId' => $app['project_id'], + ]); + $pubsub = $builder->pubsub(); + $subscription = $pubsub->subscription($app['subscription']); + $ackIds = []; + foreach ($subscription->pull(['returnImmediately' => true]) as $message) { + $ackIds[] = $message['ackId']; + $messageData = $message['message']['data']; + $messages[] = base64_decode($messageData); + } + if ($ackIds) { + $subscription->acknowledgeBatch($ackIds); + } + return new JsonResponse($messages); +}); + +$app->post('/receive_message', function () use ($app) { + // pull the message from the post body + $json = $app['request']->getContent(); + $request = json_decode($json, true); + if ( + !isset($request['message']['data']) + || !$message = base64_decode($request['message']['data']) + ) { + return new Response('', 400); + } + // store the push message in memcache + $app['save_pull_message']($message); + return new Response(); +}); + +$app->post('/send_message', function () use ($app) { + // send the pubsub message + if ($message = $app['request']->get('message')) { + $builder = new ServiceBuilder([ + 'projectId' => $app['project_id'], + ]); + $pubsub = $builder->pubsub(); + $topic = $pubsub->topic($app['topic']); + $response = $topic->publish(['data' => $message]); + return new Response('', 204); + } + return new Response('', 400); +}); + +$app['get_pull_messages'] = $app->protect(function ($clearMessages = false) { + $memcache = new Memcached; + if ($pullMessages = $memcache->get('pull-messages')) { + if ($clearMessages) { + $memcache->set('pull-messages', []); + } + return $pullMessages; + } + return []; +}); + +$app['save_pull_message'] = $app->protect(function ($message) use ($app) { + $memcache = new Memcached; + $messages = $app['get_pull_messages'](); + $messages[] = $message; + $memcache->set('pull-messages', $messages); +}); + +return $app; diff --git a/pubsub/app/app.yaml b/pubsub/app/app.yaml new file mode 100644 index 0000000000..e9fd7704da --- /dev/null +++ b/pubsub/app/app.yaml @@ -0,0 +1,12 @@ +runtime: php55 +api_version: 1 +threadsafe: true + +handlers: +- url: pubsub.js + static_file: pubsub.js +- url: /.* + script: index.php + +env_variables: + GOOGLE_PROJECT_ID: "cloud-samples-tests-php" \ No newline at end of file diff --git a/pubsub/composer.json b/pubsub/app/composer.json similarity index 75% rename from pubsub/composer.json rename to pubsub/app/composer.json index 83ab1e566c..3ca90c5069 100644 --- a/pubsub/composer.json +++ b/pubsub/app/composer.json @@ -1,13 +1,8 @@ { - "autoload": { - "psr-4": { - "Google\\Cloud\\Samples\\Pubsub\\": "src" - } - }, "require": { "php": ">=5.4", + "google/cloud": "0.8", "silex/silex": "~1.3", - "google/apiclient": "^2.0", "symfony/twig-bridge": "~2.7|3.0.*", "twig/twig": "~1.8|~2.0" }, diff --git a/pubsub/composer.lock b/pubsub/app/composer.lock similarity index 89% rename from pubsub/composer.lock rename to pubsub/app/composer.lock index e46819872c..c48dedc150 100644 --- a/pubsub/composer.lock +++ b/pubsub/app/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "923ae619838ee81f6e110a58258f4baf", - "content-hash": "59adf5fecbf2a5be4c4e1801d0c0dbe3", + "hash": "67c331a61fa2c4a063dffd5c8813f57c", + "content-hash": "7a04093664c6b1c2469b10c179218e3e", "packages": [ { "name": "firebase/php-jwt", @@ -51,146 +51,134 @@ "time": "2015-07-22 18:31:08" }, { - "name": "google/apiclient", - "version": "v2.0.2", + "name": "google/auth", + "version": "v0.10", "source": { "type": "git", - "url": "https://github.com/google/google-api-php-client.git", - "reference": "18dd5534280318598e8770cb7929e9a542e91c0d" + "url": "https://github.com/google/google-auth-library-php.git", + "reference": "760e3fbe4064c0525c22e27e5374eada3c103da8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/google/google-api-php-client/zipball/18dd5534280318598e8770cb7929e9a542e91c0d", - "reference": "18dd5534280318598e8770cb7929e9a542e91c0d", + "url": "https://api.github.com/repos/google/google-auth-library-php/zipball/760e3fbe4064c0525c22e27e5374eada3c103da8", + "reference": "760e3fbe4064c0525c22e27e5374eada3c103da8", "shasum": "" }, "require": { "firebase/php-jwt": "~2.0|~3.0", - "google/apiclient-services": "^0.5", - "google/auth": "0.9", - "guzzlehttp/guzzle": "~5.2|~6.0", - "guzzlehttp/psr7": "^1.2", - "monolog/monolog": "^1.17", + "guzzlehttp/guzzle": "~5.3|~6.0", + "guzzlehttp/psr7": "~1.2", "php": ">=5.4", - "phpseclib/phpseclib": "~2.0" + "psr/cache": "^1.0", + "psr/http-message": "^1.0" }, "require-dev": { - "phpunit/phpunit": "~4", - "squizlabs/php_codesniffer": "~2.3", - "symfony/css-selector": "~2.1", - "symfony/dom-crawler": "~2.1", - "tedivm/stash": "^0.14.1" - }, - "suggest": { - "tedivm/stash": "For caching certs and tokens (using Google_Client::setCache)" + "friendsofphp/php-cs-fixer": "^1.11", + "phpunit/phpunit": "3.7.*" }, "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": "2016-07-21 18:41:10" - }, - { - "name": "google/apiclient-services", - "version": "v0.5", - "target-dir": "Google/Service", - "source": { - "type": "git", - "url": "https://github.com/google/google-api-php-client-services.git", - "reference": "a2d43f4c7eace8c7aa16c5ea83191344c63b4526" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/google/google-api-php-client-services/zipball/a2d43f4c7eace8c7aa16c5ea83191344c63b4526", - "reference": "a2d43f4c7eace8c7aa16c5ea83191344c63b4526", - "shasum": "" - }, - "require": { - "php": ">=5.4" - }, - "type": "library", - "autoload": { - "psr-0": { - "Google_Service_": "" + "src/" + ], + "psr-4": { + "Google\\Auth\\": "src" } }, "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", + "description": "Google Auth Library for PHP", + "homepage": "http://github.com/google/google-auth-library-php", "keywords": [ - "google" + "Authentication", + "google", + "oauth2" ], - "time": "2016-07-21 18:01:41" + "time": "2016-08-02 22:00:48" }, { - "name": "google/auth", - "version": "v0.9", + "name": "google/cloud", + "version": "v0.8.0", "source": { "type": "git", - "url": "https://github.com/google/google-auth-library-php.git", - "reference": "47c3c6bece495e58381a21fed13a735bd23a51cc" + "url": "https://github.com/GoogleCloudPlatform/google-cloud-php.git", + "reference": "79a765fdcb2be9e756f8bf9283ad3626cd2f61d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/google/google-auth-library-php/zipball/47c3c6bece495e58381a21fed13a735bd23a51cc", - "reference": "47c3c6bece495e58381a21fed13a735bd23a51cc", + "url": "https://api.github.com/repos/GoogleCloudPlatform/google-cloud-php/zipball/79a765fdcb2be9e756f8bf9283ad3626cd2f61d4", + "reference": "79a765fdcb2be9e756f8bf9283ad3626cd2f61d4", "shasum": "" }, "require": { - "firebase/php-jwt": "~2.0|~3.0", - "guzzlehttp/guzzle": "~5.3|~6.0", - "guzzlehttp/psr7": "~1.2", - "php": ">=5.4", - "psr/cache": "^1.0", - "psr/http-message": "^1.0" + "google/auth": "0.10", + "guzzlehttp/guzzle": "~5.2|~6.0", + "guzzlehttp/psr7": "^1.2", + "monolog/monolog": "~1", + "php": ">=5.5", + "psr/http-message": "1.0.*", + "rize/uri-template": "~0.3" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^1.11", - "phpunit/phpunit": "3.7.*" + "james-heinrich/getid3": "^1.9", + "league/json-guard": "^0.3", + "phpdocumentor/phpdocumentor": "2.8.*", + "phpunit/phpunit": "4.8.*", + "squizlabs/php_codesniffer": "2.*", + "symfony/console": "2.*" + }, + "suggest": { + "google/gax": "Required to support gRPC", + "google/proto-client-php": "Required to support gRPC", + "james-heinrich/getid3": "Allows the Google Cloud Speech client to determine sample rate and encoding of audio inputs" }, "type": "library", "autoload": { - "classmap": [ - "src/" - ], "psr-4": { - "Google\\Auth\\": "src" + "Google\\Cloud\\": "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", + "authors": [ + { + "name": "John Pedrie", + "email": "john@pedrie.com" + }, + { + "name": "Dave Supplee", + "email": "dwsupplee@gmail.com" + } + ], + "description": "Google Cloud Client Library", + "homepage": "http://github.com/GoogleCloudPlatform/google-cloud-php", "keywords": [ - "Authentication", + "big query", + "bigquery", + "cloud", + "datastore", + "gcs", "google", - "oauth2" - ], - "time": "2016-06-01 22:07:52" + "google api", + "google api client", + "google apis", + "google apis client", + "google cloud", + "google cloud platform", + "natural language", + "pub sub", + "pubsub", + "speech", + "stackdriver logging", + "storage", + "translate", + "vision" + ], + "time": "2016-09-09 14:17:08" }, { "name": "guzzlehttp/guzzle", @@ -365,16 +353,16 @@ }, { "name": "monolog/monolog", - "version": "1.20.0", + "version": "1.21.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037" + "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/55841909e2bcde01b5318c35f2b74f8ecc86e037", - "reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f42fbdfd53e306bda545845e4dbfd3e72edb4952", + "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952", "shasum": "" }, "require": { @@ -439,99 +427,7 @@ "logging", "psr-3" ], - "time": "2016-07-02 14:02:10" - }, - { - "name": "phpseclib/phpseclib", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "3d265f7c079f5b37d33475f996d7a383c5fc8aeb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/3d265f7c079f5b37d33475f996d7a383c5fc8aeb", - "reference": "3d265f7c079f5b37d33475f996d7a383c5fc8aeb", - "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." - }, - "type": "library", - "autoload": { - "files": [ - "phpseclib/bootstrap.php" - ], - "psr-4": { - "phpseclib\\": "phpseclib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "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" - }, - { - "name": "Graham Campbell", - "email": "graham@alt-three.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": "2016-05-13 01:15:21" + "time": "2016-07-29 03:23:52" }, { "name": "pimple/pimple", @@ -581,16 +477,16 @@ }, { "name": "psr/cache", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/php-fig/cache.git", - "reference": "9e66031f41fbbdda45ee11e93c45d480ccba3eb3" + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/9e66031f41fbbdda45ee11e93c45d480ccba3eb3", - "reference": "9e66031f41fbbdda45ee11e93c45d480ccba3eb3", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", "shasum": "" }, "require": { @@ -623,20 +519,20 @@ "psr", "psr-6" ], - "time": "2015-12-11 02:52:07" + "time": "2016-08-06 20:24:11" }, { "name": "psr/http-message", - "version": "1.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", "shasum": "" }, "require": { @@ -664,6 +560,7 @@ } ], "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ "http", "http-message", @@ -672,7 +569,7 @@ "request", "response" ], - "time": "2015-05-04 20:22:00" + "time": "2016-08-06 14:39:51" }, { "name": "psr/log", @@ -712,6 +609,50 @@ ], "time": "2012-12-21 11:40:51" }, + { + "name": "rize/uri-template", + "version": "0.3.0", + "source": { + "type": "git", + "url": "https://github.com/rize/UriTemplate.git", + "reference": "2496aa674438f1c48fce122ffc44291ad7014717" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rize/UriTemplate/zipball/2496aa674438f1c48fce122ffc44291ad7014717", + "reference": "2496aa674438f1c48fce122ffc44291ad7014717", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Rize\\UriTemplate": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marut K", + "homepage": "http://twitter.com/rezigned" + } + ], + "description": "PHP URI Template (RFC 6570) supports both expansion & extraction", + "keywords": [ + "RFC 6570", + "template", + "uri" + ], + "time": "2015-04-17 16:12:22" + }, { "name": "silex/silex", "version": "v1.3.5", @@ -791,16 +732,16 @@ }, { "name": "symfony/debug", - "version": "v3.1.2", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "06e2d52e307ef880ac739f44ee6c2418ca9e3283" + "reference": "34f6ac18c2974ca5fce68adf419ee7d15def6f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/06e2d52e307ef880ac739f44ee6c2418ca9e3283", - "reference": "06e2d52e307ef880ac739f44ee6c2418ca9e3283", + "url": "https://api.github.com/repos/symfony/debug/zipball/34f6ac18c2974ca5fce68adf419ee7d15def6f11", + "reference": "34f6ac18c2974ca5fce68adf419ee7d15def6f11", "shasum": "" }, "require": { @@ -844,20 +785,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com/", - "time": "2016-06-29 05:41:56" + "time": "2016-08-23 13:39:15" }, { "name": "symfony/event-dispatcher", - "version": "v3.0.8", + "version": "v3.0.9", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "43e9a14f71db135da5c75dd5d383ecff6ada920e" + "reference": "54da3ff63dec3c9c0e32ec3f95a7d94ef64baa00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/43e9a14f71db135da5c75dd5d383ecff6ada920e", - "reference": "43e9a14f71db135da5c75dd5d383ecff6ada920e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/54da3ff63dec3c9c0e32ec3f95a7d94ef64baa00", + "reference": "54da3ff63dec3c9c0e32ec3f95a7d94ef64baa00", "shasum": "" }, "require": { @@ -904,20 +845,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com/", - "time": "2016-06-29 05:40:00" + "time": "2016-07-19 10:44:15" }, { "name": "symfony/http-foundation", - "version": "v3.0.8", + "version": "v3.0.9", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "1341139f906d295baa4f4abd55293d07e25a065a" + "reference": "49ba00f8ede742169cb6b70abe33243f4d673f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1341139f906d295baa4f4abd55293d07e25a065a", - "reference": "1341139f906d295baa4f4abd55293d07e25a065a", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/49ba00f8ede742169cb6b70abe33243f4d673f82", + "reference": "49ba00f8ede742169cb6b70abe33243f4d673f82", "shasum": "" }, "require": { @@ -957,20 +898,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com/", - "time": "2016-06-29 07:02:21" + "time": "2016-07-17 13:54:30" }, { "name": "symfony/http-kernel", - "version": "v3.0.8", + "version": "v3.0.9", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "177b63b2d50b63fa6d82ea41359ed9928cc7a1fb" + "reference": "d97ba4425e36e79c794e7d14ff36f00f081b37b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/177b63b2d50b63fa6d82ea41359ed9928cc7a1fb", - "reference": "177b63b2d50b63fa6d82ea41359ed9928cc7a1fb", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/d97ba4425e36e79c794e7d14ff36f00f081b37b3", + "reference": "d97ba4425e36e79c794e7d14ff36f00f081b37b3", "shasum": "" }, "require": { @@ -1039,7 +980,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com/", - "time": "2016-06-30 16:30:17" + "time": "2016-07-30 09:10:37" }, { "name": "symfony/polyfill-mbstring", @@ -1102,7 +1043,7 @@ }, { "name": "symfony/routing", - "version": "v3.0.8", + "version": "v3.0.9", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", @@ -1177,16 +1118,16 @@ }, { "name": "symfony/twig-bridge", - "version": "v3.0.8", + "version": "v3.0.9", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "aeb38a51575a9a67c48b2f602bf1fd01e3b5527b" + "reference": "34ddcc46f09f6564f03cb61134ee51f3b309aa58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/aeb38a51575a9a67c48b2f602bf1fd01e3b5527b", - "reference": "aeb38a51575a9a67c48b2f602bf1fd01e3b5527b", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/34ddcc46f09f6564f03cb61134ee51f3b309aa58", + "reference": "34ddcc46f09f6564f03cb61134ee51f3b309aa58", "shasum": "" }, "require": { @@ -1207,7 +1148,7 @@ "symfony/stopwatch": "~2.8|~3.0", "symfony/templating": "~2.8|~3.0", "symfony/translation": "~2.8|~3.0", - "symfony/var-dumper": "~2.8|~3.0", + "symfony/var-dumper": "~2.8.9|~3.0.9|~3.1.3|~3.2", "symfony/yaml": "~2.8|~3.0" }, "suggest": { @@ -1254,20 +1195,20 @@ ], "description": "Symfony Twig Bridge", "homepage": "https://symfony.com/", - "time": "2016-06-29 05:40:00" + "time": "2016-07-28 11:13:34" }, { "name": "twig/twig", - "version": "v1.24.1", + "version": "v1.24.2", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "3566d311a92aae4deec6e48682dc5a4528c4a512" + "reference": "33093f6e310e6976baeac7b14f3a6ec02f2d79b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/3566d311a92aae4deec6e48682dc5a4528c4a512", - "reference": "3566d311a92aae4deec6e48682dc5a4528c4a512", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/33093f6e310e6976baeac7b14f3a6ec02f2d79b7", + "reference": "33093f6e310e6976baeac7b14f3a6ec02f2d79b7", "shasum": "" }, "require": { @@ -1315,7 +1256,7 @@ "keywords": [ "templating" ], - "time": "2016-05-30 09:11:59" + "time": "2016-09-01 17:50:53" } ], "packages-dev": [ @@ -2168,23 +2109,23 @@ }, { "name": "sebastian/environment", - "version": "1.3.7", + "version": "1.3.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", - "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^4.8 || ^5.0" }, "type": "library", "extra": { @@ -2214,7 +2155,7 @@ "environment", "hhvm" ], - "time": "2016-05-17 03:18:57" + "time": "2016-08-18 05:49:44" }, { "name": "sebastian/exporter", @@ -2424,16 +2365,16 @@ }, { "name": "symfony/browser-kit", - "version": "v2.8.8", + "version": "v2.8.11", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "7be191464d63441382db763c53907a8eebe9a259" + "reference": "165bf6d1e72cd72f2fe170a070aa2a1f17f2d744" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/7be191464d63441382db763c53907a8eebe9a259", - "reference": "7be191464d63441382db763c53907a8eebe9a259", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/165bf6d1e72cd72f2fe170a070aa2a1f17f2d744", + "reference": "165bf6d1e72cd72f2fe170a070aa2a1f17f2d744", "shasum": "" }, "require": { @@ -2477,20 +2418,20 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com/", - "time": "2016-06-29 05:29:29" + "time": "2016-09-06 10:55:00" }, { "name": "symfony/css-selector", - "version": "v2.8.8", + "version": "v2.8.11", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "9da4c615ba303850986e0480cc472bf704cfdb64" + "reference": "71c8c3a04c126300c37089b1baa7c6322dfb845f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/9da4c615ba303850986e0480cc472bf704cfdb64", - "reference": "9da4c615ba303850986e0480cc472bf704cfdb64", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/71c8c3a04c126300c37089b1baa7c6322dfb845f", + "reference": "71c8c3a04c126300c37089b1baa7c6322dfb845f", "shasum": "" }, "require": { @@ -2530,20 +2471,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com/", - "time": "2016-06-29 05:31:50" + "time": "2016-09-06 10:55:00" }, { "name": "symfony/dom-crawler", - "version": "v2.8.8", + "version": "v2.8.11", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "f8c304f5715081c949043902d311480d71adb1e0" + "reference": "aac03b7ea2a7adff10a3599d614e79e6101230ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/f8c304f5715081c949043902d311480d71adb1e0", - "reference": "f8c304f5715081c949043902d311480d71adb1e0", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/aac03b7ea2a7adff10a3599d614e79e6101230ab", + "reference": "aac03b7ea2a7adff10a3599d614e79e6101230ab", "shasum": "" }, "require": { @@ -2586,20 +2527,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com/", - "time": "2016-06-29 05:29:29" + "time": "2016-07-30 07:20:35" }, { "name": "symfony/process", - "version": "v3.1.2", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "5c11a1a4d4016662eeaf0f8757958c7de069f9a0" + "reference": "e64e93041c80e77197ace5ab9385dedb5a143697" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/5c11a1a4d4016662eeaf0f8757958c7de069f9a0", - "reference": "5c11a1a4d4016662eeaf0f8757958c7de069f9a0", + "url": "https://api.github.com/repos/symfony/process/zipball/e64e93041c80e77197ace5ab9385dedb5a143697", + "reference": "e64e93041c80e77197ace5ab9385dedb5a143697", "shasum": "" }, "require": { @@ -2635,20 +2576,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com/", - "time": "2016-06-29 05:42:25" + "time": "2016-08-16 14:58:24" }, { "name": "symfony/yaml", - "version": "v3.1.2", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de" + "reference": "f291ed25eb1435bddbe8a96caaef16469c2a092d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/2884c26ce4c1d61aebf423a8b912950fe7c764de", - "reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de", + "url": "https://api.github.com/repos/symfony/yaml/zipball/f291ed25eb1435bddbe8a96caaef16469c2a092d", + "reference": "f291ed25eb1435bddbe8a96caaef16469c2a092d", "shasum": "" }, "require": { @@ -2684,32 +2625,33 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com/", - "time": "2016-06-29 05:41:56" + "time": "2016-09-02 02:12:52" }, { "name": "webmozart/assert", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde" + "reference": "bb2d123231c095735130cc8f6d31385a44c7b308" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", - "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", + "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308", + "reference": "bb2d123231c095735130cc8f6d31385a44c7b308", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3|^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.6" + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -2733,7 +2675,7 @@ "check", "validate" ], - "time": "2015-08-24 13:29:44" + "time": "2016-08-09 15:02:57" } ], "aliases": [], diff --git a/pubsub/web/index.php b/pubsub/app/index.php similarity index 75% rename from pubsub/web/index.php rename to pubsub/app/index.php index d828ca5780..eda78770b1 100644 --- a/pubsub/web/index.php +++ b/pubsub/app/index.php @@ -17,10 +17,13 @@ */ // composer autoloading -require_once __DIR__ . '/../vendor/autoload.php'; +require_once __DIR__ . '/vendor/autoload.php'; -$app = require_once __DIR__ . '/../src/app.php'; +$app = require_once __DIR__ . '/app.php'; +$app['project_id'] = getenv('GOOGLE_PROJECT_ID'); +$app['topic'] = 'php-example-topic'; +$app['subscription'] = 'php-example-subscription'; $app['debug'] = true; $app->run(); diff --git a/pubsub/app/phpunit.xml.dist b/pubsub/app/phpunit.xml.dist new file mode 100644 index 0000000000..7123ce295a --- /dev/null +++ b/pubsub/app/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + test + + + + + + + + app.php + + + diff --git a/pubsub/templates/pubsub.html.twig b/pubsub/app/pubsub.html.twig similarity index 90% rename from pubsub/templates/pubsub.html.twig rename to pubsub/app/pubsub.html.twig index adace5842d..4a546f8510 100644 --- a/pubsub/templates/pubsub.html.twig +++ b/pubsub/app/pubsub.html.twig @@ -20,7 +20,6 @@ - per seconds. {{ "{{ PubsubController.errorNotice }}" }}

Messages:

@@ -28,6 +27,6 @@
  • {{ "{{ m }}" }}
  • - + diff --git a/pubsub/web/js/pubsub.js b/pubsub/app/pubsub.js similarity index 77% rename from pubsub/web/js/pubsub.js rename to pubsub/app/pubsub.js index 17061058c3..78eb7cd0d5 100644 --- a/pubsub/web/js/pubsub.js +++ b/pubsub/app/pubsub.js @@ -12,11 +12,10 @@ pubsub.PubsubController = function($http, $log, $timeout) { this.promise = null; this.logger = $log; this.http = $http; - this.timeout = $timeout; - this.interval = 1; this.isAutoUpdating = true; this.failCount = 0; this.hasAttemptedToCreateTopicAndSubscription = false; + this.messages = []; this.fetchMessages(); }; @@ -32,10 +31,6 @@ pubsub.PubsubController.prototype.toggleAutoUpdate = function() { if (this.isAutoUpdating) { this.logger.info('Start fetching.'); this.fetchMessages(); - } else if (this.promise !== null) { - this.logger.info('Cancel the promise.'); - this.timeout.cancel(this.promise); - this.promise = null; } }; @@ -77,28 +72,20 @@ pubsub.PubsubController.prototype.sendMessage = function(message) { * Continuously fetches messages from the server. */ pubsub.PubsubController.prototype.fetchMessages = function() { + if (!this.isAutoUpdating) { + return; + } var self = this; self.http.get('/fetch_messages') .success(function(data, status) { - self.messages = data; + self.messages.push.apply(self.messages, data); self.failCount = 0; + self.fetchMessages(); }) .error(function(data, status) { self.logger.error('Failed to receive the messages. Status: ' + status + '.'); self.failCount += 1; + self.fetchMessages(); }); - if (self.failCount < pubsub.PubsubController.MAX_FAILURE_COUNT) { - if (self.isAutoUpdating) { - self.promise = self.timeout( - function() { self.fetchMessages(); }, - self.interval * pubsub.PubsubController.TIMEOUT_MULTIPLIER); - } - } else { - self.errorNotice = 'Maximum failure count reached, ' + - 'so stopped fetching messages.'; - self.logger.error(self.errorNotice); - self.isAutoUpdating = false; - self.failCount = 0; - } }; diff --git a/pubsub/test/DeployAppEngineFlexTest.php b/pubsub/app/test/DeployAppEngineFlexTest.php similarity index 84% rename from pubsub/test/DeployAppEngineFlexTest.php rename to pubsub/app/test/DeployAppEngineFlexTest.php index 7f95eea6d6..b28b7671aa 100644 --- a/pubsub/test/DeployAppEngineFlexTest.php +++ b/pubsub/app/test/DeployAppEngineFlexTest.php @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -namespace Google\Cloud\Samples\pubsub\test; +namespace Google\Cloud\Samples\PubSub\test; use Google\Cloud\TestUtils\AppEngineDeploymentTrait; use Google\Cloud\TestUtils\FileUtil; @@ -27,11 +27,11 @@ class DeployAppEngineFlexTest extends \PHPUnit_Framework_TestCase public function beforeDeploy() { $tmpDir = FileUtil::cloneDirectoryIntoTmp(__DIR__ . '/..'); - FileUtil::copyDir(__DIR__ . '/../../appengine/flexible/pubsub', $tmpDir); + FileUtil::copyDir(__DIR__ . '/../../../appengine/flexible/pubsub', $tmpDir); self::$gcloudWrapper->setDir($tmpDir); chdir($tmpDir); $appYaml = Yaml::parse(file_get_contents('app.yaml')); - $appYaml['env_variables']['GOOGLE_PROJECT_NAME'] = + $appYaml['env_variables']['GOOGLE_PROJECT_ID'] = getenv('GOOGLE_PROJECT_ID'); file_put_contents('app.yaml', Yaml::dump($appYaml)); } @@ -46,10 +46,6 @@ public function testIndex() public function testSendMessage() { - $resp = $this->client->request('POST', '/create_topic_and_subscription'); - $this->assertEquals('200', $resp->getStatusCode(), - '/create_topic_and_subscription status code'); - $resp = $this->client->request('POST', '/send_message', [ 'form_params' => [ 'message' => 'Good day!' diff --git a/pubsub/test/pubsubTest.php b/pubsub/app/test/appTest.php similarity index 67% rename from pubsub/test/pubsubTest.php rename to pubsub/app/test/appTest.php index 425b9d332d..695614f1a3 100644 --- a/pubsub/test/pubsubTest.php +++ b/pubsub/app/test/appTest.php @@ -15,21 +15,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -namespace Google\Cloud\Samples\pubsub\test; +namespace Google\Cloud\Samples\PubSub\Tests; use Silex\WebTestCase; use Symfony\Component\HttpKernel\Client; -class pubsubTest extends WebTestCase +class appTest extends WebTestCase { public function createApplication() { // pull the app and set parameters for testing - $app = require __DIR__ . '/../src/app.php'; + $app = require __DIR__ . '/../app.php'; $app['session.test'] = true; $app['debug'] = true; $app['project_id'] = 'cloud-samples-tests-php'; + $app['topic'] = getenv('GOOGLE_PUBSUB_TOPIC'); + $app['subscription'] = getenv('GOOGLE_PUBSUB_SUBSCRIPTION'); // this will be set by travis, but may not be set locally if (!$credentials = getenv('GOOGLE_APPLICATION_CREDENTIALS')) { @@ -40,6 +42,9 @@ public function createApplication() if (!file_exists($credentials) || 0 == filesize($credentials)) { $this->markTestSkipped('credentials not found'); } + if (empty($app['topic']) || empty($app['subscription'])) { + $this->markTestSkipped('topic or subscription not set'); + } // prevent HTML error exceptions unset($app['exception_handler']); @@ -61,22 +66,8 @@ public function testInitialPage() public function testFetchMessages() { - // set up mock objects - $apiResponse = new \Google_Service_Datastore_RunQueryResponse(); - $apiResponse->setBatch(new \Google_Service_Datastore_QueryResultBatch()); - $apiClient = $this->getMock('Google_Client'); - $apiClient - ->expects($this->once()) - ->method('execute') - ->will($this->returnValue($apiResponse)); - $apiClient - ->expects($this->once()) - ->method('getLogger') - ->will($this->returnValue($this->getMock('Psr\Log\LoggerInterface'))); - // create the application $app = $this->createApplication(); - $app['google_client'] = $apiClient; $client = new Client($app); // make the request @@ -86,25 +77,12 @@ public function testFetchMessages() $response = $client->getResponse(); $this->assertTrue($response->isOk()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); - $this->assertEquals('[]', $response->getContent()); + $this->assertTrue(is_array(json_decode($response->getContent()))); } public function testSendMessage() - { - // set up mock objects - $apiClient = $this->getMock('Google_Client'); - $apiClient - ->expects($this->once()) - ->method('execute') - ->will($this->returnValue(true)); - $apiClient - ->expects($this->once()) - ->method('getLogger') - ->will($this->returnValue($this->getMock('Psr\Log\LoggerInterface'))); - - // create the application + { // create the application $app = $this->createApplication(); - $app['google_client'] = $apiClient; $client = new Client($app); // make the request diff --git a/pubsub/app/test/bootstrap.php b/pubsub/app/test/bootstrap.php new file mode 100644 index 0000000000..f91a988cc6 --- /dev/null +++ b/pubsub/app/test/bootstrap.php @@ -0,0 +1,4 @@ +=5.4", + "google/cloud": "0.8", + "symfony/console": " ^3.0" + } +} diff --git a/pubsub/cli/composer.lock b/pubsub/cli/composer.lock new file mode 100644 index 0000000000..36d40228d1 --- /dev/null +++ b/pubsub/cli/composer.lock @@ -0,0 +1,740 @@ +{ + "_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": "ef0b715a5c854ae0ab054843d949c5b2", + "content-hash": "c69e63ad9272ddc9e74454e898835b53", + "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/auth", + "version": "v0.10", + "source": { + "type": "git", + "url": "https://github.com/google/google-auth-library-php.git", + "reference": "760e3fbe4064c0525c22e27e5374eada3c103da8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/google/google-auth-library-php/zipball/760e3fbe4064c0525c22e27e5374eada3c103da8", + "reference": "760e3fbe4064c0525c22e27e5374eada3c103da8", + "shasum": "" + }, + "require": { + "firebase/php-jwt": "~2.0|~3.0", + "guzzlehttp/guzzle": "~5.3|~6.0", + "guzzlehttp/psr7": "~1.2", + "php": ">=5.4", + "psr/cache": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^1.11", + "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": "2016-08-02 22:00:48" + }, + { + "name": "google/cloud", + "version": "v0.8.0", + "source": { + "type": "git", + "url": "https://github.com/GoogleCloudPlatform/google-cloud-php.git", + "reference": "79a765fdcb2be9e756f8bf9283ad3626cd2f61d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GoogleCloudPlatform/google-cloud-php/zipball/79a765fdcb2be9e756f8bf9283ad3626cd2f61d4", + "reference": "79a765fdcb2be9e756f8bf9283ad3626cd2f61d4", + "shasum": "" + }, + "require": { + "google/auth": "0.10", + "guzzlehttp/guzzle": "~5.2|~6.0", + "guzzlehttp/psr7": "^1.2", + "monolog/monolog": "~1", + "php": ">=5.5", + "psr/http-message": "1.0.*", + "rize/uri-template": "~0.3" + }, + "require-dev": { + "james-heinrich/getid3": "^1.9", + "league/json-guard": "^0.3", + "phpdocumentor/phpdocumentor": "2.8.*", + "phpunit/phpunit": "4.8.*", + "squizlabs/php_codesniffer": "2.*", + "symfony/console": "2.*" + }, + "suggest": { + "google/gax": "Required to support gRPC", + "google/proto-client-php": "Required to support gRPC", + "james-heinrich/getid3": "Allows the Google Cloud Speech client to determine sample rate and encoding of audio inputs" + }, + "type": "library", + "autoload": { + "psr-4": { + "Google\\Cloud\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "John Pedrie", + "email": "john@pedrie.com" + }, + { + "name": "Dave Supplee", + "email": "dwsupplee@gmail.com" + } + ], + "description": "Google Cloud Client Library", + "homepage": "http://github.com/GoogleCloudPlatform/google-cloud-php", + "keywords": [ + "big query", + "bigquery", + "cloud", + "datastore", + "gcs", + "google", + "google api", + "google api client", + "google apis", + "google apis client", + "google cloud", + "google cloud platform", + "natural language", + "pub sub", + "pubsub", + "speech", + "stackdriver logging", + "storage", + "translate", + "vision" + ], + "time": "2016-09-09 14:17:08" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.2.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427", + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.3.1", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.0", + "psr/log": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.2-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "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", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2016-07-15 17:22:37" + }, + { + "name": "guzzlehttp/promises", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-05-18 16:56:05" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "PSR-7 message implementation", + "keywords": [ + "http", + "message", + "stream", + "uri" + ], + "time": "2016-06-24 23:00:38" + }, + { + "name": "monolog/monolog", + "version": "1.21.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f42fbdfd53e306bda545845e4dbfd3e72edb4952", + "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952", + "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-amqplib/php-amqplib": "~2.4", + "php-console/php-console": "^3.1.3", + "phpunit/phpunit": "~4.5", + "phpunit/phpunit-mock-objects": "2.3.0", + "ruflin/elastica": ">=0.90 <3.0", + "sentry/sentry": "^0.13", + "swiftmailer/swiftmailer": "~5.3" + }, + "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", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "php-console/php-console": "Allow sending log messages to Google Chrome", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "sentry/sentry": "Allow sending log messages to a Sentry server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.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": "2016-07-29 03:23:52" + }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "time": "2016-08-06 20:24:11" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06 14:39:51" + }, + { + "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": "rize/uri-template", + "version": "0.3.0", + "source": { + "type": "git", + "url": "https://github.com/rize/UriTemplate.git", + "reference": "2496aa674438f1c48fce122ffc44291ad7014717" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rize/UriTemplate/zipball/2496aa674438f1c48fce122ffc44291ad7014717", + "reference": "2496aa674438f1c48fce122ffc44291ad7014717", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Rize\\UriTemplate": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marut K", + "homepage": "http://twitter.com/rezigned" + } + ], + "description": "PHP URI Template (RFC 6570) supports both expansion & extraction", + "keywords": [ + "RFC 6570", + "template", + "uri" + ], + "time": "2015-04-17 16:12:22" + }, + { + "name": "symfony/console", + "version": "v3.1.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "8ea494c34f0f772c3954b5fbe00bffc5a435e563" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/8ea494c34f0f772c3954b5fbe00bffc5a435e563", + "reference": "8ea494c34f0f772c3954b5fbe00bffc5a435e563", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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 Console Component", + "homepage": "https://symfony.com/", + "time": "2016-08-19 06:48:39" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "dff51f72b0706335131b00a7f49606168c582594" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", + "reference": "dff51f72b0706335131b00a7f49606168c582594", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2016-05-18 14:26:46" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.4" + }, + "platform-dev": [] +} diff --git a/pubsub/phpunit.xml b/pubsub/cli/phpunit.xml.dist similarity index 100% rename from pubsub/phpunit.xml rename to pubsub/cli/phpunit.xml.dist diff --git a/pubsub/cli/pubsub.php b/pubsub/cli/pubsub.php new file mode 100644 index 0000000000..b7728d6a6e --- /dev/null +++ b/pubsub/cli/pubsub.php @@ -0,0 +1,14 @@ +add(new SubscriptionCommand()); +$application->add(new TopicCommand()); +$application->add(new IamCommand()); +$application->run(); diff --git a/pubsub/cli/src/IamCommand.php b/pubsub/cli/src/IamCommand.php new file mode 100644 index 0000000000..d87bfb697f --- /dev/null +++ b/pubsub/cli/src/IamCommand.php @@ -0,0 +1,109 @@ +setName('iam') + ->setDescription('Manage IAM for Pub\Sub') + ->setHelp(<<%command.name% command manages Pub\Sub IAM policies. + + php %command.full_name% --topic my-topic + + php %command.full_name% --subscription my-subscription + +EOF + ) + ->addOption( + 'project', + null, + InputOption::VALUE_REQUIRED, + 'The Google Cloud Platform project name to use for this invocation. ' . + 'If omitted then the current gcloud project is assumed. ' + ) + ->addOption( + 'topic', + null, + InputOption::VALUE_REQUIRED, + 'The topic name. ' + ) + ->addOption( + 'subscription', + null, + InputOption::VALUE_REQUIRED, + 'The subscription name. ' + ) + ->addOption( + 'add-user', + null, + InputOption::VALUE_REQUIRED, + 'Create the IAM for the supplied user email. ' + ) + ->addOption( + 'test', + null, + InputOption::VALUE_NONE, + 'Test the IAM policy. ' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + if (!$projectId = $input->getOption('project')) { + $projectId = $this->getProjectIdFromGcloud(); + } + $topicName = $input->getOption('topic'); + $subscriptionName = $input->getOption('subscription'); + if ($topicName) { + if ($userEmail = $input->getOption('add-user')) { + set_topic_policy($projectId, $topicName, $userEmail); + } elseif ($input->getOption('test')) { + test_topic_permissions($projectId, $topicName); + } else { + get_topic_policy($projectId, $topicName); + } + } elseif ($subscriptionName) { + if ($userEmail = $input->getOption('add-user')) { + set_subscription_policy($projectId, $subscriptionName, $userEmail); + } elseif ($input->getOption('test')) { + test_subscription_permissions($projectId, $subscriptionName); + } else { + get_subscription_policy($projectId, $subscriptionName); + } + } else { + throw new \Exception('Must provide "--topic", or "--subscription"'); + } + } +} diff --git a/pubsub/cli/src/ProjectIdTrait.php b/pubsub/cli/src/ProjectIdTrait.php new file mode 100644 index 0000000000..97c836fd7b --- /dev/null +++ b/pubsub/cli/src/ProjectIdTrait.php @@ -0,0 +1,36 @@ +/dev/null", $output, $return_var); + + if (0 === $return_var) { + return array_pop($output); + } + + throw new Exception('Could not derive a project ID from gcloud. ' . + 'You must supply a project ID using --project'); + } +} diff --git a/pubsub/cli/src/SubscriptionCommand.php b/pubsub/cli/src/SubscriptionCommand.php new file mode 100644 index 0000000000..59627523b3 --- /dev/null +++ b/pubsub/cli/src/SubscriptionCommand.php @@ -0,0 +1,109 @@ +setName('subscription') + ->setDescription('Manage subscriptions for Pub\Sub') + ->setHelp(<<%command.name% command manages Pub\Sub subscriptions. + + php %command.full_name% + +EOF + ) + ->addArgument( + 'subscription', + InputArgument::OPTIONAL, + 'The subscription name' + ) + ->addOption( + 'project', + null, + InputOption::VALUE_REQUIRED, + 'The Google Cloud Platform project name to use for this invocation. ' . + 'If omitted then the current gcloud project is assumed. ' + ) + ->addOption( + 'create', + null, + InputOption::VALUE_NONE, + 'Create the subscription. ' + ) + ->addOption( + 'topic', + null, + InputOption::VALUE_REQUIRED, + 'The topic for the subscription (when using --create). ' + ) + ->addOption( + 'endpoint', + null, + InputOption::VALUE_REQUIRED, + 'An optional endpoint for push subscriptions.' + ) + ->addOption( + 'delete', + null, + InputOption::VALUE_NONE, + 'Delete the subscription. ' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + if (!$projectId = $input->getOption('project')) { + $projectId = $this->getProjectIdFromGcloud(); + } + $subscriptionName = $input->getArgument('subscription'); + if (empty($subscriptionName)) { + list_subscriptions($projectId); + } elseif ($input->getOption('create')) { + if (!$topicName = $input->getOption('topic')) { + throw new \Exception('--topic is required when creating a subscription'); + } + if ($endpoint = $input->getOption('endpoint')) { + create_push_subscription($projectId, $topicName, $subscriptionName, $endpoint); + } else { + create_subscription($projectId, $topicName, $subscriptionName); + } + } elseif ($input->getOption('delete')) { + delete_subscription($projectId, $subscriptionName); + } else { + pull_messages($projectId, $subscriptionName); + } + } +} diff --git a/pubsub/cli/src/TopicCommand.php b/pubsub/cli/src/TopicCommand.php new file mode 100644 index 0000000000..e4197edef9 --- /dev/null +++ b/pubsub/cli/src/TopicCommand.php @@ -0,0 +1,97 @@ +setName('topic') + ->setDescription('Manage topics for Pub\Sub') + ->setHelp(<<%command.name% command manages Pub\Sub topics. + + php %command.full_name% + +EOF + ) + ->addArgument( + 'topic', + InputArgument::OPTIONAL, + 'The topic name' + ) + ->addArgument( + 'message', + InputArgument::OPTIONAL, + 'A message to publish to the topic' + ) + ->addOption( + 'project', + null, + InputOption::VALUE_REQUIRED, + 'The Google Cloud Platform project name to use for this invocation. ' . + 'If omitted then the current gcloud project is assumed. ' + ) + ->addOption( + 'create', + null, + InputOption::VALUE_NONE, + 'Create the topic. ' + ) + ->addOption( + 'delete', + null, + InputOption::VALUE_NONE, + 'Delete the topic. ' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + if (!$projectId = $input->getOption('project')) { + $projectId = $this->getProjectIdFromGcloud(); + } + $topicName = $input->getArgument('topic'); + if (empty($topicName)) { + list_topics($projectId); + } elseif ($input->getOption('create')) { + create_topic($projectId, $topicName); + } elseif ($input->getOption('delete')) { + delete_topic($projectId, $topicName); + } elseif ($message = $input->getArgument('message')) { + publish_message($projectId, $topicName, $message); + } else { + throw new \Exception('Must provide "--create", "--delete" or "message" with topic name'); + } + } +} diff --git a/pubsub/cli/src/functions/create_push_subscription.php b/pubsub/cli/src/functions/create_push_subscription.php new file mode 100644 index 0000000000..45d934b7ab --- /dev/null +++ b/pubsub/cli/src/functions/create_push_subscription.php @@ -0,0 +1,48 @@ + $projectId, + ]); + $topic = $pubsub->topic($topicName); + $subscription = $topic->subscription($subscriptionName); + $subscription->create([ + 'endpoint' => $endpoint + ]); +} +# [END create_push_subscription] diff --git a/pubsub/cli/src/functions/create_subscription.php b/pubsub/cli/src/functions/create_subscription.php new file mode 100644 index 0000000000..824843616d --- /dev/null +++ b/pubsub/cli/src/functions/create_subscription.php @@ -0,0 +1,47 @@ + $projectId, + ]); + $topic = $pubsub->topic($topicName); + $subscription = $topic->subscription($subscriptionName); + $subscription->create(); + + printf('Subscription created: %s' . PHP_EOL, $subscription->name()); +} +# [END create_subscription] diff --git a/pubsub/cli/src/functions/create_topic.php b/pubsub/cli/src/functions/create_topic.php new file mode 100644 index 0000000000..092e418a71 --- /dev/null +++ b/pubsub/cli/src/functions/create_topic.php @@ -0,0 +1,44 @@ + $projectId, + ]); + $topic = $pubsub->createTopic($topicName); + + printf('Topic created: %s' . PHP_EOL, $topic->name()); +} +# [END create_topic] diff --git a/pubsub/cli/src/functions/delete_subscription.php b/pubsub/cli/src/functions/delete_subscription.php new file mode 100644 index 0000000000..f9ed94448c --- /dev/null +++ b/pubsub/cli/src/functions/delete_subscription.php @@ -0,0 +1,45 @@ + $projectId, + ]); + $subscription = $pubsub->subscription($subscriptionName); + $subscription->delete(); + + printf('Subscription deleted: %s' . PHP_EOL, $subscription->name()); +} +# [END delete_subscription] diff --git a/pubsub/cli/src/functions/delete_topic.php b/pubsub/cli/src/functions/delete_topic.php new file mode 100644 index 0000000000..4977571e2f --- /dev/null +++ b/pubsub/cli/src/functions/delete_topic.php @@ -0,0 +1,45 @@ + $projectId, + ]); + $topic = $pubsub->topic($topicName); + $topic->delete(); + + printf('Topic deleted: %s' . PHP_EOL, $topic->name()); +} +# [END delete_topic] diff --git a/pubsub/cli/src/functions/get_subscription_policy.php b/pubsub/cli/src/functions/get_subscription_policy.php new file mode 100644 index 0000000000..5a9051ac99 --- /dev/null +++ b/pubsub/cli/src/functions/get_subscription_policy.php @@ -0,0 +1,44 @@ + $projectId, + ]); + $subscription = $pubsub->subscription($subscriptionName); + $policy = $subscription->iam()->policy(); + print_r($policy); +} +# [END get_subscription_policy] diff --git a/pubsub/cli/src/functions/get_topic_policy.php b/pubsub/cli/src/functions/get_topic_policy.php new file mode 100644 index 0000000000..96ce432512 --- /dev/null +++ b/pubsub/cli/src/functions/get_topic_policy.php @@ -0,0 +1,44 @@ + $projectId, + ]); + $topic = $pubsub->topic($topicName); + $policy = $topic->iam()->policy(); + print_r($policy); +} +# [END get_topic_policy] diff --git a/pubsub/cli/src/functions/list_subscriptions.php b/pubsub/cli/src/functions/list_subscriptions.php new file mode 100644 index 0000000000..bfe1c8f79a --- /dev/null +++ b/pubsub/cli/src/functions/list_subscriptions.php @@ -0,0 +1,43 @@ + $projectId, + ]); + foreach ($pubsub->subscriptions() as $subscription) { + printf('Subscription: %s' . PHP_EOL, $subscription->name()); + } +} +# [END list_subscriptions] diff --git a/pubsub/cli/src/functions/list_topics.php b/pubsub/cli/src/functions/list_topics.php new file mode 100644 index 0000000000..220d1799ce --- /dev/null +++ b/pubsub/cli/src/functions/list_topics.php @@ -0,0 +1,43 @@ + $projectId, + ]); + foreach ($pubsub->topics() as $topic) { + printf('Topic: %s' . PHP_EOL, $topic->name()); + } +} +# [END list_topics] diff --git a/pubsub/cli/src/functions/publish_message.php b/pubsub/cli/src/functions/publish_message.php new file mode 100644 index 0000000000..b29b5a005c --- /dev/null +++ b/pubsub/cli/src/functions/publish_message.php @@ -0,0 +1,45 @@ + $projectId, + ]); + $topic = $pubsub->topic($topicName); + $topic->publish(['data' => $message]); + print('Message published' . PHP_EOL); +} +# [END publish_message] diff --git a/pubsub/cli/src/functions/pubsub_client.php b/pubsub/cli/src/functions/pubsub_client.php new file mode 100644 index 0000000000..9da836c73a --- /dev/null +++ b/pubsub/cli/src/functions/pubsub_client.php @@ -0,0 +1,42 @@ + $projectId, +]); +# [END build_service] +return $pubsub; diff --git a/pubsub/cli/src/functions/pull_messages.php b/pubsub/cli/src/functions/pull_messages.php new file mode 100644 index 0000000000..c04d486032 --- /dev/null +++ b/pubsub/cli/src/functions/pull_messages.php @@ -0,0 +1,46 @@ + $projectId, + ]); + $subscription = $pubsub->subscription($subscriptionName); + foreach ($subscription->pull() as $message) { + $messageData = $message['message']['data']; + printf('Message: %s' . PHP_EOL, base64_decode($messageData)); + } +} +# [END pull_message] diff --git a/pubsub/cli/src/functions/set_subscription_policy.php b/pubsub/cli/src/functions/set_subscription_policy.php new file mode 100644 index 0000000000..ca6999bc69 --- /dev/null +++ b/pubsub/cli/src/functions/set_subscription_policy.php @@ -0,0 +1,53 @@ + $projectId, + ]); + $subscription = $pubsub->subscription($subscriptionName); + $policy = $subscription->iam()->policy(); + $policy['bindings'][] = [ + 'role' => 'roles/pubsub.subscriber', + 'members' => ['user:' . $userEmail] + ]; + $subscription->iam()->setPolicy($policy); + + printf('User %s added to policy for %s' . PHP_EOL, + $userEmail, + $subscriptionName); +} +# [END set_subscription_policy] diff --git a/pubsub/cli/src/functions/set_topic_policy.php b/pubsub/cli/src/functions/set_topic_policy.php new file mode 100644 index 0000000000..3c605a9c40 --- /dev/null +++ b/pubsub/cli/src/functions/set_topic_policy.php @@ -0,0 +1,53 @@ + $projectId, + ]); + $topic = $pubsub->topic($topicName); + $policy = $topic->iam()->policy(); + $policy['bindings'][] = [ + 'role' => 'roles/pubsub.publisher', + 'members' => ['user:' . $userEmail] + ]; + $topic->iam()->setPolicy($policy); + + printf('User %s added to policy for %s' . PHP_EOL, + $userEmail, + $topicName); +} +# [END set_topic_policy] diff --git a/pubsub/cli/src/functions/test_subscription_permissions.php b/pubsub/cli/src/functions/test_subscription_permissions.php new file mode 100644 index 0000000000..15a4a4ae06 --- /dev/null +++ b/pubsub/cli/src/functions/test_subscription_permissions.php @@ -0,0 +1,49 @@ + $projectId, + ]); + $subscription = $pubsub->subscription($subscriptionName); + $permissions = $subscription->iam()->testPermissions([ + 'pubsub.subscriptions.consume', + 'pubsub.subscriptions.update' + ]); + foreach ($permissions['permissions'] as $permission) { + printf('Permission: %s' . PHP_EOL, $permission); + } +} +# [END test_subscription_permissions] diff --git a/pubsub/cli/src/functions/test_topic_permissions.php b/pubsub/cli/src/functions/test_topic_permissions.php new file mode 100644 index 0000000000..2813c92d14 --- /dev/null +++ b/pubsub/cli/src/functions/test_topic_permissions.php @@ -0,0 +1,50 @@ + $projectId, + ]); + $topic = $pubsub->topic($topicName); + $permissions = $topic->iam()->testPermissions([ + 'pubsub.topics.attachSubscription', + 'pubsub.topics.publish', + 'pubsub.topics.update' + ]); + foreach ($permissions['permissions'] as $permission) { + printf('Permission: %s' . PHP_EOL, $permission); + } +} +# [END test_topic_permissions] diff --git a/pubsub/cli/test/FunctionsTest.php b/pubsub/cli/test/FunctionsTest.php new file mode 100644 index 0000000000..d2c5fc64af --- /dev/null +++ b/pubsub/cli/test/FunctionsTest.php @@ -0,0 +1,37 @@ +markTestSkipped('No project ID'); + } + + $pubsub = require __DIR__ . '/../src/functions/pubsub_client.php'; + + $this->assertInstanceOf(PubSubClient::class, $pubsub); + } +} diff --git a/pubsub/cli/test/IamCommandTest.php b/pubsub/cli/test/IamCommandTest.php new file mode 100644 index 0000000000..e3ac4aea4e --- /dev/null +++ b/pubsub/cli/test/IamCommandTest.php @@ -0,0 +1,199 @@ + 0; + } + + public function testSubscriptionPolicy() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$subscription = getenv('GOOGLE_PUBSUB_SUBSCRIPTION')) { + $this->markTestSkipped('No pubsub subscription name'); + } + + $application = new Application(); + $application->add(new IamCommand()); + $commandTester = new CommandTester($application->get('iam')); + $commandTester->execute( + [ + '--subscription' => $subscription, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex(sprintf('/etag/', $subscription)); + } + + public function testTopicPolicy() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$topic = getenv('GOOGLE_PUBSUB_TOPIC')) { + $this->markTestSkipped('No pubsub topic name'); + } + + $application = new Application(); + $application->add(new IamCommand()); + $commandTester = new CommandTester($application->get('iam')); + $commandTester->execute( + [ + '--topic' => $topic, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex(sprintf('/etag/', $topic)); + } + + public function testCreateSubscriptionPolicy() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$subscription = getenv('GOOGLE_PUBSUB_SUBSCRIPTION')) { + $this->markTestSkipped('No pubsub subscription name'); + } + $userEmail = 'betterbrent@google.com'; + + $application = new Application(); + $application->add(new IamCommand()); + $commandTester = new CommandTester($application->get('iam')); + $commandTester->execute( + [ + '--subscription' => $subscription, + '--add-user' => $userEmail, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex(sprintf('/User %s added to policy for %s/', $userEmail, $subscription)); + } + + public function testCreateTopicPolicy() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$topic = getenv('GOOGLE_PUBSUB_TOPIC')) { + $this->markTestSkipped('No pubsub topic name'); + } + $userEmail = 'betterbrent@google.com'; + + $application = new Application(); + $application->add(new IamCommand()); + $commandTester = new CommandTester($application->get('iam')); + $commandTester->execute( + [ + '--topic' => $topic, + '--add-user' => $userEmail, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex(sprintf('/User %s added to policy for %s/', $userEmail, $topic)); + } + + public function testTestSubscriptionPolicy() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$subscription = getenv('GOOGLE_PUBSUB_SUBSCRIPTION')) { + $this->markTestSkipped('No pubsub subscription name'); + } + + $application = new Application(); + $application->add(new IamCommand()); + $commandTester = new CommandTester($application->get('iam')); + $commandTester->execute( + [ + '--subscription' => $subscription, + '--test' => true, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex('/Permission: pubsub.subscriptions.consume/'); + } + + public function testTestTopicPolicy() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$topic = getenv('GOOGLE_PUBSUB_TOPIC')) { + $this->markTestSkipped('No pubsub topic name'); + } + + $application = new Application(); + $application->add(new IamCommand()); + $commandTester = new CommandTester($application->get('iam')); + $commandTester->execute( + [ + '--topic' => $topic, + '--test' => true, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex('/Permission: pubsub.topics.attachSubscription/'); + } +} diff --git a/pubsub/cli/test/SubscriptionCommandTest.php b/pubsub/cli/test/SubscriptionCommandTest.php new file mode 100644 index 0000000000..90cd088dbf --- /dev/null +++ b/pubsub/cli/test/SubscriptionCommandTest.php @@ -0,0 +1,189 @@ + 0; + } + + public function testListSubscriptions() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$subscription = getenv('GOOGLE_PUBSUB_SUBSCRIPTION')) { + $this->markTestSkipped('No pubsub subscription name'); + } + + $application = new Application(); + $application->add(new SubscriptionCommand()); + $commandTester = new CommandTester($application->get('subscription')); + $commandTester->execute( + [ + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex(sprintf('/%s/', $subscription)); + } + + public function testCreateAndDeleteSubscription() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$topic = getenv('GOOGLE_PUBSUB_TOPIC')) { + $this->markTestSkipped('No pubsub topic name'); + } + $subscription = 'test-subscription-' . rand(); + $application = new Application(); + $application->add(new SubscriptionCommand()); + $commandTester = new CommandTester($application->get('subscription')); + $commandTester->execute( + [ + 'subscription' => $subscription, + '--topic' => $topic, + '--create' => true, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex('/Subscription created:/'); + $this->expectOutputRegex(sprintf('/%s/', $subscription)); + + $commandTester->execute( + [ + 'subscription' => $subscription, + '--delete' => true, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex('/Subscription deleted:/'); + $this->expectOutputRegex(sprintf('/%s/', $subscription)); + } + + public function testCreateAndDeletePushSubscription() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$topic = getenv('GOOGLE_PUBSUB_TOPIC')) { + $this->markTestSkipped('No pubsub topic name'); + } + $subscription = 'test-subscription-' . rand(); + $application = new Application(); + $application->add(new SubscriptionCommand()); + $commandTester = new CommandTester($application->get('subscription')); + $commandTester->execute( + [ + 'subscription' => $subscription, + '--topic' => $topic, + '--endpoint' => 'https://example.com/receive_message', + '--create' => true, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex('/Subscription created:/'); + $this->expectOutputRegex(sprintf('/%s/', $subscription)); + + $commandTester->execute( + [ + 'subscription' => $subscription, + '--delete' => true, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex('/Subscription deleted:/'); + $this->expectOutputRegex(sprintf('/%s/', $subscription)); + } + + public function testPullMessages() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$topic = getenv('GOOGLE_PUBSUB_TOPIC')) { + $this->markTestSkipped('No pubsub topic name'); + } + if (!$subscription = getenv('GOOGLE_PUBSUB_SUBSCRIPTION')) { + $this->markTestSkipped('No pubsub subscription name'); + } + + $application = new Application(); + $application->add(new TopicCommand()); + $application->add(new SubscriptionCommand()); + $commandTester = new CommandTester($application->get('topic')); + $commandTester->execute( + [ + 'topic' => $topic, + 'message' => 'This is a test message', + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex('/Message published/'); + + $application->add(new SubscriptionCommand()); + $commandTester = new CommandTester($application->get('subscription')); + $commandTester->execute( + [ + 'subscription' => $subscription, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex('/This is a test message/'); + } +} diff --git a/pubsub/cli/test/TopicCommandTest.php b/pubsub/cli/test/TopicCommandTest.php new file mode 100644 index 0000000000..17e3df41c6 --- /dev/null +++ b/pubsub/cli/test/TopicCommandTest.php @@ -0,0 +1,154 @@ + 0; + } + + public function testListTopics() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$topic = getenv('GOOGLE_PUBSUB_TOPIC')) { + $this->markTestSkipped('No pubsub topic name'); + } + + $application = new Application(); + $application->add(new TopicCommand()); + $commandTester = new CommandTester($application->get('topic')); + $commandTester->execute( + [ + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex(sprintf('/%s/', $topic)); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Must provide "--create", "--delete" or "message" with topic name + */ + public function testGetTopicThrowsException() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$topic = getenv('GOOGLE_PUBSUB_TOPIC')) { + $this->markTestSkipped('No pubsub topic name'); + } + + $application = new Application(); + $application->add(new TopicCommand()); + $commandTester = new CommandTester($application->get('topic')); + $commandTester->execute( + [ + 'topic' => $topic, + '--project' => $projectId, + ], + ['interactive' => false] + ); + } + + public function testCreateAndDeleteTopic() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + $topic = 'test-topic-' . rand(); + $application = new Application(); + $application->add(new TopicCommand()); + $commandTester = new CommandTester($application->get('topic')); + $commandTester->execute( + [ + 'topic' => $topic, + '--create' => true, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex('/Topic created:/'); + $this->expectOutputRegex(sprintf('/%s/', $topic)); + + $commandTester->execute( + [ + 'topic' => $topic, + '--delete' => true, + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex('/Topic deleted:/'); + $this->expectOutputRegex(sprintf('/%s/', $topic)); + } + + public function testTopicMessage() + { + if (!self::$hasCredentials) { + $this->markTestSkipped('No application credentials were found.'); + } + if (!$projectId = getenv('GOOGLE_PROJECT_ID')) { + $this->markTestSkipped('No project ID'); + } + if (!$topic = getenv('GOOGLE_PUBSUB_TOPIC')) { + $this->markTestSkipped('No pubsub topic name'); + } + + $application = new Application(); + $application->add(new TopicCommand()); + $commandTester = new CommandTester($application->get('topic')); + $commandTester->execute( + [ + 'topic' => $topic, + 'message' => 'This is a test message', + '--project' => $projectId, + ], + ['interactive' => false] + ); + + $this->expectOutputRegex('/Message published/'); + } +} diff --git a/pubsub/test/bootstrap.php b/pubsub/cli/test/bootstrap.php similarity index 51% rename from pubsub/test/bootstrap.php rename to pubsub/cli/test/bootstrap.php index c8e00c57c4..6c8c4f51b9 100644 --- a/pubsub/test/bootstrap.php +++ b/pubsub/cli/test/bootstrap.php @@ -1,4 +1,3 @@ client = $client; - $this->datasetId = $datasetId; - } - - /** - * Creates a query object for pulling the last $limit number of - * "PubSubMessage" items, equivalent to the following GQL: - * - * SELECT * from PubSubMessage ORDER BY created DESC LIMIT 20 - * - * @see https://cloud.google.com/datastore/docs/concepts/gql - */ - public function createQuery($limit = 20) - { - $request = new \Google_Service_Datastore_RunQueryRequest(); - $query = new \Google_Service_Datastore_Query(); - - $order = new \Google_Service_Datastore_PropertyOrder(); - $order->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('PubSubMessage'); - $query->setKind($kind); - - $query->setLimit($limit); - - $request->setQuery($query); - - return $request; - } - - /** - * Creates the request to store a PubSubMessage item in datastore - */ - public function createMessageRequest(\Google_Service_Datastore_Key $id, $message) - { - $entity = $this->createEntity($id, $message); - $mutation = new \Google_Service_Datastore_Mutation(); - $mutation->setUpsert($entity); - $req = new \Google_Service_Datastore_CommitRequest(); - $req->setMode('NON_TRANSACTIONAL'); - $req->setMutations([$mutation]); - - return $req; - } - - /** - * Creates the basic entity for PubSubMessage, with properties "created" - * and "message" - */ - public function createEntity(\Google_Service_Datastore_Key $key, $message) - { - $entity = new \Google_Service_Datastore_Entity(); - $entity->setKey($key); - $messageProp = new \Google_Service_Datastore_Value(); - $messageProp->setStringValue($message); - $createdProp = new \Google_Service_Datastore_Value(); - $createdProp->setTimeStampValue(date('c')); - $properties = [ - 'message' => $messageProp, - 'created' => $createdProp, - ]; - - $entity->setProperties($properties); - - return $entity; - } - - /** - * Fetches a unique key from Datastore for a PubSub message - */ - public function createUniqueKeyRequest() - { - // retrieve a unique ID from datastore - $path = new \Google_Service_Datastore_PathElement(); - $path->setKind('PubSubMessage'); - $key = new \Google_Service_Datastore_Key(); - $key->setPath([$path]); - $idRequest = new \Google_Service_Datastore_AllocateIdsRequest(); - $idRequest->setKeys([$key]); - - return $idRequest; - } - - /** - * Queries the Datastore API for all messages and returns as an array - * - * @see createQuery - * @return array - */ - public function fetchMessages() - { - $datastore = new \Google_Service_Datastore($this->client); - - $query = $this->createQuery(); - - $response = $datastore->projects->runQuery($this->datasetId, $query); - - $messages = []; - foreach ($response->getBatch()->getEntityResults() as $entityResult) { - $properties = $entityResult->getEntity()->getProperties(); - $messages[] = $properties['message']->getStringValue(); - } - - return $messages; - } - - /** - * Stores a single message in Datastore using the Datastore API - * - * @param string $message - * @return bool - */ - public function storeMessage($message) - { - $datastore = new \Google_Service_Datastore($this->client); - - $idRequest = $this->createUniqueKeyRequest(); - $uniqueId = $datastore->projects->allocateIds($this->datasetId, $idRequest); - $key = $uniqueId->getKeys()[0]; - - // build the API request to send using the key and message - $request = $this->createMessageRequest($key, $message); - - return $datastore->projects->commit($this->datasetId, $request); - } -} diff --git a/pubsub/src/app.php b/pubsub/src/app.php deleted file mode 100644 index 77cb277132..0000000000 --- a/pubsub/src/app.php +++ /dev/null @@ -1,148 +0,0 @@ -register(new TwigServiceProvider()); -$app['twig.path'] = [ __DIR__ . '/../templates' ]; -$app['project_id'] = getenv('GOOGLE_PROJECT_NAME'); -$app['topic'] = getenv('TOPIC_NAME') ?: 'php-pubsub-example'; - -// Authenticate your API Client -$client = new Google_Client(); -$client->useApplicationDefaultCredentials(); -$client->addScope(Google_Service_Pubsub::PUBSUB); -$client->addScope(Google_Service_Datastore::DATASTORE); - -$app['google_client'] = $client; - -$app->get('/', function () use ($app) { - return $app['twig']->render('pubsub.html.twig', [ - 'project_id' => $app['project_id'], - ]); -}); - -$app->get('/fetch_messages', function () use ($app) { - /** @var Google_Client $client */ - $client = $app['google_client']; - $projectId = $app['project_id']; - - // Retrieve all messages from datastore - // For a more complete demo of datastore, - // @see https://github.com/GoogleCloudPlatform/php-docs-samples/tree/master/datastore - $datastore = new DatastoreHelper($client, $projectId); - $messages = $datastore->fetchMessages(); - - return new JsonResponse($messages); -}); - -$app->post('/receive_message', function () use ($app) { - /** @var Google_Client $client */ - $client = $app['google_client']; - $projectId = $app['project_id']; - - // pull the message from the post body - $json = $app['request']->getContent(); - $request = json_decode($json, true); - if (!isset($request['message']['data']) || !$message = base64_decode($request['message']['data'])) { - return new Response('', 400); - } - - // Store the received message in datastore - // For a more complete demo of datastore, - // @see https://github.com/GoogleCloudPlatform/php-docs-samples/tree/master/datastore - $datastore = new DatastoreHelper($client, $projectId); - $datastore->storeMessage($message); - - return new Response(); -}); - -$app->post('/send_message', function () use ($app) { - // send the pubsub message - if ($messageText = $app['request']->get('message')) { - /** @var Google_Client $client */ - $client = $app['google_client']; - $projectName = sprintf('projects/%s', $app['project_id']); - $topicName = sprintf('%s/topics/%s', $projectName, $app['topic']); - - $pubsub = new Google_Service_Pubsub($client); - - // create pubsub message object - $message = new Google_Service_Pubsub_PubsubMessage(); - $message->setData(base64_encode($messageText)); - // create pubsub request - $request = new Google_Service_Pubsub_PublishRequest(); - $request->setMessages([$message]); - - $pubsub->projects_topics->publish($topicName, $request); - - return new Response('', 204); - } - - return new Response('', 400); -}); - -$app->post('/create_topic_and_subscription', function () use ($app) { - /** @var Google_Client $client */ - $client = $app['google_client']; - $projectName = sprintf('projects/%s', $app['project_id']); - $pubsub = new Google_Service_Pubsub($client); - $topic = new Google_Service_Pubsub_Topic(); - $topic->setName(sprintf('%s/topics/%s', $projectName, $app['topic'])); - try { - $pubsub->projects_topics->create($topic->getName(), $topic); - } catch (Google_Service_Exception $e) { - // 409 is ok. The topic already exists. - if ($e->getCode() != 409) { - throw $e; - } - } - $subscription = new Google_Service_Pubsub_Subscription(); - $subscription->setName(sprintf( - '%s/subscriptions/%s', - $projectName, - $app['topic'] - )); - $subscription->setTopic($topic->getName()); - $config = new Google_Service_Pubsub_PushConfig(); - $project_id = $app['project_id']; - $config->setPushEndpoint("https://$project_id.appspot.com/receive_message"); - $subscription->setPushConfig($config); - try { - $pubsub->projects_subscriptions->create( - $subscription->getName(), - $subscription - ); - } catch (Google_Service_Exception $e) { - // 409 is ok. The subscription already exists. - if ($e->getCode() != 409) { - throw $e; - } - } - return 'OK'; -}); - -return $app; diff --git a/pubsub/test/DatastoreHelperTest.php b/pubsub/test/DatastoreHelperTest.php deleted file mode 100644 index 6a58c930fb..0000000000 --- a/pubsub/test/DatastoreHelperTest.php +++ /dev/null @@ -1,61 +0,0 @@ -getMock('Google_Client'); - $datastore = new DatastoreHelper($client, 'test-dataset-id'); - - $request = $datastore->createQuery(14); - - $this->assertInstanceOf('Google_Service_Datastore_RunQueryRequest', $request); - $this->assertEquals(14, $request->getQuery()->getLimit()); - } - - public function testCreateEntity() - { - $client = $this->getMock('Google_Client'); - $datastore = new DatastoreHelper($client, 'test-dataset-id'); - - $key = $this->getMock('Google_Service_Datastore_Key'); - $entity = $datastore->createEntity($key, 'my test message'); - - $this->assertInstanceOf('Google_Service_Datastore_Entity', $entity); - - $properties = $entity->getProperties(); - $this->assertArrayHasKey('message', $properties); - - $properties = $entity->getProperties(); - $this->assertEquals('my test message', $properties['message']->getStringValue()); - } - - public function testCreateUniqueKeyRequest() - { - $client = $this->getMock('Google_Client'); - $datastore = new DatastoreHelper($client, 'test-dataset-id'); - - $key = $datastore->createUniqueKeyRequest(); - - $this->assertInstanceOf('Google_Service_Datastore_AllocateIdsRequest', $key); - } -}