├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── phpunit.xml ├── src └── Google │ └── Spreadsheet │ ├── Batch │ ├── BatchRequest.php │ └── BatchResponse.php │ ├── CellEntry.php │ ├── CellFeed.php │ ├── DefaultServiceRequest.php │ ├── Exception │ ├── BadRequestException.php │ ├── EmptyBatchException.php │ ├── Exception.php │ ├── ResourceNotFoundException.php │ ├── SpreadsheetNotFoundException.php │ ├── UnauthorizedException.php │ └── WorksheetNotFoundException.php │ ├── ListEntry.php │ ├── ListFeed.php │ ├── ServiceRequestFactory.php │ ├── ServiceRequestInterface.php │ ├── Spreadsheet.php │ ├── SpreadsheetFeed.php │ ├── SpreadsheetService.php │ ├── Util.php │ ├── Worksheet.php │ └── WorksheetFeed.php └── tests ├── Google └── Spreadsheet │ ├── Batch │ ├── BatchRequestTest.php │ └── BatchResponseTest.php │ ├── CellEntryTest.php │ ├── CellFeedTest.php │ ├── DefaultServiceRequestTest.php │ ├── ListEntryTest.php │ ├── ListFeedTest.php │ ├── ServiceRequestFactoryTest.php │ ├── SpreadsheetFeedTest.php │ ├── SpreadsheetServiceTest.php │ ├── SpreadsheetTest.php │ ├── TestBase.php │ ├── TestServiceRequest.php │ ├── UtilTest.php │ ├── WorksheetFeedTest.php │ ├── WorksheetTest.php │ └── xml │ ├── batch-response-error.xml │ ├── batch-response.xml │ ├── cell-feed-with-ampersand.xml │ ├── cell-feed.xml │ ├── list-feed.xml │ ├── spreadsheet-feed.xml │ ├── spreadsheet.xml │ ├── worksheet-feed.xml │ └── worksheet.xml ├── bootstrap.php └── cellfeed.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | /vendor/ 3 | /coverage/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - '5.6' 5 | - '7.0' 6 | 7 | before_install: 8 | - composer self-update 9 | 10 | install: 11 | - composer install 12 | 13 | script: 14 | - vendor/bin/phpunit -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016 Asim Liaquat 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/asimlqt/php-google-spreadsheet-client.svg?branch=master)](https://travis-ci.org/asimlqt/php-google-spreadsheet-client) 2 | 3 | > ### This library is no longer maintained. Please use the official [Google PHP Client](https://developers.google.com/sheets/api/quickstart/php) 4 | 5 | # Contents 6 | * [Introduction](#introduction) 7 | * [Installation](#installation) 8 | * [Bootstrapping](#bootstrapping) 9 | * [Spreadsheet](#spreadsheet) 10 | * [Retrieving a list of spreadsheets](#retrieving-a-list-of-spreadsheets) 11 | * [Retrieving a public spreadsheet](#retrieving-a-public-spreadsheet) 12 | * [Worksheet](#worksheet) 13 | * [Retrieving a list of worksheets](#retrieving-a-list-of-worksheets) 14 | * [Adding a worksheet](#adding-a-worksheet) 15 | * [Adding headers to a new worksheet](#adding-headers-to-a-new-worksheet) 16 | * [Deleting a worksheet](#deleting-a-worksheet) 17 | * [List feed](#list-feed) 18 | * [Retrieving a list feed](#retrieving-a-list-feed) 19 | * [Adding a list row](#adding-a-list-row) 20 | * [Updating a list row](#updating-a-list-row) 21 | * [Cell feed](#cell-feed) 22 | * [Retrieving a cell feed](#retrieving-a-cell-feed) 23 | * [Updating a cell](#updating-a-cell) 24 | * [Batch request](#updating-multiple-cells-with-a-batch-request) 25 | 26 | # Introduction 27 | 28 | This library provides a simple interface to the Google Spreadsheet API v3. 29 | 30 | There are a couple of important things to note. 31 | 32 | * This library requires a valid OAuth access token to work but does not provide any means of generating one. The [Google APIs Client Library for PHP](https://github.com/google/google-api-php-client) has all the functionality required for generating and refreshing tokens so it would have been a waste of time duplicating the official Google library. 33 | * You can not create spreadsheets using this library, as creating spreadsheets is not part of the Google Spreadsheet API, rather it's part of the Google Drive API. See the official [Google APIs Client Library for PHP](https://github.com/google/google-api-php-client). 34 | 35 | I strongly recommend you read through the [official Google Spreadsheet API documentation](https://developers.google.com/google-apps/spreadsheets) to get a grasp of the concepts. 36 | 37 | # Usage 38 | 39 | ## Installation 40 | 41 | Using [Composer](https://getcomposer.org/) is the recommended way to install it. 42 | 43 | 1 - Add "asimlqt/php-google-spreadsheet-client" as a dependency in your project's composer.json file. 44 | 45 | ```json 46 | { 47 | "require": { 48 | "asimlqt/php-google-spreadsheet-client": "3.0.*" 49 | } 50 | } 51 | ``` 52 | 53 | 2 - Download and install Composer. 54 | 55 | ``` 56 | curl -sS https://getcomposer.org/installer | php 57 | ``` 58 | 59 | 3 - Install your dependencies. 60 | 61 | ``` 62 | php composer.phar install 63 | ``` 64 | 65 | 4 - Require Composer's autoloader. 66 | 67 | ``` 68 | require 'vendor/autoload.php'; 69 | ``` 70 | 71 | 72 | ## Bootstrapping 73 | 74 | The first thing you will need to do is initialize the service request factory: 75 | 76 | ```php 77 | use Google\Spreadsheet\DefaultServiceRequest; 78 | use Google\Spreadsheet\ServiceRequestFactory; 79 | 80 | $serviceRequest = new DefaultServiceRequest($accessToken); 81 | ServiceRequestFactory::setInstance($serviceRequest); 82 | ``` 83 | 84 | > Note: For Windows users, you can disable the ssl verification by '$serviceRequest->setSslVerifyPeer(false)' 85 | 86 | ## Spreadsheet 87 | 88 | ### Retrieving a list of spreadsheets 89 | 90 | ```php 91 | $spreadsheetService = new Google\Spreadsheet\SpreadsheetService(); 92 | $spreadsheetFeed = $spreadsheetService->getSpreadsheetFeed(); 93 | ``` 94 | 95 | Once you have a SpreadsheetFeed you can iterate over the spreadsheets using a foreach loop by calling the 'getEntries()' method or you can retrieve a single spreadsheet by it's title. 96 | 97 | ```php 98 | $spreadsheet = $spreadsheetFeed->getByTitle('MySpreadsheet'); 99 | ``` 100 | 101 | > Note: The 'getByTitle' method will return the first spreadsheet found with that title if you have more than one spreadsheet with the same name. 102 | 103 | ### Retrieving a public spreadsheet 104 | 105 | A public spreadsheet is one that has been "published to the web". This does not require authentication. e.g. 106 | 107 | ```php 108 | $serviceRequest = new DefaultServiceRequest(""); 109 | ServiceRequestFactory::setInstance($serviceRequest); 110 | 111 | $spreadsheetService = new Google\Spreadsheet\SpreadsheetService(); 112 | $worksheetFeed = $spreadsheetService->getPublicSpreadsheet("spreadsheet-id"); 113 | ``` 114 | 115 | The spreadsheet id can be copied from the url of the actual spreadsheet in Google Drive. 116 | 117 | ## Worksheet 118 | 119 | ### Retrieving a list of worksheets 120 | 121 | You can retrieve a list of worksheets from a spreadsheet by calling the getWorksheets() method. 122 | 123 | ```php 124 | $spreadsheet = $spreadsheetFeed->getByTitle('MySpreadsheet'); 125 | $worksheetFeed = $spreadsheet->getWorksheetFeed(); 126 | ``` 127 | 128 | You can loop over each worksheet using 'getEntries()' or retrieve a single worksheet by it's title. 129 | 130 | ```php 131 | $worksheet = $worksheetFeed->getByTitle('Sheet1'); 132 | ``` 133 | 134 | ### Adding a worksheet 135 | 136 | To create a new worksheet simply use the 'addWorksheet()' method. This takes 3 arguments: 137 | - Worksheet name 138 | - Number of rows 139 | - Number of columns 140 | 141 | ```php 142 | $spreadsheet->addWorksheet('New Worksheet', 50, 20); 143 | ``` 144 | 145 | ### Adding headers to a new worksheet 146 | 147 | The Google Spreadsheet API does not allow you to update a list row if headers are not already assigned. So, when you create a new worksheet, before you can add data to a worksheet using the 'Adding/Updating a list row' methods above, you need to add headers. 148 | 149 | To add headers to a worksheet, use the following: 150 | ```php 151 | $cellFeed = $worksheet->getCellFeed(); 152 | 153 | $cellFeed->editCell(1,1, "Row1Col1Header"); 154 | $cellFeed->editCell(1,2, "Row1Col2Header"); 155 | ``` 156 | 157 | The only required parameter is the worksheet name, The row and column count are optional. The default value for rows is 100 and columns is 10. 158 | 159 | ### Deleting a worksheet 160 | 161 | It's also possible to delete a worksheet. 162 | 163 | ```php 164 | $worksheet->delete(); 165 | ``` 166 | 167 | ## List feed 168 | 169 | List feeds work at the row level. Each entry will contain the data for a specific row. 170 | 171 | > Note: You can not use formulas with the list feed. If you want to use formulas then you must use the cell feed (described below). 172 | 173 | ### Retrieving a list feed 174 | 175 | ```php 176 | $listFeed = $worksheet->getListFeed(); 177 | ``` 178 | 179 | Once you have a list feed you can loop over each entry. 180 | 181 | ```php 182 | foreach ($listFeed->getEntries() as $entry) { 183 | $values = $entry->getValues(); 184 | } 185 | ``` 186 | 187 | The getValues() method returns an associative array where the keys are the column names and the values are the cell content. 188 | 189 | > Note: The Google api converts the column headers to lower case so the column headings might not appear to be the same as what you see in Google Drive using your browser. 190 | 191 | > Note: If there is data for a particular row which does not have a column header then Google randomly generates a header and as far as I know it always begins with an underscore. Bear in mind that this is not generated by this library. 192 | 193 | You can also sort and filter the data so you only retrieve what is required, this is expecially useful for large worksheets. 194 | 195 | ```php 196 | $listFeed = $worksheet->getListFeed(["sq" => "age > 45", "reverse" => "true"]); 197 | ``` 198 | To find out all the available options visit [https://developers.google.com/google-apps/spreadsheets/#sorting_rows](https://developers.google.com/google-apps/spreadsheets/#sorting_rows). 199 | 200 | ### Adding a list row 201 | 202 | ```php 203 | $listFeed->insert(["name" => "Someone", "age" => 25]); 204 | ``` 205 | 206 | > When adding or updating a row the column headers need to match exactly what was returned by the Google API, not what you see in Google Drive. 207 | 208 | ### Updating a list row 209 | 210 | ```php 211 | $entries = $listFeed->getEntries(); 212 | $listEntry = $entries[0]; 213 | 214 | $values = $listEntry->getValues(); 215 | $values["name"] = "Joe"; 216 | $listEntry->update($values); 217 | ``` 218 | 219 | ## Cell feed 220 | 221 | Cell feed deals with individual cells. A cell feed is a collection of cells (of type CellEntry) 222 | 223 | ### Retrieving a cell feed 224 | 225 | ```php 226 | $cellFeed = $worksheet->getCellFeed(); 227 | ``` 228 | 229 | ### Updating a cell 230 | 231 | You can retrieve a single cell from the cell feed if you know the row and column numbers for that specific cell. 232 | 233 | ```php 234 | $cell = $cellFeed->getCell(10, 2); 235 | ``` 236 | 237 | You can then update the cell value using the 'update' method. The value can be a primitive value or a formula e.g. 238 | 239 | ```php 240 | $cell->update("=SUM(B2:B9)"); 241 | ``` 242 | 243 | ### Updating multiple cells with a batch request 244 | 245 | When attempting to insert data into multiple cells then consider using the batch request functionality to improve performance. 246 | 247 | To use the batch request functionality you need access to a cell feed first. You can not use batch requests with list feeds. 248 | 249 | ```php 250 | $cellFeed = $worksheet->getCellFeed(); 251 | 252 | $batchRequest = new Google\Spreadsheet\Batch\BatchRequest(); 253 | $batchRequest->addEntry($cellFeed->createCell(2, 1, "111")); 254 | $batchRequest->addEntry($cellFeed->createCell(3, 1, "222")); 255 | $batchRequest->addEntry($cellFeed->createCell(4, 1, "333")); 256 | $batchRequest->addEntry($cellFeed->createCell(5, 1, "=SUM(A2:A4)")); 257 | 258 | $batchResponse = $cellFeed->insertBatch($batchRequest); 259 | ``` 260 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asimlqt/php-google-spreadsheet-client", 3 | "type": "library", 4 | "description": "Google Spreadsheet PHP Client", 5 | "keywords": ["google", "spreadsheet"], 6 | "homepage": "https://github.com/asimlqt/php-google-spreadsheet-client", 7 | "license": "Apache-2.0", 8 | "authors": [ 9 | { 10 | "name": "Asim Liaquat", 11 | "email": "asimlqt22@gmail.com", 12 | "role": "Developer" 13 | } 14 | ], 15 | "require": { 16 | "php": ">=5.6.0" 17 | }, 18 | "require-dev": { 19 | "phpunit/phpunit": "4.4.2" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "Google\\": "src/Google"} 24 | }, 25 | "autoload-dev": { 26 | "psr-4": { 27 | "GoogleSpreadsheet\\Tests\\": "tests/" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "c3186240264ee490db0ad7721372cc91", 8 | "content-hash": "b31c8c546a1f80567a474bc7aca4fc65", 9 | "packages": [], 10 | "packages-dev": [ 11 | { 12 | "name": "doctrine/instantiator", 13 | "version": "1.0.4", 14 | "source": { 15 | "type": "git", 16 | "url": "https://github.com/doctrine/instantiator.git", 17 | "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119" 18 | }, 19 | "dist": { 20 | "type": "zip", 21 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119", 22 | "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119", 23 | "shasum": "" 24 | }, 25 | "require": { 26 | "php": ">=5.3,<8.0-DEV" 27 | }, 28 | "require-dev": { 29 | "athletic/athletic": "~0.1.8", 30 | "ext-pdo": "*", 31 | "ext-phar": "*", 32 | "phpunit/phpunit": "~4.0", 33 | "squizlabs/php_codesniffer": "2.0.*@ALPHA" 34 | }, 35 | "type": "library", 36 | "extra": { 37 | "branch-alias": { 38 | "dev-master": "1.0.x-dev" 39 | } 40 | }, 41 | "autoload": { 42 | "psr-0": { 43 | "Doctrine\\Instantiator\\": "src" 44 | } 45 | }, 46 | "notification-url": "https://packagist.org/downloads/", 47 | "license": [ 48 | "MIT" 49 | ], 50 | "authors": [ 51 | { 52 | "name": "Marco Pivetta", 53 | "email": "ocramius@gmail.com", 54 | "homepage": "http://ocramius.github.com/" 55 | } 56 | ], 57 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 58 | "homepage": "https://github.com/doctrine/instantiator", 59 | "keywords": [ 60 | "constructor", 61 | "instantiate" 62 | ], 63 | "time": "2014-10-13 12:58:55" 64 | }, 65 | { 66 | "name": "phpunit/php-code-coverage", 67 | "version": "2.0.15", 68 | "source": { 69 | "type": "git", 70 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 71 | "reference": "34cc484af1ca149188d0d9e91412191e398e0b67" 72 | }, 73 | "dist": { 74 | "type": "zip", 75 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/34cc484af1ca149188d0d9e91412191e398e0b67", 76 | "reference": "34cc484af1ca149188d0d9e91412191e398e0b67", 77 | "shasum": "" 78 | }, 79 | "require": { 80 | "php": ">=5.3.3", 81 | "phpunit/php-file-iterator": "~1.3", 82 | "phpunit/php-text-template": "~1.2", 83 | "phpunit/php-token-stream": "~1.3", 84 | "sebastian/environment": "~1.0", 85 | "sebastian/version": "~1.0" 86 | }, 87 | "require-dev": { 88 | "ext-xdebug": ">=2.1.4", 89 | "phpunit/phpunit": "~4" 90 | }, 91 | "suggest": { 92 | "ext-dom": "*", 93 | "ext-xdebug": ">=2.2.1", 94 | "ext-xmlwriter": "*" 95 | }, 96 | "type": "library", 97 | "extra": { 98 | "branch-alias": { 99 | "dev-master": "2.0.x-dev" 100 | } 101 | }, 102 | "autoload": { 103 | "classmap": [ 104 | "src/" 105 | ] 106 | }, 107 | "notification-url": "https://packagist.org/downloads/", 108 | "license": [ 109 | "BSD-3-Clause" 110 | ], 111 | "authors": [ 112 | { 113 | "name": "Sebastian Bergmann", 114 | "email": "sb@sebastian-bergmann.de", 115 | "role": "lead" 116 | } 117 | ], 118 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 119 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 120 | "keywords": [ 121 | "coverage", 122 | "testing", 123 | "xunit" 124 | ], 125 | "time": "2015-01-24 10:06:35" 126 | }, 127 | { 128 | "name": "phpunit/php-file-iterator", 129 | "version": "1.3.4", 130 | "source": { 131 | "type": "git", 132 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 133 | "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" 134 | }, 135 | "dist": { 136 | "type": "zip", 137 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", 138 | "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", 139 | "shasum": "" 140 | }, 141 | "require": { 142 | "php": ">=5.3.3" 143 | }, 144 | "type": "library", 145 | "autoload": { 146 | "classmap": [ 147 | "File/" 148 | ] 149 | }, 150 | "notification-url": "https://packagist.org/downloads/", 151 | "include-path": [ 152 | "" 153 | ], 154 | "license": [ 155 | "BSD-3-Clause" 156 | ], 157 | "authors": [ 158 | { 159 | "name": "Sebastian Bergmann", 160 | "email": "sb@sebastian-bergmann.de", 161 | "role": "lead" 162 | } 163 | ], 164 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 165 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 166 | "keywords": [ 167 | "filesystem", 168 | "iterator" 169 | ], 170 | "time": "2013-10-10 15:34:57" 171 | }, 172 | { 173 | "name": "phpunit/php-text-template", 174 | "version": "1.2.0", 175 | "source": { 176 | "type": "git", 177 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 178 | "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" 179 | }, 180 | "dist": { 181 | "type": "zip", 182 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", 183 | "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", 184 | "shasum": "" 185 | }, 186 | "require": { 187 | "php": ">=5.3.3" 188 | }, 189 | "type": "library", 190 | "autoload": { 191 | "classmap": [ 192 | "Text/" 193 | ] 194 | }, 195 | "notification-url": "https://packagist.org/downloads/", 196 | "include-path": [ 197 | "" 198 | ], 199 | "license": [ 200 | "BSD-3-Clause" 201 | ], 202 | "authors": [ 203 | { 204 | "name": "Sebastian Bergmann", 205 | "email": "sb@sebastian-bergmann.de", 206 | "role": "lead" 207 | } 208 | ], 209 | "description": "Simple template engine.", 210 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 211 | "keywords": [ 212 | "template" 213 | ], 214 | "time": "2014-01-30 17:20:04" 215 | }, 216 | { 217 | "name": "phpunit/php-timer", 218 | "version": "1.0.5", 219 | "source": { 220 | "type": "git", 221 | "url": "https://github.com/sebastianbergmann/php-timer.git", 222 | "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" 223 | }, 224 | "dist": { 225 | "type": "zip", 226 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", 227 | "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", 228 | "shasum": "" 229 | }, 230 | "require": { 231 | "php": ">=5.3.3" 232 | }, 233 | "type": "library", 234 | "autoload": { 235 | "classmap": [ 236 | "PHP/" 237 | ] 238 | }, 239 | "notification-url": "https://packagist.org/downloads/", 240 | "include-path": [ 241 | "" 242 | ], 243 | "license": [ 244 | "BSD-3-Clause" 245 | ], 246 | "authors": [ 247 | { 248 | "name": "Sebastian Bergmann", 249 | "email": "sb@sebastian-bergmann.de", 250 | "role": "lead" 251 | } 252 | ], 253 | "description": "Utility class for timing", 254 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 255 | "keywords": [ 256 | "timer" 257 | ], 258 | "time": "2013-08-02 07:42:54" 259 | }, 260 | { 261 | "name": "phpunit/php-token-stream", 262 | "version": "1.4.0", 263 | "source": { 264 | "type": "git", 265 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 266 | "reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74" 267 | }, 268 | "dist": { 269 | "type": "zip", 270 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/db32c18eba00b121c145575fcbcd4d4d24e6db74", 271 | "reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74", 272 | "shasum": "" 273 | }, 274 | "require": { 275 | "ext-tokenizer": "*", 276 | "php": ">=5.3.3" 277 | }, 278 | "require-dev": { 279 | "phpunit/phpunit": "~4.2" 280 | }, 281 | "type": "library", 282 | "extra": { 283 | "branch-alias": { 284 | "dev-master": "1.4-dev" 285 | } 286 | }, 287 | "autoload": { 288 | "classmap": [ 289 | "src/" 290 | ] 291 | }, 292 | "notification-url": "https://packagist.org/downloads/", 293 | "license": [ 294 | "BSD-3-Clause" 295 | ], 296 | "authors": [ 297 | { 298 | "name": "Sebastian Bergmann", 299 | "email": "sebastian@phpunit.de" 300 | } 301 | ], 302 | "description": "Wrapper around PHP's tokenizer extension.", 303 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 304 | "keywords": [ 305 | "tokenizer" 306 | ], 307 | "time": "2015-01-17 09:51:32" 308 | }, 309 | { 310 | "name": "phpunit/phpunit", 311 | "version": "4.4.2", 312 | "source": { 313 | "type": "git", 314 | "url": "https://github.com/sebastianbergmann/phpunit.git", 315 | "reference": "e90575c2bb86290d57a262862dab1da125431576" 316 | }, 317 | "dist": { 318 | "type": "zip", 319 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e90575c2bb86290d57a262862dab1da125431576", 320 | "reference": "e90575c2bb86290d57a262862dab1da125431576", 321 | "shasum": "" 322 | }, 323 | "require": { 324 | "ext-dom": "*", 325 | "ext-json": "*", 326 | "ext-pcre": "*", 327 | "ext-reflection": "*", 328 | "ext-spl": "*", 329 | "php": ">=5.3.3", 330 | "phpunit/php-code-coverage": "~2.0", 331 | "phpunit/php-file-iterator": "~1.3.2", 332 | "phpunit/php-text-template": "~1.2", 333 | "phpunit/php-timer": "~1.0.2", 334 | "phpunit/phpunit-mock-objects": "~2.3", 335 | "sebastian/comparator": "~1.0", 336 | "sebastian/diff": "~1.1", 337 | "sebastian/environment": "~1.1", 338 | "sebastian/exporter": "~1.0", 339 | "sebastian/global-state": "~1.0", 340 | "sebastian/version": "~1.0", 341 | "symfony/yaml": "~2.0" 342 | }, 343 | "suggest": { 344 | "phpunit/php-invoker": "~1.1" 345 | }, 346 | "bin": [ 347 | "phpunit" 348 | ], 349 | "type": "library", 350 | "extra": { 351 | "branch-alias": { 352 | "dev-master": "4.4.x-dev" 353 | } 354 | }, 355 | "autoload": { 356 | "classmap": [ 357 | "src/" 358 | ] 359 | }, 360 | "notification-url": "https://packagist.org/downloads/", 361 | "license": [ 362 | "BSD-3-Clause" 363 | ], 364 | "authors": [ 365 | { 366 | "name": "Sebastian Bergmann", 367 | "email": "sebastian@phpunit.de", 368 | "role": "lead" 369 | } 370 | ], 371 | "description": "The PHP Unit Testing framework.", 372 | "homepage": "https://phpunit.de/", 373 | "keywords": [ 374 | "phpunit", 375 | "testing", 376 | "xunit" 377 | ], 378 | "time": "2015-01-17 11:24:41" 379 | }, 380 | { 381 | "name": "phpunit/phpunit-mock-objects", 382 | "version": "2.3.0", 383 | "source": { 384 | "type": "git", 385 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 386 | "reference": "c63d2367247365f688544f0d500af90a11a44c65" 387 | }, 388 | "dist": { 389 | "type": "zip", 390 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/c63d2367247365f688544f0d500af90a11a44c65", 391 | "reference": "c63d2367247365f688544f0d500af90a11a44c65", 392 | "shasum": "" 393 | }, 394 | "require": { 395 | "doctrine/instantiator": "~1.0,>=1.0.1", 396 | "php": ">=5.3.3", 397 | "phpunit/php-text-template": "~1.2" 398 | }, 399 | "require-dev": { 400 | "phpunit/phpunit": "~4.3" 401 | }, 402 | "suggest": { 403 | "ext-soap": "*" 404 | }, 405 | "type": "library", 406 | "extra": { 407 | "branch-alias": { 408 | "dev-master": "2.3.x-dev" 409 | } 410 | }, 411 | "autoload": { 412 | "classmap": [ 413 | "src/" 414 | ] 415 | }, 416 | "notification-url": "https://packagist.org/downloads/", 417 | "license": [ 418 | "BSD-3-Clause" 419 | ], 420 | "authors": [ 421 | { 422 | "name": "Sebastian Bergmann", 423 | "email": "sb@sebastian-bergmann.de", 424 | "role": "lead" 425 | } 426 | ], 427 | "description": "Mock Object library for PHPUnit", 428 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 429 | "keywords": [ 430 | "mock", 431 | "xunit" 432 | ], 433 | "time": "2014-10-03 05:12:11" 434 | }, 435 | { 436 | "name": "sebastian/comparator", 437 | "version": "1.1.1", 438 | "source": { 439 | "type": "git", 440 | "url": "https://github.com/sebastianbergmann/comparator.git", 441 | "reference": "1dd8869519a225f7f2b9eb663e225298fade819e" 442 | }, 443 | "dist": { 444 | "type": "zip", 445 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e", 446 | "reference": "1dd8869519a225f7f2b9eb663e225298fade819e", 447 | "shasum": "" 448 | }, 449 | "require": { 450 | "php": ">=5.3.3", 451 | "sebastian/diff": "~1.2", 452 | "sebastian/exporter": "~1.2" 453 | }, 454 | "require-dev": { 455 | "phpunit/phpunit": "~4.4" 456 | }, 457 | "type": "library", 458 | "extra": { 459 | "branch-alias": { 460 | "dev-master": "1.1.x-dev" 461 | } 462 | }, 463 | "autoload": { 464 | "classmap": [ 465 | "src/" 466 | ] 467 | }, 468 | "notification-url": "https://packagist.org/downloads/", 469 | "license": [ 470 | "BSD-3-Clause" 471 | ], 472 | "authors": [ 473 | { 474 | "name": "Jeff Welch", 475 | "email": "whatthejeff@gmail.com" 476 | }, 477 | { 478 | "name": "Volker Dusch", 479 | "email": "github@wallbash.com" 480 | }, 481 | { 482 | "name": "Bernhard Schussek", 483 | "email": "bschussek@2bepublished.at" 484 | }, 485 | { 486 | "name": "Sebastian Bergmann", 487 | "email": "sebastian@phpunit.de" 488 | } 489 | ], 490 | "description": "Provides the functionality to compare PHP values for equality", 491 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 492 | "keywords": [ 493 | "comparator", 494 | "compare", 495 | "equality" 496 | ], 497 | "time": "2015-01-29 16:28:08" 498 | }, 499 | { 500 | "name": "sebastian/diff", 501 | "version": "1.2.0", 502 | "source": { 503 | "type": "git", 504 | "url": "https://github.com/sebastianbergmann/diff.git", 505 | "reference": "5843509fed39dee4b356a306401e9dd1a931fec7" 506 | }, 507 | "dist": { 508 | "type": "zip", 509 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/5843509fed39dee4b356a306401e9dd1a931fec7", 510 | "reference": "5843509fed39dee4b356a306401e9dd1a931fec7", 511 | "shasum": "" 512 | }, 513 | "require": { 514 | "php": ">=5.3.3" 515 | }, 516 | "require-dev": { 517 | "phpunit/phpunit": "~4.2" 518 | }, 519 | "type": "library", 520 | "extra": { 521 | "branch-alias": { 522 | "dev-master": "1.2-dev" 523 | } 524 | }, 525 | "autoload": { 526 | "classmap": [ 527 | "src/" 528 | ] 529 | }, 530 | "notification-url": "https://packagist.org/downloads/", 531 | "license": [ 532 | "BSD-3-Clause" 533 | ], 534 | "authors": [ 535 | { 536 | "name": "Kore Nordmann", 537 | "email": "mail@kore-nordmann.de" 538 | }, 539 | { 540 | "name": "Sebastian Bergmann", 541 | "email": "sebastian@phpunit.de" 542 | } 543 | ], 544 | "description": "Diff implementation", 545 | "homepage": "http://www.github.com/sebastianbergmann/diff", 546 | "keywords": [ 547 | "diff" 548 | ], 549 | "time": "2014-08-15 10:29:00" 550 | }, 551 | { 552 | "name": "sebastian/environment", 553 | "version": "1.2.1", 554 | "source": { 555 | "type": "git", 556 | "url": "https://github.com/sebastianbergmann/environment.git", 557 | "reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7" 558 | }, 559 | "dist": { 560 | "type": "zip", 561 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e6c71d918088c251b181ba8b3088af4ac336dd7", 562 | "reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7", 563 | "shasum": "" 564 | }, 565 | "require": { 566 | "php": ">=5.3.3" 567 | }, 568 | "require-dev": { 569 | "phpunit/phpunit": "~4.3" 570 | }, 571 | "type": "library", 572 | "extra": { 573 | "branch-alias": { 574 | "dev-master": "1.2.x-dev" 575 | } 576 | }, 577 | "autoload": { 578 | "classmap": [ 579 | "src/" 580 | ] 581 | }, 582 | "notification-url": "https://packagist.org/downloads/", 583 | "license": [ 584 | "BSD-3-Clause" 585 | ], 586 | "authors": [ 587 | { 588 | "name": "Sebastian Bergmann", 589 | "email": "sebastian@phpunit.de" 590 | } 591 | ], 592 | "description": "Provides functionality to handle HHVM/PHP environments", 593 | "homepage": "http://www.github.com/sebastianbergmann/environment", 594 | "keywords": [ 595 | "Xdebug", 596 | "environment", 597 | "hhvm" 598 | ], 599 | "time": "2014-10-25 08:00:45" 600 | }, 601 | { 602 | "name": "sebastian/exporter", 603 | "version": "1.2.0", 604 | "source": { 605 | "type": "git", 606 | "url": "https://github.com/sebastianbergmann/exporter.git", 607 | "reference": "84839970d05254c73cde183a721c7af13aede943" 608 | }, 609 | "dist": { 610 | "type": "zip", 611 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943", 612 | "reference": "84839970d05254c73cde183a721c7af13aede943", 613 | "shasum": "" 614 | }, 615 | "require": { 616 | "php": ">=5.3.3", 617 | "sebastian/recursion-context": "~1.0" 618 | }, 619 | "require-dev": { 620 | "phpunit/phpunit": "~4.4" 621 | }, 622 | "type": "library", 623 | "extra": { 624 | "branch-alias": { 625 | "dev-master": "1.2.x-dev" 626 | } 627 | }, 628 | "autoload": { 629 | "classmap": [ 630 | "src/" 631 | ] 632 | }, 633 | "notification-url": "https://packagist.org/downloads/", 634 | "license": [ 635 | "BSD-3-Clause" 636 | ], 637 | "authors": [ 638 | { 639 | "name": "Jeff Welch", 640 | "email": "whatthejeff@gmail.com" 641 | }, 642 | { 643 | "name": "Volker Dusch", 644 | "email": "github@wallbash.com" 645 | }, 646 | { 647 | "name": "Bernhard Schussek", 648 | "email": "bschussek@2bepublished.at" 649 | }, 650 | { 651 | "name": "Sebastian Bergmann", 652 | "email": "sebastian@phpunit.de" 653 | }, 654 | { 655 | "name": "Adam Harvey", 656 | "email": "aharvey@php.net" 657 | } 658 | ], 659 | "description": "Provides the functionality to export PHP variables for visualization", 660 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 661 | "keywords": [ 662 | "export", 663 | "exporter" 664 | ], 665 | "time": "2015-01-27 07:23:06" 666 | }, 667 | { 668 | "name": "sebastian/global-state", 669 | "version": "1.0.0", 670 | "source": { 671 | "type": "git", 672 | "url": "https://github.com/sebastianbergmann/global-state.git", 673 | "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01" 674 | }, 675 | "dist": { 676 | "type": "zip", 677 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01", 678 | "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01", 679 | "shasum": "" 680 | }, 681 | "require": { 682 | "php": ">=5.3.3" 683 | }, 684 | "require-dev": { 685 | "phpunit/phpunit": "~4.2" 686 | }, 687 | "suggest": { 688 | "ext-uopz": "*" 689 | }, 690 | "type": "library", 691 | "extra": { 692 | "branch-alias": { 693 | "dev-master": "1.0-dev" 694 | } 695 | }, 696 | "autoload": { 697 | "classmap": [ 698 | "src/" 699 | ] 700 | }, 701 | "notification-url": "https://packagist.org/downloads/", 702 | "license": [ 703 | "BSD-3-Clause" 704 | ], 705 | "authors": [ 706 | { 707 | "name": "Sebastian Bergmann", 708 | "email": "sebastian@phpunit.de" 709 | } 710 | ], 711 | "description": "Snapshotting of global state", 712 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 713 | "keywords": [ 714 | "global state" 715 | ], 716 | "time": "2014-10-06 09:23:50" 717 | }, 718 | { 719 | "name": "sebastian/recursion-context", 720 | "version": "1.0.0", 721 | "source": { 722 | "type": "git", 723 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 724 | "reference": "3989662bbb30a29d20d9faa04a846af79b276252" 725 | }, 726 | "dist": { 727 | "type": "zip", 728 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252", 729 | "reference": "3989662bbb30a29d20d9faa04a846af79b276252", 730 | "shasum": "" 731 | }, 732 | "require": { 733 | "php": ">=5.3.3" 734 | }, 735 | "require-dev": { 736 | "phpunit/phpunit": "~4.4" 737 | }, 738 | "type": "library", 739 | "extra": { 740 | "branch-alias": { 741 | "dev-master": "1.0.x-dev" 742 | } 743 | }, 744 | "autoload": { 745 | "classmap": [ 746 | "src/" 747 | ] 748 | }, 749 | "notification-url": "https://packagist.org/downloads/", 750 | "license": [ 751 | "BSD-3-Clause" 752 | ], 753 | "authors": [ 754 | { 755 | "name": "Jeff Welch", 756 | "email": "whatthejeff@gmail.com" 757 | }, 758 | { 759 | "name": "Sebastian Bergmann", 760 | "email": "sebastian@phpunit.de" 761 | }, 762 | { 763 | "name": "Adam Harvey", 764 | "email": "aharvey@php.net" 765 | } 766 | ], 767 | "description": "Provides functionality to recursively process PHP variables", 768 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 769 | "time": "2015-01-24 09:48:32" 770 | }, 771 | { 772 | "name": "sebastian/version", 773 | "version": "1.0.4", 774 | "source": { 775 | "type": "git", 776 | "url": "https://github.com/sebastianbergmann/version.git", 777 | "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b" 778 | }, 779 | "dist": { 780 | "type": "zip", 781 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/a77d9123f8e809db3fbdea15038c27a95da4058b", 782 | "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b", 783 | "shasum": "" 784 | }, 785 | "type": "library", 786 | "autoload": { 787 | "classmap": [ 788 | "src/" 789 | ] 790 | }, 791 | "notification-url": "https://packagist.org/downloads/", 792 | "license": [ 793 | "BSD-3-Clause" 794 | ], 795 | "authors": [ 796 | { 797 | "name": "Sebastian Bergmann", 798 | "email": "sebastian@phpunit.de", 799 | "role": "lead" 800 | } 801 | ], 802 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 803 | "homepage": "https://github.com/sebastianbergmann/version", 804 | "time": "2014-12-15 14:25:24" 805 | }, 806 | { 807 | "name": "symfony/yaml", 808 | "version": "v2.6.4", 809 | "target-dir": "Symfony/Component/Yaml", 810 | "source": { 811 | "type": "git", 812 | "url": "https://github.com/symfony/Yaml.git", 813 | "reference": "60ed7751671113cf1ee7d7778e691642c2e9acd8" 814 | }, 815 | "dist": { 816 | "type": "zip", 817 | "url": "https://api.github.com/repos/symfony/Yaml/zipball/60ed7751671113cf1ee7d7778e691642c2e9acd8", 818 | "reference": "60ed7751671113cf1ee7d7778e691642c2e9acd8", 819 | "shasum": "" 820 | }, 821 | "require": { 822 | "php": ">=5.3.3" 823 | }, 824 | "type": "library", 825 | "extra": { 826 | "branch-alias": { 827 | "dev-master": "2.6-dev" 828 | } 829 | }, 830 | "autoload": { 831 | "psr-0": { 832 | "Symfony\\Component\\Yaml\\": "" 833 | } 834 | }, 835 | "notification-url": "https://packagist.org/downloads/", 836 | "license": [ 837 | "MIT" 838 | ], 839 | "authors": [ 840 | { 841 | "name": "Symfony Community", 842 | "homepage": "http://symfony.com/contributors" 843 | }, 844 | { 845 | "name": "Fabien Potencier", 846 | "email": "fabien@symfony.com" 847 | } 848 | ], 849 | "description": "Symfony Yaml Component", 850 | "homepage": "http://symfony.com", 851 | "time": "2015-01-25 04:39:26" 852 | } 853 | ], 854 | "aliases": [], 855 | "minimum-stability": "stable", 856 | "stability-flags": [], 857 | "prefer-stable": false, 858 | "prefer-lowest": false, 859 | "platform": { 860 | "php": ">=5.6.0" 861 | }, 862 | "platform-dev": [] 863 | } 864 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | tests/Google 6 | 7 | 8 | 9 | 10 | src 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Google/Spreadsheet/Batch/BatchRequest.php: -------------------------------------------------------------------------------- 1 | 29 | */ 30 | class BatchRequest 31 | { 32 | /** 33 | * 34 | * @var CellEntry[] 35 | */ 36 | protected $entries; 37 | 38 | 39 | public function __construct() 40 | { 41 | $this->entries = array(); 42 | } 43 | 44 | /** 45 | * 46 | * @param CellEntry $cellEntry 47 | */ 48 | public function addEntry(CellEntry $cellEntry) 49 | { 50 | $this->entries[] = $cellEntry; 51 | } 52 | 53 | /** 54 | * Get all entries in the batch 55 | * 56 | * @return CellEntry[] 57 | */ 58 | public function getEntries() 59 | { 60 | return $this->entries; 61 | } 62 | 63 | /** 64 | * 65 | * @param CellFeed $cellFeed 66 | * 67 | * @return \SimpleXMLElement 68 | * 69 | * @throws EmptyBatchException 70 | */ 71 | public function createRequestXml(CellFeed $cellFeed) 72 | { 73 | if(count($this->entries) === 0) { 74 | throw new EmptyBatchException(); 75 | 76 | } 77 | 78 | $feed = new \SimpleXMLElement(" 79 | 83 | 84 | "); 85 | 86 | $feed->id = $cellFeed->getPostUrl(); 87 | 88 | $i = 1; 89 | foreach($this->entries as $cellEntry) { 90 | $entry = $feed->addChild("entry"); 91 | 92 | $entry->addChild("xmlns:batch:id", "A".$i++); 93 | 94 | $op = $entry->addChild("xmlns:batch:operation"); 95 | $op->addAttribute("type", "update"); 96 | 97 | $entry->addChild("id", $cellFeed->getPostUrl() . "/" . $cellEntry->getCellIdString()); 98 | 99 | $link = $entry->addChild("link"); 100 | $link->addAttribute("rel", "edit"); 101 | $link->addAttribute("type", "application/atom+xml"); 102 | $link->addAttribute("href", $cellEntry->getEditUrl()); 103 | 104 | $cell = $entry->addChild("xmlns:gs:cell"); 105 | $cell->addAttribute("row", $cellEntry->getRow()); 106 | $cell->addAttribute("col", $cellEntry->getColumn()); 107 | $cell->addAttribute("inputValue", $cellEntry->getContent()); 108 | } 109 | 110 | return $feed; 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/Google/Spreadsheet/Batch/BatchResponse.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class BatchResponse 27 | { 28 | /** 29 | * 30 | * @var SimpleXMLElement 31 | */ 32 | protected $xml; 33 | 34 | /** 35 | * 36 | * @param \SimpleXMLElement $xml 37 | */ 38 | public function __construct(\SimpleXMLElement $xml) 39 | { 40 | $this->xml = $xml; 41 | } 42 | 43 | /** 44 | * 45 | * @return SimpleXMLElement 46 | */ 47 | public function getXml() 48 | { 49 | return $this->xml; 50 | } 51 | 52 | /** 53 | * 54 | * @return boolean 55 | */ 56 | public function hasErrors() 57 | { 58 | foreach ($this->xml->xpath("//batch:status/@code") as $el) { 59 | if($el->__toString() !== "200") { 60 | return true; 61 | } 62 | } 63 | 64 | return false; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/Google/Spreadsheet/CellEntry.php: -------------------------------------------------------------------------------- 1 | 27 | */ 28 | class CellEntry 29 | { 30 | /** 31 | * Xml element for a cell entry 32 | * 33 | * @var \SimpleXMLElement 34 | */ 35 | protected $xml; 36 | 37 | /** 38 | * The url for making a post request 39 | * 40 | * @var string 41 | */ 42 | protected $postUrl; 43 | 44 | /** 45 | * The row number of this cell 46 | * 47 | * @var int 48 | */ 49 | protected $row; 50 | 51 | /** 52 | * The row number of this cell 53 | * 54 | * @var int 55 | */ 56 | protected $column; 57 | 58 | /** 59 | * The contents of this cell 60 | * 61 | * @var string 62 | */ 63 | protected $content; 64 | 65 | /** 66 | * The input value of this cell 67 | * 68 | * @var string 69 | */ 70 | protected $inputValue; 71 | 72 | /** 73 | * Constructor 74 | * 75 | * @param \SimpleXMLElement $xml 76 | * @param string $postUrl 77 | */ 78 | public function __construct($xml, $postUrl) 79 | { 80 | $this->xml = $xml; 81 | $this->postUrl = $postUrl; 82 | $this->setCellLocation(); 83 | $this->content = $xml->content->__toString(); 84 | $this->inputValue = Util::extractAttributeFromXml($xml, "gs", "inputValue"); 85 | } 86 | 87 | /** 88 | * 89 | * @return string 90 | */ 91 | public function getCellIdString() 92 | { 93 | return sprintf( 94 | "R%sC%s", 95 | $this->row, 96 | $this->column 97 | ); 98 | } 99 | 100 | /** 101 | * Get the raw XML 102 | * 103 | * @return int 104 | */ 105 | public function getXml() 106 | { 107 | return $this->xml; 108 | } 109 | 110 | /** 111 | * Get the row number fo this cell 112 | * 113 | * @return int 114 | */ 115 | public function getRow() 116 | { 117 | return $this->row; 118 | } 119 | 120 | /** 121 | * Get the column number fo this cell 122 | * 123 | * @return int 124 | */ 125 | public function getColumn() 126 | { 127 | return $this->column; 128 | } 129 | 130 | /** 131 | * Set the post url 132 | * 133 | * @param string 134 | * 135 | * @return void 136 | */ 137 | public function setPostUrl($url) 138 | { 139 | $this->postUrl = $url; 140 | } 141 | 142 | /** 143 | * Get post url 144 | * 145 | * @return string 146 | */ 147 | public function getPostUrl() 148 | { 149 | return $this->postUrl; 150 | } 151 | 152 | /** 153 | * Get the the of this cell from its XML 154 | * 155 | * @return string 156 | */ 157 | public function getInputValue() 158 | { 159 | return $this->inputValue; 160 | } 161 | 162 | /** 163 | * Set the input value of this cell 164 | * 165 | * @param string $inputValue 166 | */ 167 | public function setInputValue($inputValue) 168 | { 169 | $this->inputValue = $inputValue; 170 | } 171 | 172 | /** 173 | * Get the cell identifier e.g. A1 174 | * 175 | * @return string 176 | */ 177 | public function getTitle() 178 | { 179 | return $this->xml->title->__toString(); 180 | } 181 | 182 | /** 183 | * Get the contents of the cell 184 | * 185 | * @return string 186 | */ 187 | public function getContent() 188 | { 189 | return $this->content; 190 | } 191 | 192 | /** 193 | * Update the cell value 194 | * 195 | * @param string $value Can be a simple constant value or a formula 196 | * 197 | * @return null 198 | */ 199 | public function update($value) 200 | { 201 | $entry = new \SimpleXMLElement(" 202 | 205 | 206 | "); 207 | 208 | $child = $entry->addChild("xmlns:gs:cell"); 209 | $child->addAttribute("row", $this->row); 210 | $child->addAttribute("col", $this->column); 211 | $child->addAttribute("inputValue", $value); 212 | 213 | $res = ServiceRequestFactory::getInstance()->post($this->postUrl, $entry->asXML()); 214 | $this->xml = new \SimpleXMLElement($res); 215 | } 216 | 217 | /** 218 | * Get the location of the cell. 219 | * 220 | * @return array 221 | * 222 | * @codeCoverageIgnore 223 | * This method is covered by getRow and getColumn tests 224 | */ 225 | protected function setCellLocation() 226 | { 227 | $id = $this->xml->id->__toString(); 228 | preg_match("@/R(\d+)C(\d+)@", $id, $matches); 229 | 230 | if(count($matches) !== 3) { 231 | throw new Exception("Filed to get the location of the cell"); 232 | } 233 | 234 | $this->row = (int) $matches[1]; 235 | $this->column = (int) $matches[2]; 236 | } 237 | 238 | /** 239 | * Get the edit url of the cell 240 | * 241 | * @return string 242 | */ 243 | public function getEditUrl() 244 | { 245 | return Util::getLinkHref($this->xml, "edit"); 246 | } 247 | 248 | } 249 | -------------------------------------------------------------------------------- /src/Google/Spreadsheet/CellFeed.php: -------------------------------------------------------------------------------- 1 | 28 | */ 29 | class CellFeed 30 | { 31 | /** 32 | * The xml representation of the feed 33 | * 34 | * @var \SimpleXMLElement 35 | */ 36 | protected $xml; 37 | 38 | /** 39 | * 40 | * @var array 41 | */ 42 | protected $entries; 43 | 44 | /** 45 | * Constructor 46 | * 47 | * @param \SimpleXMLElement $xml 48 | */ 49 | public function __construct(\SimpleXMLElement $xml) 50 | { 51 | $this->xml = $xml; 52 | $this->entries = array(); 53 | } 54 | 55 | /** 56 | * Get the raw XML 57 | * 58 | * @return int 59 | */ 60 | public function getXml() 61 | { 62 | return $this->xml; 63 | } 64 | 65 | /** 66 | * Get the feed id. Returns the full url. 67 | * 68 | * @return string 69 | */ 70 | public function getId() 71 | { 72 | return $this->xml->id->__toString(); 73 | } 74 | 75 | /** 76 | * Get the feed entries 77 | * 78 | * @return array \Google\Spreadsheet\CellEntry 79 | */ 80 | public function getEntries() 81 | { 82 | if(count($this->entries) > 0) { 83 | return $this->entries; 84 | } 85 | 86 | $postUrl = $this->getPostUrl(); 87 | 88 | foreach ($this->xml->entry as $entry) { 89 | $cell = new CellEntry($entry, $postUrl); 90 | $this->entries[$cell->getCellIdString()] = $cell; 91 | } 92 | 93 | return $this->entries; 94 | } 95 | 96 | /** 97 | * Returns the feed entries as a two-dimensional array, indexed by row/column 98 | * number. Array may be sparse, if returned cell data is sparse. 99 | * 100 | * @return array 101 | */ 102 | public function toArray() 103 | { 104 | $entries = $this->getEntries(); 105 | 106 | $result = array(); 107 | foreach ($entries as $entry) { 108 | $result[$entry->getRow()][$entry->getColumn()] = $entry->getContent(); 109 | } 110 | 111 | return $result; 112 | } 113 | 114 | /** 115 | * 116 | * @param int $row 117 | * @param int $col 118 | * 119 | * @return CellEntry|null 120 | */ 121 | public function getCell($row, $col) 122 | { 123 | if(count($this->entries) === 0) { 124 | $this->getEntries(); 125 | } 126 | 127 | $id = sprintf( 128 | "R%sC%s", 129 | $row, 130 | $col 131 | ); 132 | 133 | if(isset($this->entries[$id])) { 134 | return $this->entries[$id]; 135 | } 136 | 137 | return null; 138 | } 139 | 140 | /** 141 | * Edit a single cell. the row and column indexing start at 1. 142 | * So the first column of the first row will be (1,1). 143 | * 144 | * @param int $rowNum Row number 145 | * @param int $colNum Column number 146 | * @param string $value Can also be a formula 147 | * 148 | * @return void 149 | */ 150 | public function editCell($rowNum, $colNum, $value) 151 | { 152 | $entry = new \SimpleXMLElement(" 153 | 156 | 157 | "); 158 | 159 | $child = $entry->addChild("xmlns:gs:cell"); 160 | $child->addAttribute("row", $rowNum); 161 | $child->addAttribute("col", $colNum); 162 | $child->addAttribute("inputValue", $value); 163 | 164 | ServiceRequestFactory::getInstance()->post($this->getPostUrl(), $entry->asXML()); 165 | } 166 | 167 | /** 168 | * 169 | * @param \Google\Spreadsheet\Batch\BatchRequest $batchRequest 170 | * 171 | * @return \Google\Spreadsheet\Batch\BatchResponse 172 | */ 173 | public function updateBatch(BatchRequest $batchRequest) 174 | { 175 | $xml = $batchRequest->createRequestXml($this); 176 | $response = ServiceRequestFactory::getInstance()->post($this->getBatchUrl(), $xml); 177 | return new BatchResponse(new \SimpleXMLElement($response)); 178 | } 179 | 180 | /** 181 | * 182 | * @param \Google\Spreadsheet\Batch\BatchRequest $batchRequest 183 | * 184 | * @return \Google\Spreadsheet\Batch\BatchResponse 185 | */ 186 | public function insertBatch(BatchRequest $batchRequest) 187 | { 188 | $xml = $batchRequest->createRequestXml($this); 189 | 190 | $response = ServiceRequestFactory::getInstance() 191 | ->addHeader("If-Match", "*") 192 | ->post($this->getBatchUrl(), $xml->asXML()); 193 | 194 | ServiceRequestFactory::getInstance()->removeHeader("If-Match"); 195 | 196 | return new BatchResponse(new \SimpleXMLElement($response)); 197 | } 198 | 199 | /** 200 | * Get the feed post url 201 | * 202 | * @return string 203 | */ 204 | public function getPostUrl() 205 | { 206 | return Util::getLinkHref($this->xml, "http://schemas.google.com/g/2005#post"); 207 | } 208 | 209 | /** 210 | * 211 | * @return string 212 | */ 213 | public function getBatchUrl() 214 | { 215 | return Util::getLinkHref($this->xml, "http://schemas.google.com/g/2005#batch"); 216 | } 217 | 218 | /** 219 | * Create a entry to insert data 220 | * 221 | * @param int $row 222 | * @param int $col 223 | * @param string $value 224 | * 225 | * @return CellEntry 226 | */ 227 | public function createCell($row, $col, $value) 228 | { 229 | $entry = new \SimpleXMLElement(" 230 | 233 | 234 | "); 235 | 236 | // use ->content instead of addChild('content', $value) 237 | // due to addChild not escaping & properly. 238 | // http://php.net/manual/en/simplexmlelement.addchild.php#112204 239 | $entry->content = $value; 240 | $child = $entry->content; 241 | $child->addAttribute("type", "text"); 242 | $child = $entry->addChild("title"); 243 | $child->addAttribute("type", "text"); 244 | $entry->addChild("id", $this->getPostUrl() . "/R" . $row . "C" . $col); 245 | $link = $entry->addChild("link"); 246 | $link->addAttribute("rel", "edit"); 247 | $link->addAttribute("type", "application/atom+xml"); 248 | $link->addAttribute("href", $this->getPostUrl() . "/R" . $row . "C" . $col); 249 | 250 | $elementType = "gs:cell"; 251 | $entry->{$elementType} = $value; 252 | $child = $entry->{$elementType}; 253 | $child->addAttribute("row", $row); 254 | $child->addAttribute("col", $col); 255 | $child->addAttribute("inputValue", $value); 256 | 257 | return new CellEntry( 258 | new \SimpleXMLElement($entry->asXML()), 259 | $this->getPostUrl() 260 | ); 261 | } 262 | 263 | } 264 | -------------------------------------------------------------------------------- /src/Google/Spreadsheet/DefaultServiceRequest.php: -------------------------------------------------------------------------------- 1 | 28 | */ 29 | class DefaultServiceRequest implements ServiceRequestInterface 30 | { 31 | /** 32 | * Request object 33 | * 34 | * @var \Google\Spreadsheet\Request 35 | */ 36 | protected $accessToken; 37 | 38 | /** 39 | * Token type (defaults to OAuth for BC) 40 | * 41 | * @var string 42 | */ 43 | protected $tokenType; 44 | 45 | /** 46 | * Request headers 47 | * 48 | * @var array 49 | */ 50 | protected $headers = []; 51 | 52 | /** 53 | * Service url 54 | * 55 | * @var string 56 | */ 57 | protected $serviceUrl = "https://spreadsheets.google.com/"; 58 | 59 | /** 60 | * User agent 61 | * 62 | * @var string 63 | */ 64 | protected $userAgent = "PHP Google Spreadsheet Api"; 65 | 66 | /** 67 | * SSL verify peer 68 | * 69 | * @var boolean 70 | */ 71 | protected $sslVerifyPeer = true; 72 | 73 | /** 74 | * cURL parameters 75 | * 76 | * @var array 77 | */ 78 | protected $curlParams = [ 79 | CURLOPT_RETURNTRANSFER => true, 80 | CURLOPT_FOLLOWLOCATION => true, 81 | CURLOPT_FAILONERROR => false, 82 | CURLOPT_SSL_VERIFYPEER => true, 83 | CURLOPT_VERBOSE => false, 84 | ]; 85 | 86 | /** 87 | * Initializes the service request object. 88 | * 89 | * @param string $accessToken 90 | * @param string $tokenType 91 | */ 92 | public function __construct($accessToken, $tokenType = "OAuth") 93 | { 94 | $this->accessToken = $accessToken; 95 | $this->tokenType = $tokenType; 96 | } 97 | 98 | /** 99 | * Get the hostname of the spreadsheet service 100 | * 101 | * @return string 102 | */ 103 | public function getServiceUrl() 104 | { 105 | return $this->serviceUrl; 106 | } 107 | 108 | /** 109 | * Get request headers 110 | * 111 | * @return array 112 | */ 113 | public function getHeaders() 114 | { 115 | return $this->headers; 116 | } 117 | 118 | /** 119 | * Set optional request headers. 120 | * 121 | * @param array $headers associative array of key value pairs 122 | * 123 | * @return Google\Spreadsheet\DefaultServiceRequest 124 | */ 125 | public function setHeaders(array $headers) 126 | { 127 | $this->headers = $headers; 128 | return $this; 129 | } 130 | 131 | /** 132 | * Add a header to the headers array 133 | * 134 | * @param string $name 135 | * @param string $value 136 | * 137 | * @return Google\Spreadsheet\DefaultServiceRequest 138 | */ 139 | public function addHeader($name, $value) 140 | { 141 | $this->headers[$name] = $value; 142 | return $this; 143 | } 144 | 145 | /** 146 | * 147 | * @param string $name 148 | * 149 | * @return Google\Spreadsheet\DefaultServiceRequest 150 | */ 151 | public function removeHeader($name) 152 | { 153 | if(array_key_exists($name, $this->headers)) { 154 | unset($this->headers[$name]); 155 | } 156 | 157 | return $this; 158 | } 159 | 160 | /** 161 | * Get the user agent 162 | * 163 | * @return string 164 | */ 165 | public function getUserAgent() 166 | { 167 | return $this->userAgent; 168 | } 169 | 170 | /** 171 | * Set the user agent. It is a good ides to leave this as is. 172 | * 173 | * @param string $userAgent 174 | * 175 | * @return Google\Spreadsheet\DefaultServiceRequest 176 | */ 177 | public function setUserAgent($userAgent) 178 | { 179 | $this->userAgent = $userAgent; 180 | return $this; 181 | } 182 | 183 | /** 184 | * Get the value for verifying the peers ssl certificate. 185 | * 186 | * @return bool 187 | */ 188 | public function getSslVerifyPeer() 189 | { 190 | return $this->curlParams[CURLOPT_SSL_VERIFYPEER]; 191 | } 192 | 193 | /** 194 | * Verify the peer"s ssl certificate 195 | * 196 | * @param bool $sslVerifyPeer 197 | * 198 | * @return DefaultServiceRequest 199 | */ 200 | public function setSslVerifyPeer($sslVerifyPeer) 201 | { 202 | $this->curlParams[CURLOPT_SSL_VERIFYPEER] = (bool) $sslVerifyPeer; 203 | return $this; 204 | } 205 | 206 | /** 207 | * Get currently set curl params 208 | * 209 | * @return array 210 | */ 211 | public function getCurlParams() 212 | { 213 | return $this->curlParams; 214 | } 215 | 216 | /** 217 | * Add an extra curl parameter or override an existing one 218 | * 219 | * @param string $name 'CURLOPT_*' constant 220 | * @param mixed $value 221 | * 222 | * @return DefaultServiceRequest 223 | */ 224 | public function addCurlParam($name, $value) 225 | { 226 | $this->curlParams[$name] = $value; 227 | return $this; 228 | } 229 | 230 | /** 231 | * Perform a get request 232 | * 233 | * @param string $url 234 | * 235 | * @return string 236 | */ 237 | public function get($url) 238 | { 239 | $ch = $this->initRequest($url); 240 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET"); 241 | return $this->execute($ch); 242 | } 243 | 244 | /** 245 | * Perform a post request 246 | * 247 | * @param string $url 248 | * @param mixed $postData 249 | * 250 | * @return string 251 | */ 252 | public function post($url, $postData) 253 | { 254 | $headers = array( 255 | "Content-Type: application/atom+xml", 256 | "Content-Length: " . strlen($postData), 257 | ); 258 | $ch = $this->initRequest($url, $headers); 259 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); 260 | curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); 261 | return $this->execute($ch); 262 | } 263 | 264 | /** 265 | * Perform a put request 266 | * 267 | * @param string $url 268 | * @param mixed $postData 269 | * 270 | * @return string 271 | */ 272 | public function put($url, $postData) 273 | { 274 | $headers = array( 275 | "Content-Type: application/atom+xml", 276 | "Content-Length: " . strlen($postData), 277 | ); 278 | $ch = $this->initRequest($url, $headers); 279 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); 280 | curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); 281 | return $this->execute($ch); 282 | } 283 | 284 | /** 285 | * Perform a delete request 286 | * 287 | * @param string $url 288 | * 289 | * @return string 290 | */ 291 | public function delete($url) 292 | { 293 | $ch = $this->initRequest($url); 294 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE"); 295 | return $this->execute($ch); 296 | } 297 | 298 | /** 299 | * Initialize the curl session 300 | * 301 | * @param string $url 302 | * @param array $requestHeaders 303 | * 304 | * @return resource 305 | */ 306 | protected function initRequest($url, $requestHeaders = array()) 307 | { 308 | if(substr($url, 0, 4) !== "http") { 309 | $url = $this->serviceUrl . $url; 310 | } 311 | 312 | $ch = curl_init(); 313 | curl_setopt_array($ch, $this->curlParams); 314 | curl_setopt($ch, CURLOPT_URL, $url); 315 | 316 | $headers = array(); 317 | if (count($this->getHeaders()) > 0) { 318 | foreach ($this->getHeaders() as $k => $v) { 319 | $headers[] = "$k: $v"; 320 | } 321 | } 322 | $headers[] = "Authorization: " . $this->tokenType . " " . $this->accessToken; 323 | $headers = array_merge($headers, $requestHeaders); 324 | 325 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 326 | curl_setopt($ch, CURLOPT_USERAGENT, $this->getUserAgent()); 327 | return $ch; 328 | } 329 | 330 | /** 331 | * Executes the api request. 332 | * 333 | * @return string the xml response 334 | * 335 | * @throws UnauthorizedException 336 | * @throws BadRequestException 337 | * 338 | * @codeCoverageIgnore 339 | */ 340 | protected function execute($ch) 341 | { 342 | $ret = curl_exec($ch); 343 | 344 | $info = curl_getinfo($ch); 345 | $httpCode = (int)$info["http_code"]; 346 | 347 | if ($httpCode > 299) { 348 | switch ($httpCode) { 349 | case 401: 350 | throw new UnauthorizedException("Access token is invalid", 401); 351 | break; 352 | case 403: 353 | throw new UnauthorizedException($ret, 403); 354 | break; 355 | case 404: 356 | throw new UnauthorizedException("You need permission", 404); 357 | break; 358 | default: 359 | throw new BadRequestException($ret, $info["http_code"]); 360 | } 361 | } 362 | curl_close($ch); 363 | return $ret; 364 | } 365 | 366 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/Exception/BadRequestException.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class BadRequestException extends Exception 27 | { 28 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/Exception/EmptyBatchException.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class EmptyBatchException extends Exception 27 | { 28 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/Exception/Exception.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class Exception extends \Exception 27 | { 28 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/Exception/ResourceNotFoundException.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class ResourceNotFoundException extends Exception 27 | { 28 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/Exception/SpreadsheetNotFoundException.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class SpreadsheetNotFoundException extends Exception 27 | { 28 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/Exception/UnauthorizedException.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class UnauthorizedException extends Exception 27 | { 28 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/Exception/WorksheetNotFoundException.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class WorksheetNotFoundException extends Exception 27 | { 28 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/ListEntry.php: -------------------------------------------------------------------------------- 1 | 28 | */ 29 | class ListEntry 30 | { 31 | /** 32 | * The xml representation of this list entry 33 | * 34 | * @var \SimpleXMLElement 35 | */ 36 | protected $xml; 37 | 38 | /** 39 | * The data for this list entry 40 | * 41 | * @var array 42 | */ 43 | protected $data; 44 | 45 | /** 46 | * Constructor 47 | * 48 | * @param \SimpleXMLElement $xml 49 | * @param array $data 50 | */ 51 | public function __construct($xml, $data) 52 | { 53 | $this->xml = $xml; 54 | $this->data = $data; 55 | } 56 | 57 | /** 58 | * Get the raw XML 59 | * 60 | * @return int 61 | */ 62 | public function getXml() 63 | { 64 | return $this->xml; 65 | } 66 | 67 | /** 68 | * Get the values of this list entry 69 | * 70 | * @return array 71 | */ 72 | public function getValues() 73 | { 74 | return $this->data; 75 | } 76 | 77 | /** 78 | * Update this entry 79 | * 80 | * @param array $values 81 | */ 82 | public function update($values) 83 | { 84 | $entry = new SimpleXMLElement(" 85 | 88 | 89 | "); 90 | 91 | $entry->addChild("id", $this->xml->id->__toString()); 92 | 93 | foreach($values as $colName => $value) { 94 | $entry->addChild("xmlns:gsx:$colName", htmlspecialchars($value)); 95 | } 96 | 97 | ServiceRequestFactory::getInstance()->put($this->getEditUrl(), $entry->asXML()); 98 | } 99 | 100 | /** 101 | * Delete the current entry. 102 | */ 103 | public function delete() 104 | { 105 | ServiceRequestFactory::getInstance()->delete($this->getEditUrl()); 106 | } 107 | 108 | /** 109 | * Get the edit url 110 | * 111 | * @return string 112 | */ 113 | public function getEditUrl() 114 | { 115 | return Util::getLinkHref($this->xml, 'edit'); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/Google/Spreadsheet/ListFeed.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class ListFeed 27 | { 28 | /** 29 | * Xml representation of this feed 30 | * 31 | * @var \SimpleXMLElement 32 | */ 33 | protected $xml; 34 | 35 | /** 36 | * Constructor 37 | * 38 | * @param string $xmlString 39 | */ 40 | public function __construct(\SimpleXMLElement $xml) 41 | { 42 | $xml->registerXPathNamespace('gsx', 'http://schemas.google.com/spreadsheets/2006/extended'); 43 | $this->xml = $xml; 44 | } 45 | 46 | /** 47 | * Get the raw XML 48 | * 49 | * @return int 50 | */ 51 | public function getXml() 52 | { 53 | return $this->xml; 54 | } 55 | 56 | /** 57 | * Get the feed id. Returns the full url. 58 | * 59 | * @return string 60 | */ 61 | public function getId() 62 | { 63 | return $this->xml->id->__toString(); 64 | } 65 | 66 | /** 67 | * Get the post url for this feed 68 | * 69 | * @return string 70 | */ 71 | public function getPostUrl() 72 | { 73 | return Util::getLinkHref($this->xml, 'http://schemas.google.com/g/2005#post'); 74 | } 75 | 76 | /** 77 | * Insert a new row into this feed 78 | * 79 | * @param array $row 80 | * 81 | * @return void 82 | */ 83 | public function insert($row) 84 | { 85 | $entry = new \SimpleXMLElement(" 86 | 89 | 90 | "); 91 | 92 | foreach($row as $colName => $value) { 93 | $entry->addChild("xmlns:gsx:$colName", htmlspecialchars($value)); 94 | } 95 | 96 | ServiceRequestFactory::getInstance()->post($this->getPostUrl(), $entry->asXML()); 97 | } 98 | 99 | /** 100 | * Get the entries of this feed 101 | * 102 | * @return ListEntry[] 103 | */ 104 | public function getEntries() 105 | { 106 | $rows = array(); 107 | 108 | if(count($this->xml->entry) > 0) { 109 | 110 | foreach ($this->xml->entry as $entry) { 111 | $data = array(); 112 | foreach($entry->xpath('gsx:*') as $col) { 113 | $data[$col->getName()] = $col->__toString(); 114 | } 115 | 116 | $rows[] = new ListEntry($entry, $data); 117 | } 118 | } 119 | 120 | return $rows; 121 | } 122 | 123 | /** 124 | * Get open search total results 125 | * 126 | * @return int 127 | */ 128 | public function getTotalResults() 129 | { 130 | $xml = $this->xml->children('openSearch', true); 131 | return intval($xml->totalResults); 132 | } 133 | 134 | /** 135 | * Get open search start index 136 | * 137 | * @return int 138 | */ 139 | public function getStartIndex() 140 | { 141 | $xml = $this->xml->children('openSearch', true); 142 | return intval($xml->startIndex); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /src/Google/Spreadsheet/ServiceRequestFactory.php: -------------------------------------------------------------------------------- 1 | 27 | */ 28 | class ServiceRequestFactory 29 | { 30 | /** 31 | * @var ServiceRequestInterface 32 | */ 33 | private static $instance; 34 | 35 | /** 36 | * Set an instance of ServiceRequestInterface 37 | * 38 | * @param ServiceRequestInterface $instance 39 | */ 40 | public static function setInstance(ServiceRequestInterface $instance = null) 41 | { 42 | self::$instance = $instance; 43 | } 44 | 45 | /** 46 | * [getInstance description] 47 | * 48 | * @return ServiceRequestInterface 49 | * 50 | * @throws Exception 51 | */ 52 | public static function getInstance() 53 | { 54 | if(is_null(self::$instance)) { 55 | throw new Exception(); 56 | } 57 | return self::$instance; 58 | } 59 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/ServiceRequestInterface.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | interface ServiceRequestInterface 27 | { 28 | public function get($url); 29 | public function post($url, $postData); 30 | public function put($url, $postData); 31 | public function delete($url); 32 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/Spreadsheet.php: -------------------------------------------------------------------------------- 1 | 27 | */ 28 | class Spreadsheet 29 | { 30 | const REL_WORKSHEETS_FEED = 'http://schemas.google.com/spreadsheets/2006#worksheetsfeed'; 31 | 32 | /** 33 | * The spreadsheet xml object 34 | * 35 | * @var \SimpleXMLElement 36 | */ 37 | protected $xml; 38 | 39 | /** 40 | * Initializes the spreadsheet object 41 | * 42 | * @param \SimpleXMLElement $xml 43 | */ 44 | public function __construct(\SimpleXMLElement $xml) 45 | { 46 | $this->xml = $xml; 47 | } 48 | 49 | /** 50 | * Get the raw XML 51 | * 52 | * @return int 53 | */ 54 | public function getXml() 55 | { 56 | return $this->xml; 57 | } 58 | 59 | /** 60 | * Get the spreadsheet id 61 | * 62 | * @return string 63 | */ 64 | public function getId() 65 | { 66 | return $this->xml->id->__toString(); 67 | } 68 | 69 | /** 70 | * Get the updated date 71 | * 72 | * @return DateTime 73 | */ 74 | public function getUpdated() 75 | { 76 | return new \DateTime($this->xml->updated->__toString()); 77 | } 78 | 79 | /** 80 | * Returns the title (name) of the spreadsheet 81 | * 82 | * @return string 83 | */ 84 | public function getTitle() 85 | { 86 | return $this->xml->title->__toString(); 87 | } 88 | 89 | /** 90 | * Get all the worksheets which belong to this spreadsheet 91 | * 92 | * @return WorksheetFeed 93 | */ 94 | public function getWorksheetFeed() 95 | { 96 | $res = ServiceRequestFactory::getInstance()->get($this->getWorksheetsFeedUrl()); 97 | return new WorksheetFeed(new \SimpleXMLElement($res)); 98 | } 99 | 100 | /** 101 | * Get a single worksheet by it's title. If there is more than 102 | * one worksheet with the same title then the first one matched 103 | * will be returned. 104 | * 105 | * @return Worksheet 106 | * 107 | * @throws WorksheetNotFoundException 108 | */ 109 | public function getWorksheetByTitle($title) 110 | { 111 | foreach ($this->getWorksheetFeed()->getEntries() as $worksheet) { 112 | if ($worksheet->getTitle() === $title) { 113 | return $worksheet; 114 | } 115 | } 116 | 117 | throw new WorksheetNotFoundException(); 118 | } 119 | 120 | /** 121 | * Add a new worksheet to this spreadsheet 122 | * 123 | * @param string $title 124 | * @param int $rowCount default is 100 125 | * @param int $colCount default is 10 126 | * 127 | * @return Worksheet 128 | */ 129 | public function addWorksheet($title, $rowCount=100, $colCount=10) 130 | { 131 | $entry = new \SimpleXMLElement(" 132 | 135 | 136 | "); 137 | 138 | $entry->title = $title; 139 | $entry->addChild("xmlns:gs:rowCount", (int) $rowCount); 140 | $entry->addChild("xmlns:gs:colCount", (int) $colCount); 141 | 142 | $response = ServiceRequestFactory::getInstance()->post( 143 | $this->getWorksheetsFeedUrl(), 144 | $entry->asXML() 145 | ); 146 | 147 | return new Worksheet(new \SimpleXMLElement($response)); 148 | } 149 | 150 | /** 151 | * Returns the feed url of the spreadsheet 152 | * 153 | * @return string 154 | */ 155 | public function getWorksheetsFeedUrl() 156 | { 157 | return Util::getLinkHref($this->xml, self::REL_WORKSHEETS_FEED); 158 | } 159 | 160 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/SpreadsheetFeed.php: -------------------------------------------------------------------------------- 1 | 27 | */ 28 | class SpreadsheetFeed 29 | { 30 | /** 31 | * The spreadsheet feed xml object 32 | * 33 | * @var SimpleXMLElement 34 | */ 35 | protected $xml; 36 | 37 | /** 38 | * Initializes the spreadsheet feed object 39 | * 40 | * @param \SimpleXMLElement $xml 41 | */ 42 | public function __construct(\SimpleXMLElement $xml) 43 | { 44 | $this->xml = $xml; 45 | } 46 | 47 | /** 48 | * Get the raw XML 49 | * 50 | * @return int 51 | */ 52 | public function getXml() 53 | { 54 | return $this->xml; 55 | } 56 | 57 | /** 58 | * Get the feed id. Returns the full url. 59 | * 60 | * @return string 61 | */ 62 | public function getId() 63 | { 64 | return $this->xml->id->__toString(); 65 | } 66 | 67 | /** 68 | * Get all spreadsheets in the feed 69 | * 70 | * @return Spreadsheet[] 71 | */ 72 | public function getEntries() 73 | { 74 | $spreadsheets = []; 75 | foreach ($this->xml->entry as $entry) { 76 | $spreadsheets[] = new Spreadsheet($entry); 77 | } 78 | return $spreadsheets; 79 | } 80 | 81 | /** 82 | * Gets a spreadhseet from the feed by its title. i.e. the name of 83 | * the spreadsheet in google drive. This method will return only the 84 | * first spreadsheet found with the specified title. 85 | * 86 | * @param string $title 87 | * 88 | * @return Spreadsheet 89 | * 90 | * @throws SpreadsheetNotFoundException 91 | */ 92 | public function getByTitle($title) 93 | { 94 | foreach($this->xml->entry as $entry) { 95 | if($entry->title->__toString() == $title) { 96 | return new Spreadsheet($entry); 97 | } 98 | } 99 | 100 | throw new SpreadsheetNotFoundException(); 101 | } 102 | 103 | /** 104 | * Gets a spreadhseet from the feed by its ID in google drive. 105 | * 106 | * @param string $id 107 | * 108 | * @return Spreadsheet 109 | * 110 | * @throws SpreadsheetNotFoundException 111 | */ 112 | public function getById($id) 113 | { 114 | foreach($this->xml->entry as $entry) { 115 | if($entry->id->__toString() == $id) { 116 | return new Spreadsheet($entry); 117 | } 118 | } 119 | 120 | throw new SpreadsheetNotFoundException(); 121 | } 122 | 123 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/SpreadsheetService.php: -------------------------------------------------------------------------------- 1 | 28 | */ 29 | class SpreadsheetService 30 | { 31 | /** 32 | * Fetches a list of spreadsheets from google drive. 33 | * 34 | * @return SpreadsheetFeed 35 | */ 36 | public function getSpreadsheetFeed() 37 | { 38 | return new SpreadsheetFeed( 39 | new \SimpleXMLElement( 40 | ServiceRequestFactory::getInstance()->get( 41 | "feeds/spreadsheets/private/full" 42 | ) 43 | ) 44 | ); 45 | } 46 | 47 | /** 48 | * Fetch a resource directly with having to traverse the tree from 49 | * the top. This will provide a huge performance benefit to the 50 | * application if you already have the id. 51 | * 52 | * All classes which have a "getId()" method can be used. e.g. 53 | * - SpreadsheetFeed 54 | * - Spreadsheet 55 | * - WorksheetFeed 56 | * - Worksheet 57 | * - ListFeed 58 | * - CellFeed 59 | * 60 | * @param string $resource the full path of the class 61 | * @param string $id the id (full url) of the resource 62 | * 63 | * @return Object 64 | * 65 | * @throws ResourceNotFoundException 66 | */ 67 | public function getResourceById($resource, $id) 68 | { 69 | try { 70 | return new $resource( 71 | new \SimpleXMLElement( 72 | ServiceRequestFactory::getInstance()->get($id) 73 | ) 74 | ); 75 | } catch (BadRequestException $e) { 76 | throw new ResourceNotFoundException($e->getMessage()); 77 | } 78 | } 79 | 80 | /** 81 | * Get public spreadsheet 82 | * 83 | * @param string $id Only the actual id and not the full url 84 | * 85 | * @return WorksheetFeed 86 | */ 87 | public function getPublicSpreadsheet($id) 88 | { 89 | $serviceRequest = ServiceRequestFactory::getInstance(); 90 | 91 | $url = sprintf( 92 | "%sfeeds/worksheets/%s/public/full", 93 | $serviceRequest->getServiceUrl(), 94 | $id 95 | ); 96 | 97 | return $this->getResourceById(WorksheetFeed::class, $url); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/Google/Spreadsheet/Util.php: -------------------------------------------------------------------------------- 1 | 27 | */ 28 | class Util 29 | { 30 | /** 31 | * Extracts the endpoint from a full google spreadsheet url. 32 | * 33 | * @param string $url 34 | * 35 | * @return string 36 | */ 37 | public static function extractEndpoint($url) 38 | { 39 | return parse_url($url, PHP_URL_PATH); 40 | } 41 | 42 | /** 43 | * Extracts the href for a specific rel from an xml object. 44 | * 45 | * @param \SimpleXMLElement $xml 46 | * @param string $rel the value of the rel attribute whose href you want 47 | * 48 | * @return string 49 | */ 50 | public static function getLinkHref(\SimpleXMLElement $xml, $rel) 51 | { 52 | foreach($xml->link as $link) { 53 | $attributes = $link->attributes(); 54 | if($attributes['rel']->__toString() === $rel) { 55 | return $attributes['href']->__toString(); 56 | } 57 | } 58 | throw new Exception('No link found with rel "'.$rel.'"'); 59 | } 60 | 61 | /** 62 | * Get a specific attribute in a namespaced tag 63 | * 64 | * @param \SimpleXMLElement $xml 65 | * @param string $attributeFocus 66 | * @param string $namespaceFocus 67 | * @param string $tagFocus 68 | * 69 | * @return string 70 | */ 71 | public static function extractAttributeFromXml( 72 | \SimpleXMLElement $xml, 73 | $namespacePrefix, 74 | $attribute 75 | ) { 76 | return $xml->children($namespacePrefix, true)->attributes()[$attribute]->__toString(); 77 | } 78 | 79 | } -------------------------------------------------------------------------------- /src/Google/Spreadsheet/Worksheet.php: -------------------------------------------------------------------------------- 1 | 27 | */ 28 | class Worksheet 29 | { 30 | /** 31 | * A worksheet xml object 32 | * 33 | * @var \SimpleXMLElement 34 | */ 35 | private $xml; 36 | 37 | /** 38 | * Initializes the worksheet object. 39 | * 40 | * @param \SimpleXMLElement $xml 41 | */ 42 | public function __construct(\SimpleXMLElement $xml) 43 | { 44 | $xml->registerXPathNamespace('gs', 'http://schemas.google.com/spreadsheets/2006'); 45 | $this->xml = $xml; 46 | } 47 | 48 | /** 49 | * Get the raw XML 50 | * 51 | * @return int 52 | */ 53 | public function getXml() 54 | { 55 | return $this->xml; 56 | } 57 | 58 | /** 59 | * Get the worksheet id. Returns the full url. 60 | * 61 | * @return string 62 | */ 63 | public function getId() 64 | { 65 | return $this->xml->id->__toString(); 66 | } 67 | 68 | /** 69 | * Get the worksheet GID 70 | * 71 | * @return int 72 | */ 73 | public function getGid() 74 | { 75 | parse_str( 76 | parse_url($this->getExportCsvUrl(), PHP_URL_QUERY), 77 | $query 78 | ); 79 | 80 | return (int) $query['gid']; 81 | } 82 | 83 | /** 84 | * Get the updated date 85 | * 86 | * @return DateTime 87 | */ 88 | public function getUpdated() 89 | { 90 | return new DateTime($this->xml->updated->__toString()); 91 | } 92 | 93 | /** 94 | * Get the title of the worksheet 95 | * 96 | * @return string 97 | */ 98 | public function getTitle() 99 | { 100 | return $this->xml->title->__toString(); 101 | } 102 | 103 | /** 104 | * Get the number of rows in the worksheet 105 | * 106 | * @return int 107 | */ 108 | public function getRowCount() 109 | { 110 | $result = $this->xml->xpath('gs:rowCount'); 111 | return (int) $result[0]->__toString(); 112 | } 113 | 114 | /** 115 | * Get the number of columns in the worksheet 116 | * 117 | * @return int 118 | */ 119 | public function getColCount() 120 | { 121 | $result = $this->xml->xpath('gs:colCount'); 122 | return (int) $result[0]->__toString(); 123 | } 124 | 125 | /** 126 | * Get the list feed of this worksheet 127 | * 128 | * @param array $query add additional query params to the url to sort/filter the results 129 | * 130 | * @return ListFeed 131 | */ 132 | public function getListFeed(array $query = []) 133 | { 134 | $feedUrl = $this->getListFeedUrl(); 135 | if(count($query) > 0) { 136 | $feedUrl .= "?" . http_build_query($query); 137 | } 138 | 139 | $res = ServiceRequestFactory::getInstance()->get($feedUrl); 140 | return new ListFeed(new \SimpleXMLElement($res)); 141 | } 142 | 143 | /** 144 | * Get the cell feed of this worksheet 145 | * 146 | * @return CellFeed 147 | */ 148 | public function getCellFeed(array $query = []) 149 | { 150 | $feedUrl = $this->getCellFeedUrl(); 151 | if(count($query) > 0) { 152 | $feedUrl .= "?" . http_build_query($query); 153 | } 154 | 155 | $res = ServiceRequestFactory::getInstance()->get($feedUrl); 156 | return new CellFeed(new \SimpleXMLElement($res)); 157 | } 158 | 159 | /** 160 | * Get csv data of this worksheet 161 | * 162 | * @return string 163 | * 164 | * @throws Exception 165 | */ 166 | public function getCsv() 167 | { 168 | return ServiceRequestFactory::getInstance()->get($this->getExportCsvUrl()); 169 | } 170 | 171 | /** 172 | * Update worksheet 173 | * 174 | * @param string $title 175 | * @param int $colCount 176 | * @param int $rowCount 177 | * 178 | * @return void 179 | */ 180 | public function update($title = null, $colCount = null, $rowCount = null) 181 | { 182 | $title = $title ? $title : $this->getTitle(); 183 | $colCount = $colCount ? $colCount : $this->getColCount(); 184 | $rowCount = $rowCount ? $rowCount : $this->getRowCount(); 185 | 186 | $entry = new \SimpleXMLElement(" 187 | 190 | 191 | "); 192 | 193 | $entry->title = $title; 194 | $entry->addChild("xmlns:gs:rowCount", (int) $rowCount); 195 | $entry->addChild("xmlns:gs:colCount", (int) $colCount); 196 | 197 | ServiceRequestFactory::getInstance()->put($this->getEditUrl(), $entry->asXML()); 198 | } 199 | 200 | /** 201 | * Delete this worksheet 202 | * 203 | * @return null 204 | */ 205 | public function delete() 206 | { 207 | ServiceRequestFactory::getInstance()->delete($this->getEditUrl()); 208 | } 209 | 210 | /** 211 | * Get the edit url of the worksheet 212 | * 213 | * @return string 214 | */ 215 | public function getEditUrl() 216 | { 217 | return Util::getLinkHref($this->xml, 'edit'); 218 | } 219 | 220 | /** 221 | * The url which is used to fetch the data of a worksheet as a list 222 | * 223 | * @return string 224 | */ 225 | public function getListFeedUrl() 226 | { 227 | return Util::getLinkHref($this->xml, 'http://schemas.google.com/spreadsheets/2006#listfeed'); 228 | } 229 | 230 | /** 231 | * Get the cell feed url 232 | * 233 | * @return string 234 | */ 235 | public function getCellFeedUrl() 236 | { 237 | return Util::getLinkHref($this->xml, 'http://schemas.google.com/spreadsheets/2006#cellsfeed'); 238 | } 239 | 240 | /** 241 | * Get the export csv url 242 | * 243 | * @return string 244 | * 245 | * @throws Exception 246 | */ 247 | public function getExportCsvUrl() 248 | { 249 | return Util::getLinkHref($this->xml, 'http://schemas.google.com/spreadsheets/2006#exportcsv'); 250 | } 251 | 252 | } 253 | -------------------------------------------------------------------------------- /src/Google/Spreadsheet/WorksheetFeed.php: -------------------------------------------------------------------------------- 1 | 27 | */ 28 | class WorksheetFeed 29 | { 30 | /** 31 | * Worksheet feed xml object 32 | * 33 | * @var \SimpleXMLElement 34 | */ 35 | private $xml; 36 | 37 | /** 38 | * Initializes thie worksheet feed object 39 | * 40 | * @param SimpleXMLElement $xml 41 | */ 42 | public function __construct(\SimpleXMLElement $xml) 43 | { 44 | $this->xml = $xml; 45 | } 46 | 47 | /** 48 | * Get the raw XML 49 | * 50 | * @return int 51 | */ 52 | public function getXml() 53 | { 54 | return $this->xml; 55 | } 56 | 57 | /** 58 | * Get the feed id. Returns the full url. 59 | * 60 | * @return string 61 | */ 62 | public function getId() 63 | { 64 | return $this->xml->id->__toString(); 65 | } 66 | 67 | /** 68 | * Get all worksheets in this feed 69 | * 70 | * @return Worksheet[] 71 | */ 72 | public function getEntries() 73 | { 74 | $worksheets = []; 75 | foreach ($this->xml->entry as $entry) { 76 | $worksheets[] = new Worksheet($entry); 77 | } 78 | return $worksheets; 79 | } 80 | 81 | /** 82 | * Get the worksheet feed post url 83 | * 84 | * @return string 85 | */ 86 | public function getPostUrl() 87 | { 88 | return Util::getLinkHref($this->xml, 'http://schemas.google.com/g/2005#post'); 89 | } 90 | 91 | /** 92 | * Get a worksheet by title (name) 93 | * 94 | * @param string $title name of the worksheet 95 | * 96 | * @return Worksheet 97 | * 98 | * @throws WorksheetNotFoundException 99 | */ 100 | public function getByTitle($title) 101 | { 102 | foreach ($this->xml->entry as $entry) { 103 | if ($entry->title->__toString() == $title) { 104 | return new Worksheet($entry); 105 | } 106 | } 107 | 108 | throw new WorksheetNotFoundException(); 109 | } 110 | 111 | /** 112 | * Get a worksheet by id 113 | * 114 | * @param string $id of the worksheet 115 | * 116 | * @return Worksheet 117 | * 118 | * @throws WorksheetNotFoundException 119 | */ 120 | public function getById($id) 121 | { 122 | $feedId = $this->xml->id->__toString(); 123 | 124 | foreach ($this->xml->entry as $entry) { 125 | if ($entry->id == $feedId . '/' . $id) { 126 | return new Worksheet($entry); 127 | } 128 | } 129 | 130 | throw new WorksheetNotFoundException(); 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/Batch/BatchRequestTest.php: -------------------------------------------------------------------------------- 1 | batchRequest = new BatchRequest(); 19 | 20 | $feed = new CellFeed($this->getSimpleXMLElement("cell-feed")); 21 | $this->cellEntry = current($feed->getEntries()); 22 | $this->cellFeed = $feed; 23 | } 24 | 25 | public function testAddEntry() 26 | { 27 | $this->batchRequest->addEntry($this->cellEntry); 28 | 29 | $this->assertEquals(1, count($this->batchRequest->getEntries())); 30 | } 31 | 32 | public function testCreateRequestXml() 33 | { 34 | $cellEntry = $this->cellFeed->createCell(2, 1, "one", true); 35 | $this->batchRequest->addEntry($cellEntry); 36 | 37 | $cellEntry = $this->cellFeed->createCell(2, 2, "two"); 38 | $this->batchRequest->addEntry($cellEntry); 39 | 40 | $xml = $this->batchRequest->createRequestXml($this->cellFeed); 41 | 42 | $this->assertTrue($xml instanceof \SimpleXMLElement); 43 | $this->assertEquals(2, count($xml->entry)); 44 | 45 | $sxe = new \SimpleXMLElement($xml->asXML()); 46 | 47 | $entry1 = $sxe->entry[0]->children('gs', true)->attributes(); 48 | $this->assertEquals("2", $entry1["row"]->__toString()); 49 | $this->assertEquals("1", $entry1["col"]->__toString()); 50 | $this->assertEquals("one", $entry1["inputValue"]->__toString()); 51 | 52 | $entry2 = $sxe->entry[1]->children('gs', true)->attributes(); 53 | $this->assertEquals("2", $entry2["row"]->__toString()); 54 | $this->assertEquals("2", $entry2["col"]->__toString()); 55 | $this->assertEquals("two", $entry2["inputValue"]->__toString()); 56 | } 57 | 58 | /** 59 | * @expectedException Google\Spreadsheet\Exception\EmptyBatchException 60 | */ 61 | public function testCreateRequestXmlNoEntries() 62 | { 63 | $this->batchRequest->createRequestXml($this->cellFeed); 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/Batch/BatchResponseTest.php: -------------------------------------------------------------------------------- 1 | batchResponse = new BatchResponse($this->getSimpleXMLElement("batch-response")); 13 | } 14 | 15 | public function testGetXml() 16 | { 17 | $this->assertTrue($this->batchResponse->getXml() instanceof \SimpleXMLElement); 18 | } 19 | 20 | public function testHasErrors() 21 | { 22 | $this->assertFalse($this->batchResponse->hasErrors()); 23 | 24 | $batchResponse = new BatchResponse($this->getSimpleXMLElement("batch-response-error")); 25 | $this->assertTrue($batchResponse->hasErrors()); 26 | } 27 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/CellEntryTest.php: -------------------------------------------------------------------------------- 1 | getSimpleXMLElement("cell-feed")); 19 | $this->cellEntry = current($cellFeed->getEntries()); 20 | } 21 | 22 | public function tearDown() 23 | { 24 | $this->cellEntry = null; 25 | } 26 | 27 | public function testGetCellIdString() 28 | { 29 | $this->assertEquals("R1C1", $this->cellEntry->getCellIdString()); 30 | } 31 | 32 | public function testGetXml() 33 | { 34 | $this->assertTrue($this->cellEntry->getXml() instanceof \SimpleXMLElement); 35 | } 36 | 37 | public function testGetRow() 38 | { 39 | $this->assertEquals(1, $this->cellEntry->getRow()); 40 | } 41 | 42 | public function testGetColumn() 43 | { 44 | $this->assertEquals(1, $this->cellEntry->getColumn()); 45 | } 46 | 47 | public function testGetSetPostUrl() 48 | { 49 | $url = "http://google/"; 50 | $this->cellEntry->setPostUrl($url); 51 | $this->assertEquals($url, $this->cellEntry->getPostUrl()); 52 | } 53 | 54 | public function testGetInputValue() 55 | { 56 | $this->assertEquals("Name", $this->cellEntry->getInputValue()); 57 | } 58 | 59 | public function testSetInputValue() 60 | { 61 | $this->cellEntry->setInputValue("Test"); 62 | $this->assertEquals("Test", $this->cellEntry->getInputValue()); 63 | } 64 | 65 | public function testGetTitle() 66 | { 67 | $this->assertEquals("A1", $this->cellEntry->getTitle()); 68 | } 69 | 70 | public function testGetSetContent() 71 | { 72 | $this->assertEquals("Name", $this->cellEntry->getContent()); 73 | } 74 | 75 | public function testUpdate() 76 | { 77 | $mockRequest = $this->getMockBuilder(DefaultServiceRequest::class) 78 | ->setMethods(["post"]) 79 | ->disableOriginalConstructor() 80 | ->getMock(); 81 | $mockRequest->expects($this->once()) 82 | ->method("post") 83 | ->with( 84 | $this->equalTo("https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full"), 85 | $this->stringContains("MyVal") 86 | ) 87 | ->willReturn(""); 88 | 89 | ServiceRequestFactory::setInstance($mockRequest); 90 | 91 | $this->cellEntry->update("MyVal"); 92 | } 93 | 94 | public function testGetEditUrl() 95 | { 96 | $this->assertEquals( 97 | "https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full/R1C1/1fvl7", 98 | $this->cellEntry->getEditUrl() 99 | ); 100 | } 101 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/CellFeedTest.php: -------------------------------------------------------------------------------- 1 | getSimpleXMLElement("cell-feed")); 16 | $this->assertTrue($feed->getXml() instanceof \SimpleXMLElement); 17 | } 18 | 19 | public function testGetId() 20 | { 21 | $feed = new CellFeed($this->getSimpleXMLElement("cell-feed")); 22 | $this->assertEquals( 23 | "https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full", 24 | $feed->getId() 25 | ); 26 | } 27 | 28 | public function testGetEntries() 29 | { 30 | $feed = new CellFeed($this->getSimpleXMLElement("cell-feed")); 31 | $this->assertEquals(6, count($feed->getEntries())); 32 | // The same call needs to be made again to test returning the 33 | // cached version of the entries. required for 100% coverage 34 | $this->assertEquals(6, count($feed->getEntries())); 35 | } 36 | 37 | public function testToArray() 38 | { 39 | $feed = new CellFeed($this->getSimpleXMLElement("cell-feed")); 40 | 41 | $expected = [ 42 | 1 => [ 43 | 1 => "Name", 44 | 2 => "Age" 45 | ], 46 | 2 => [ 47 | 1 => "Asim", 48 | 2 => "99" 49 | ], 50 | 3 => [ 51 | 1 => "Other", 52 | 2 => "18" 53 | ], 54 | ]; 55 | 56 | $this->assertEquals($expected, $feed->toArray()); 57 | } 58 | 59 | public function testGetCell() 60 | { 61 | $feed = new CellFeed($this->getSimpleXMLElement("cell-feed")); 62 | 63 | $this->assertTrue($feed->getCell(1, 1) instanceof CellEntry); 64 | $this->assertNull($feed->getCell(5, 3)); 65 | } 66 | 67 | public function testEditCell() 68 | { 69 | $feed = new CellFeed($this->getSimpleXMLElement("cell-feed")); 70 | 71 | $mockServiceRequest = $this->getMockBuilder(DefaultServiceRequest::class) 72 | ->setMethods(array("post")) 73 | ->disableOriginalConstructor() 74 | ->getMock(); 75 | 76 | $mockServiceRequest->expects($this->once()) 77 | ->method("post") 78 | ->with( 79 | $this->equalTo("https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full"), 80 | $this->stringContains("editCell(2, 1, "Test"); 86 | } 87 | 88 | public function testUpdateBatch() 89 | { 90 | $mockBatchRequest = $this->getMockBuilder(BatchRequest::class) 91 | ->setMethods(["createRequestXml"]) 92 | ->disableOriginalConstructor() 93 | ->getMock(); 94 | $mockBatchRequest->expects($this->once()) 95 | ->method("createRequestXml") 96 | ->will($this->returnValue("")); 97 | 98 | $mockCellFeed = $this->getMockBuilder(CellFeed::class) 99 | ->setMethods(["getBatchUrl"]) 100 | ->disableOriginalConstructor() 101 | ->getMock(); 102 | $mockCellFeed->expects($this->once()) 103 | ->method("getBatchUrl") 104 | ->will($this->returnValue("https://spreadsheets.google.com/")); 105 | 106 | $mockServiceRequest = $this->getMockBuilder(DefaultServiceRequest::class) 107 | ->setMethods(array("post")) 108 | ->disableOriginalConstructor() 109 | ->getMock(); 110 | $mockServiceRequest->expects($this->once()) 111 | ->method("post") 112 | ->with( 113 | $this->equalTo("https://spreadsheets.google.com/"), 114 | $this->stringContains("") 115 | ) 116 | ->will($this->returnValue("")); 117 | ServiceRequestFactory::setInstance($mockServiceRequest); 118 | 119 | $this->assertTrue($mockCellFeed->updateBatch($mockBatchRequest) instanceof BatchResponse); 120 | } 121 | 122 | public function testInsertBatch() 123 | { 124 | $mockBatchRequest = $this->getMockBuilder(BatchRequest::class) 125 | ->setMethods(["createRequestXml"]) 126 | ->disableOriginalConstructor() 127 | ->getMock(); 128 | $mockBatchRequest->expects($this->once()) 129 | ->method("createRequestXml") 130 | ->will($this->returnValue(new \SimpleXMLElement(""))); 131 | 132 | $mockCellFeed = $this->getMockBuilder(CellFeed::class) 133 | ->setMethods(["getBatchUrl"]) 134 | ->disableOriginalConstructor() 135 | ->getMock(); 136 | $mockCellFeed->expects($this->once()) 137 | ->method("getBatchUrl") 138 | ->will($this->returnValue("https://spreadsheets.google.com/")); 139 | 140 | $mockServiceRequest = $this->getMockBuilder(DefaultServiceRequest::class) 141 | ->setMethods(array("post")) 142 | ->disableOriginalConstructor() 143 | ->getMock(); 144 | $mockServiceRequest->expects($this->once()) 145 | ->method("post") 146 | ->with( 147 | $this->equalTo("https://spreadsheets.google.com/"), 148 | $this->stringContains("") 149 | ) 150 | ->will($this->returnValue("")); 151 | ServiceRequestFactory::setInstance($mockServiceRequest); 152 | 153 | $this->assertTrue($mockCellFeed->insertBatch($mockBatchRequest) instanceof BatchResponse); 154 | } 155 | 156 | public function testGetPostUrl() 157 | { 158 | $feed = new CellFeed($this->getSimpleXMLElement("cell-feed")); 159 | $this->assertEquals( 160 | "https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full", 161 | $feed->getPostUrl() 162 | ); 163 | } 164 | 165 | public function testGetBatchUrl() 166 | { 167 | $feed = new CellFeed($this->getSimpleXMLElement("cell-feed")); 168 | $this->assertEquals( 169 | "https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full/batch", 170 | $feed->getBatchUrl() 171 | ); 172 | } 173 | 174 | public function testCreateCell() 175 | { 176 | $mockCellFeed = $this->getMockBuilder(CellFeed::class) 177 | ->setMethods(["getPostUrl"]) 178 | ->disableOriginalConstructor() 179 | ->getMock(); 180 | $mockCellFeed->expects($this->any()) 181 | ->method("getPostUrl") 182 | ->will($this->returnValue("https://spreadsheets.google.com/")); 183 | 184 | $actual = $mockCellFeed->createCell(2, 1, "Someone"); 185 | $this->assertTrue($actual instanceof CellEntry); 186 | } 187 | 188 | public function testCreateCellWithAmpersand() 189 | { 190 | $mockCellFeed = $this->getMockBuilder(CellFeed::class) 191 | ->setMethods(["getPostUrl"]) 192 | ->disableOriginalConstructor() 193 | ->getMock(); 194 | $mockCellFeed->expects($this->any()) 195 | ->method("getPostUrl") 196 | ->will($this->returnValue("https://spreadsheets.google.com/")); 197 | 198 | $actual = $mockCellFeed->createCell(2, 1, "a & b < c"); 199 | 200 | $this->assertTrue($actual instanceof CellEntry); 201 | 202 | $expectedXML = file_get_contents(__DIR__."/xml/cell-feed-with-ampersand.xml"); 203 | $actualXML = $actual->getXML()->asXML(); 204 | $this->assertXmlStringEqualsXmlString($actualXML,$expectedXML); 205 | } 206 | 207 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/DefaultServiceRequestTest.php: -------------------------------------------------------------------------------- 1 | assertEquals([], $request->getHeaders()); 13 | } 14 | 15 | public function testSetHeaders() 16 | { 17 | $request = new DefaultServiceRequest("token"); 18 | $headers = ["k" => "v"]; 19 | $this->assertTrue($request->setHeaders($headers) instanceof DefaultServiceRequest); 20 | $this->assertEquals($headers, $request->getHeaders()); 21 | } 22 | 23 | public function testAddHeader() 24 | { 25 | $request = new DefaultServiceRequest("token"); 26 | $headers = ["k" => "v"]; 27 | $this->assertTrue($request->addHeader("k", "v") instanceof DefaultServiceRequest); 28 | $this->assertEquals($headers, $request->getHeaders()); 29 | } 30 | 31 | public function testRemoveHeader() 32 | { 33 | $request = new DefaultServiceRequest("token"); 34 | $headers = ["k" => "v"]; 35 | $request->addHeader("k", "v"); 36 | $this->assertEquals($headers, $request->getHeaders()); 37 | $this->assertTrue($request->removeHeader("k") instanceof DefaultServiceRequest); 38 | $this->assertEquals([], $request->getHeaders()); 39 | } 40 | 41 | public function testGetUserAgent() 42 | { 43 | $request = new DefaultServiceRequest("token"); 44 | $this->assertEquals("PHP Google Spreadsheet Api", $request->getUserAgent()); 45 | } 46 | 47 | public function testSetUserAgent() 48 | { 49 | $request = new DefaultServiceRequest("token"); 50 | $this->assertTrue($request->setUserAgent("my user agent") instanceof DefaultServiceRequest); 51 | $this->assertEquals("my user agent", $request->getUserAgent()); 52 | } 53 | 54 | public function testGetSslVerifyPeer() 55 | { 56 | $request = new DefaultServiceRequest("token"); 57 | $this->assertTrue($request->getSslVerifyPeer()); 58 | } 59 | 60 | public function testSetSslVerifyPeer() 61 | { 62 | $request = new DefaultServiceRequest("token"); 63 | $this->assertTrue($request->setSslVerifyPeer(false) instanceof DefaultServiceRequest); 64 | $this->assertFalse($request->getSslVerifyPeer()); 65 | } 66 | 67 | public function testGetCurlParams() 68 | { 69 | $request = new DefaultServiceRequest("token"); 70 | $this->assertTrue(count($request->getCurlParams()) === 5); 71 | } 72 | 73 | public function testAddCurlParam() 74 | { 75 | $request = new DefaultServiceRequest("token"); 76 | $request->addCurlParam(CURLOPT_SSL_VERIFYPEER, false); 77 | 78 | $params = $request->getCurlParams(); 79 | 80 | $this->assertFalse($params[CURLOPT_SSL_VERIFYPEER]); 81 | } 82 | 83 | public function testGet() 84 | { 85 | $mockRequest = $this->getMockBuilder(DefaultServiceRequest::class) 86 | ->setMethods(["execute"]) 87 | ->disableOriginalConstructor() 88 | ->getMock(); 89 | $mockRequest->expects($this->once()) 90 | ->method("execute") 91 | ->will($this->returnValue("")); 92 | 93 | $this->assertEquals("", $mockRequest->get("http://test")); 94 | } 95 | 96 | public function testPost() 97 | { 98 | $mockRequest = $this->getMockBuilder(DefaultServiceRequest::class) 99 | ->setMethods(["execute"]) 100 | ->disableOriginalConstructor() 101 | ->getMock(); 102 | $mockRequest->expects($this->once()) 103 | ->method("execute"); 104 | 105 | $mockRequest->post("http://test", ""); 106 | } 107 | 108 | public function testPut() 109 | { 110 | $mockRequest = $this->getMockBuilder(DefaultServiceRequest::class) 111 | ->setMethods(["execute"]) 112 | ->disableOriginalConstructor() 113 | ->getMock(); 114 | $mockRequest->expects($this->once()) 115 | ->method("execute"); 116 | 117 | $mockRequest->put("http://test", ""); 118 | } 119 | 120 | public function testDelete() 121 | { 122 | $mockRequest = $this->getMockBuilder(DefaultServiceRequest::class) 123 | ->setMethods(["execute"]) 124 | ->disableOriginalConstructor() 125 | ->getMock(); 126 | $mockRequest->expects($this->once()) 127 | ->method("execute"); 128 | 129 | $mockRequest->delete("http://test"); 130 | } 131 | 132 | public function testInitRequest() 133 | { 134 | $method = new \ReflectionMethod( 135 | DefaultServiceRequest::class, 136 | "initRequest" 137 | ); 138 | 139 | $method->setAccessible(true); 140 | 141 | $request = new DefaultServiceRequest("token"); 142 | $request->addHeader("k", "v"); 143 | 144 | $result = $method->invoke($request, "http://test"); 145 | $this->assertTrue(is_resource($result)); 146 | 147 | $result = $method->invoke($request, "spreadsheet"); 148 | $this->assertTrue(is_resource($result)); 149 | } 150 | 151 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/ListEntryTest.php: -------------------------------------------------------------------------------- 1 | getSimpleXMLElement("list-feed")); 14 | $entry = current($listFeed->getEntries()); 15 | 16 | $this->assertTrue($entry->getXml() instanceof \SimpleXMLElement); 17 | } 18 | 19 | public function testGetEditUrl() 20 | { 21 | $listFeed = new ListFeed($this->getSimpleXMLElement("list-feed")); 22 | $listEntry = current($listFeed->getEntries()); 23 | 24 | $this->assertEquals( 25 | "https://spreadsheets.google.com/feeds/list/G3345eEsfsk60/od6/private/full/cokwr/bnkj8i7jo6c", 26 | $listEntry->getEditUrl() 27 | ); 28 | } 29 | 30 | public function testUpdate() 31 | { 32 | $mockServiceRequest = $this->getMockBuilder(DefaultServiceRequest::class) 33 | ->setMethods(["put"]) 34 | ->disableOriginalConstructor() 35 | ->getMock(); 36 | 37 | $mockServiceRequest->expects($this->once()) 38 | ->method("put") 39 | ->with( 40 | $this->equalTo("https://spreadsheets.google.com/feeds/list/G3345eEsfsk60/od6/private/full/cokwr/bnkj8i7jo6c"), 41 | $this->stringContains("Asim") 42 | ); 43 | 44 | ServiceRequestFactory::setInstance($mockServiceRequest); 45 | 46 | $listFeed = new ListFeed($this->getSimpleXMLElement("list-feed")); 47 | $entry = current($listFeed->getEntries()); 48 | $data = $entry->getValues(); 49 | $data["nname"] = "Asim"; 50 | $entry->update($data); 51 | } 52 | 53 | public function testDelete() 54 | { 55 | $mockServiceRequest = $this->getMockBuilder(DefaultServiceRequest::class) 56 | ->setMethods(["delete"]) 57 | ->disableOriginalConstructor() 58 | ->getMock(); 59 | 60 | $mockServiceRequest->expects($this->once()) 61 | ->method("delete") 62 | ->with( 63 | $this->equalTo("https://spreadsheets.google.com/feeds/list/G3345eEsfsk60/od6/private/full/cokwr/bnkj8i7jo6c") 64 | ); 65 | 66 | ServiceRequestFactory::setInstance($mockServiceRequest); 67 | 68 | $listFeed = new ListFeed($this->getSimpleXMLElement("list-feed")); 69 | $entry = current($listFeed->getEntries()); 70 | $entry->delete(); 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/ListFeedTest.php: -------------------------------------------------------------------------------- 1 | listFeed = new ListFeed($this->getSimpleXMLElement("list-feed")); 14 | } 15 | 16 | public function tearDown() 17 | { 18 | $this->listFeed = null; 19 | } 20 | 21 | public function testGetXml() 22 | { 23 | $this->assertTrue($this->listFeed->getXml() instanceof \SimpleXMLElement); 24 | } 25 | 26 | public function testGetId() 27 | { 28 | $this->assertEquals( 29 | "https://spreadsheets.google.com/feeds/list/G3345eEsfsk60/od6/private/full", 30 | $this->listFeed->getId() 31 | ); 32 | } 33 | 34 | public function testGetPostUrl() 35 | { 36 | $this->assertEquals( 37 | "https://spreadsheets.google.com/feeds/list/G3345eEsfsk60/od6/private/full", 38 | $this->listFeed->getPostUrl() 39 | ); 40 | } 41 | 42 | public function testInsert() 43 | { 44 | $mockServiceRequest = $this->getMockBuilder("Google\Spreadsheet\DefaultServiceRequest") 45 | ->setMethods(array("post")) 46 | ->disableOriginalConstructor() 47 | ->getMock(); 48 | 49 | $mockServiceRequest->expects($this->once()) 50 | ->method("post") 51 | ->with( 52 | $this->equalTo("https://spreadsheets.google.com/feeds/list/G3345eEsfsk60/od6/private/full"), 53 | $this->stringContains("software engineer") 54 | ); 55 | 56 | ServiceRequestFactory::setInstance($mockServiceRequest); 57 | 58 | $this->listFeed->insert(["name" => "asim", "occupation" => "software engineer"]); 59 | } 60 | 61 | public function testGetEntries() 62 | { 63 | $this->assertEquals(4, count($this->listFeed->getEntries())); 64 | } 65 | 66 | public function testGetTotalResults() 67 | { 68 | $this->assertEquals(4, $this->listFeed->getTotalResults()); 69 | } 70 | 71 | public function testGetStartIndex() 72 | { 73 | $this->assertEquals(1, $this->listFeed->getStartIndex()); 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/ServiceRequestFactoryTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(ServiceRequestFactory::getInstance() instanceof ServiceRequestInterface); 14 | } 15 | 16 | /** 17 | * @expectedException Exception 18 | */ 19 | public function testGetInstanceException() 20 | { 21 | ServiceRequestFactory::setInstance(null); 22 | ServiceRequestFactory::getInstance(); 23 | } 24 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/SpreadsheetFeedTest.php: -------------------------------------------------------------------------------- 1 | spreadsheetFeed = new SpreadsheetFeed( 14 | $this->getSimpleXMLElement("spreadsheet-feed") 15 | ); 16 | } 17 | 18 | public function tearDown() 19 | { 20 | $this->spreadsheetFeed = null; 21 | } 22 | 23 | public function testGetXml() 24 | { 25 | $this->assertTrue( 26 | $this->spreadsheetFeed->getXml() instanceof \SimpleXMLElement 27 | ); 28 | } 29 | 30 | public function testGetId() 31 | { 32 | $this->assertEquals( 33 | "https://spreadsheets.google.com/feeds/spreadsheets/private/full", 34 | $this->spreadsheetFeed->getId() 35 | ); 36 | } 37 | 38 | public function testGetEntries() 39 | { 40 | $this->assertEquals(2, count($this->spreadsheetFeed->getEntries())); 41 | } 42 | 43 | public function testGetByTitle() 44 | { 45 | $this->assertTrue( 46 | $this->spreadsheetFeed->getByTitle("Test Spreadsheet") instanceof Spreadsheet 47 | ); 48 | } 49 | 50 | /** 51 | * @expectedException Google\Spreadsheet\Exception\SpreadsheetNotFoundException 52 | */ 53 | public function testGetByTitleException() 54 | { 55 | $this->assertNull( 56 | $this->spreadsheetFeed->getByTitle("No Spreadsheet") 57 | ); 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/SpreadsheetServiceTest.php: -------------------------------------------------------------------------------- 1 | setServiceRequest("spreadsheet-feed.xml"); 17 | 18 | $spreadsheetService = new SpreadsheetService(); 19 | $feed = $spreadsheetService->getSpreadsheetFeed(); 20 | 21 | $this->assertTrue($feed instanceof SpreadsheetFeed); 22 | } 23 | 24 | public function testGetResourceById() 25 | { 26 | $this->setServiceRequest("spreadsheet.xml", false); 27 | 28 | $spreadsheetService = new SpreadsheetService(); 29 | $spreadsheet = $spreadsheetService->getResourceById( 30 | Spreadsheet::class, 31 | "https://spreadsheets.google.com/feeds/spreadsheets/private/full/tFEgU8ywJkkjcZjG" 32 | ); 33 | 34 | $this->assertTrue($spreadsheet instanceof Spreadsheet); 35 | } 36 | 37 | /** 38 | * @expectedException Google\Spreadsheet\Exception\ResourceNotFoundException 39 | */ 40 | public function testGetResourceByIdException() 41 | { 42 | $resourceId = "http://resource"; 43 | 44 | $mockRequest = $this->getMockBuilder(DefaultServiceRequest::class) 45 | ->setMethods(["get"]) 46 | ->disableOriginalConstructor() 47 | ->getMock(); 48 | $mockRequest->expects($this->once()) 49 | ->method("get") 50 | ->with( 51 | $this->equalTo($resourceId) 52 | ) 53 | ->will($this->throwException(new BadRequestException())); 54 | 55 | ServiceRequestFactory::setInstance($mockRequest); 56 | 57 | $spreadsheetService = new SpreadsheetService(); 58 | $spreadsheet = $spreadsheetService->getResourceById( 59 | Spreadsheet::class, 60 | $resourceId 61 | ); 62 | } 63 | 64 | public function testGetPublicSpreadsheet() 65 | { 66 | $id = "1Jfgc77-TukPZf_HOXH"; 67 | $url = "https://spreadsheets.google.com/feeds/worksheets/$id/public/full"; 68 | 69 | $mockService = $this->getMockBuilder(SpreadsheetService::class) 70 | ->setMethods(["getResourceById"]) 71 | ->getMock(); 72 | $mockService->expects($this->once()) 73 | ->method("getResourceById") 74 | ->with( 75 | $this->equalTo(WorksheetFeed::class), 76 | $this->equalTo($url) 77 | ); 78 | 79 | $mockService->getPublicSpreadsheet($id); 80 | } 81 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/SpreadsheetTest.php: -------------------------------------------------------------------------------- 1 | getSimpleXMLElement("spreadsheet")); 14 | $this->assertTrue($spreadsheet->getXml() instanceof \SimpleXMLElement); 15 | } 16 | 17 | public function testGetId() 18 | { 19 | $spreadsheet = new Spreadsheet($this->getSimpleXMLElement("spreadsheet")); 20 | $this->assertEquals($this->serviceUrl . "tFEgU8ywJkkjcZjG", $spreadsheet->getId()); 21 | } 22 | 23 | public function testGetUpdated() 24 | { 25 | $spreadsheet = new Spreadsheet($this->getSimpleXMLElement("spreadsheet")); 26 | 27 | $this->assertTrue($spreadsheet->getUpdated() instanceof \DateTime); 28 | $this->assertEquals( 29 | "2014-02-07 18:33:44", 30 | $spreadsheet->getUpdated()->format("Y-m-d H:i:s") 31 | ); 32 | } 33 | 34 | public function testGetTitle() 35 | { 36 | $spreadsheet = new Spreadsheet($this->getSimpleXMLElement("spreadsheet")); 37 | $this->assertEquals("Test Spreadsheet", $spreadsheet->getTitle()); 38 | } 39 | 40 | public function testGetWorksheetFeed() 41 | { 42 | $this->setServiceRequest("worksheet-feed.xml"); 43 | $spreadsheet = new Spreadsheet($this->getSimpleXMLElement("spreadsheet")); 44 | 45 | $this->assertTrue($spreadsheet->getWorksheetFeed() instanceof WorksheetFeed); 46 | } 47 | 48 | public function testGetWorksheetByTitle() 49 | { 50 | $spreadsheetMock = $this->getMockBuilder(Spreadsheet::class) 51 | ->setMethods(["getWorksheetFeed"]) 52 | ->disableOriginalConstructor() 53 | ->getMock(); 54 | 55 | $spreadsheetMock->expects($this->any()) 56 | ->method("getWorksheetFeed") 57 | ->will($this->returnValue(new WorksheetFeed( 58 | $this->getSimpleXMLElement("worksheet-feed") 59 | ))); 60 | 61 | $this->assertTrue($spreadsheetMock->getWorksheetByTitle("Sheet2") instanceof Worksheet); 62 | } 63 | 64 | /** 65 | * @expectedException Google\Spreadsheet\Exception\WorksheetNotFoundException 66 | */ 67 | public function testGetWorksheetByTitleNotFound() 68 | { 69 | $spreadsheetMock = $this->getMockBuilder(Spreadsheet::class) 70 | ->setMethods(["getWorksheetFeed"]) 71 | ->disableOriginalConstructor() 72 | ->getMock(); 73 | 74 | $spreadsheetMock->expects($this->any()) 75 | ->method("getWorksheetFeed") 76 | ->will($this->returnValue(new WorksheetFeed( 77 | $this->getSimpleXMLElement("worksheet-feed") 78 | ))); 79 | 80 | $this->assertTrue($spreadsheetMock->getWorksheetByTitle("Sheet10") instanceof Worksheet); 81 | } 82 | 83 | public function testAddWorksheet() 84 | { 85 | $this->setServiceRequest("worksheet.xml"); 86 | $spreadsheet = new Spreadsheet($this->getSimpleXMLElement("spreadsheet")); 87 | 88 | $this->assertTrue($spreadsheet->addWorksheet("Sheet 3") instanceof Worksheet); 89 | } 90 | 91 | public function testGetWorksheetsFeedUrl() 92 | { 93 | $spreadsheet = new Spreadsheet($this->getSimpleXMLElement("spreadsheet")); 94 | $this->assertEquals("https://spreadsheets.google.com/feeds/worksheets/tFEgU8ywJkkjcZjG/private/full", $spreadsheet->getWorksheetsFeedUrl()); 95 | } 96 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/TestBase.php: -------------------------------------------------------------------------------- 1 | setExecuteReturn($xml); 23 | ServiceRequestFactory::setInstance($serviceRequest); 24 | } 25 | 26 | /** 27 | * Read an xml file from the filessytem and return it as a 28 | * SimpleXMLElement object. 29 | * 30 | * @param string $file 31 | * 32 | * @return \SimpleXMLElement 33 | */ 34 | protected function getSimpleXMLElement($file) 35 | { 36 | return new \SimpleXMLElement( 37 | file_get_contents(__DIR__ . "/xml/${file}.xml") 38 | ); 39 | } 40 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/TestServiceRequest.php: -------------------------------------------------------------------------------- 1 | retVal = $retVal; 13 | } 14 | 15 | public function execute() 16 | { 17 | if($this->retVal instanceof \Exception) { 18 | throw new $this->retVal; 19 | } 20 | 21 | return $this->retVal; 22 | } 23 | 24 | public function delete($url) 25 | { 26 | return $this->execute(); 27 | } 28 | 29 | public function get($url) 30 | { 31 | return $this->execute(); 32 | } 33 | 34 | public function post($url, $postData) 35 | { 36 | return $this->execute(); 37 | } 38 | 39 | public function put($url, $postData) 40 | { 41 | return $this->execute(); 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/UtilTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($expected, $actual); 16 | } 17 | 18 | public function testGetLinkHref() 19 | { 20 | $xml = $this->getSimpleXMLElement("worksheet"); 21 | $expected = "https://spreadsheets.google.com/feeds/worksheets/tA3TdJ0RIVEem3xQZhG2Ceg/private/full/od8"; 22 | $actual = Util::getLinkHref($xml, "self"); 23 | 24 | $this->assertEquals($expected, $actual); 25 | } 26 | 27 | /** 28 | * @expectedException Google\Spreadsheet\Exception\Exception 29 | */ 30 | public function testGetLinkHrefException() 31 | { 32 | $xml = $this->getSimpleXMLElement("worksheet"); 33 | $expected = "https://spreadsheets.google.com/feeds/worksheets/tA3TdJ0RIVEem3xQZhG2Ceg/private/full/od8"; 34 | Util::getLinkHref($xml, "selfie"); 35 | } 36 | } -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/WorksheetFeedTest.php: -------------------------------------------------------------------------------- 1 | worksheetFeed = new WorksheetFeed( 14 | $this->getSimpleXMLElement("worksheet-feed") 15 | ); 16 | } 17 | 18 | public function testGetXml() 19 | { 20 | $this->assertTrue($this->worksheetFeed->getXml() instanceof \SimpleXMLElement); 21 | } 22 | 23 | public function testGetId() 24 | { 25 | $this->assertEquals( 26 | "https://spreadsheets.google.com/feeds/worksheets/tFEgU8ywJkkjcZjGsXV/private/full", 27 | $this->worksheetFeed->getId() 28 | ); 29 | } 30 | 31 | public function testGetEntries() 32 | { 33 | $this->assertEquals(2, count($this->worksheetFeed->getEntries())); 34 | } 35 | 36 | public function testGetPostUrl() 37 | { 38 | $this->assertEquals( 39 | "https://spreadsheets.google.com/feeds/worksheets/tFEgU8ywJkkjcZjGsXV/private/full", 40 | $this->worksheetFeed->getPostUrl() 41 | ); 42 | } 43 | 44 | public function testGetByTitle() 45 | { 46 | $this->assertTrue($this->worksheetFeed->getByTitle("Sheet1") instanceof Worksheet); 47 | } 48 | 49 | /** 50 | * @expectedException Google\Spreadsheet\Exception\WorksheetNotFoundException 51 | */ 52 | public function testGetByTitleException() 53 | { 54 | $worksheetFeed = new WorksheetFeed( 55 | $this->getSimpleXMLElement("worksheet-feed") 56 | ); 57 | 58 | $this->assertNull($worksheetFeed->getByTitle("Sheet3")); 59 | } 60 | 61 | public function testGetById() 62 | { 63 | $worksheetFeed = new WorksheetFeed( 64 | $this->getSimpleXMLElement("worksheet-feed") 65 | ); 66 | 67 | $this->assertTrue($worksheetFeed->getById("od6") instanceof Worksheet); 68 | } 69 | 70 | /** 71 | * @expectedException Google\Spreadsheet\Exception\WorksheetNotFoundException 72 | */ 73 | public function testGetByIdException() 74 | { 75 | $worksheetFeed = new WorksheetFeed( 76 | $this->getSimpleXMLElement("worksheet-feed") 77 | ); 78 | 79 | $this->assertTrue(is_null($worksheetFeed->getById("od7"))); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/WorksheetTest.php: -------------------------------------------------------------------------------- 1 | worksheet = new Worksheet( 17 | $this->getSimpleXMLElement("worksheet") 18 | ); 19 | } 20 | 21 | public function testGetId() 22 | { 23 | $this->assertEquals( 24 | "https://spreadsheets.google.com/feeds/worksheets/tA3TdJ0RIVEem3xQZhG2Ceg/private/full/od8", 25 | $this->worksheet->getId() 26 | ); 27 | } 28 | 29 | public function testGetXml() 30 | { 31 | $this->assertTrue($this->worksheet->getXml() instanceof \SimpleXMLElement); 32 | } 33 | 34 | public function testGetGid() 35 | { 36 | $this->assertEquals( 37 | "0", 38 | $this->worksheet->getGid() 39 | ); 40 | } 41 | 42 | public function testGetUpdated() 43 | { 44 | $worksheet = new Worksheet( 45 | $this->getSimpleXMLElement("worksheet") 46 | ); 47 | 48 | $this->assertTrue($worksheet->getUpdated() instanceof \DateTime); 49 | $this->assertEquals("2013-02-10 21:12:33", $worksheet->getUpdated()->format("Y-m-d H:i:s")); 50 | } 51 | 52 | public function testGetTitle() 53 | { 54 | $worksheet = new Worksheet( 55 | $this->getSimpleXMLElement("worksheet") 56 | ); 57 | 58 | $this->assertEquals("Test", $worksheet->getTitle()); 59 | } 60 | 61 | public function testGetRowCount() 62 | { 63 | $this->assertEquals(100, $this->worksheet->getRowCount()); 64 | } 65 | 66 | public function testGetColCount() 67 | { 68 | $this->assertEquals(10, $this->worksheet->getColCount()); 69 | } 70 | 71 | public function testGetListFeed() 72 | { 73 | $feedUrl = "https://spreadsheets.google.com/feeds/list/tA3TdJ0RIVEem3xQZhG2Ceg/od8/private/full"; 74 | 75 | $mockServiceRequest = $this->getMockBuilder(DefaultServiceRequest::class) 76 | ->setMethods(["get"]) 77 | ->disableOriginalConstructor() 78 | ->getMock(); 79 | 80 | $mockServiceRequest 81 | ->expects($this->once()) 82 | ->method("get") 83 | ->with($this->equalTo($feedUrl)) 84 | ->willReturn(file_get_contents(__DIR__."/xml/list-feed.xml")); 85 | 86 | ServiceRequestFactory::setInstance($mockServiceRequest); 87 | 88 | $worksheet = new Worksheet( 89 | $this->getSimpleXMLElement("worksheet") 90 | ); 91 | 92 | $this->assertTrue($worksheet->getListFeed() instanceof ListFeed); 93 | } 94 | 95 | public function testGetListFeedWithQuery() 96 | { 97 | $feedUrl = "https://spreadsheets.google.com/feeds/list/tA3TdJ0RIVEem3xQZhG2Ceg/od8/private/full?reverse=true&sq=age+%3E+45"; 98 | 99 | $mockServiceRequest = $this->getMockBuilder("Google\Spreadsheet\DefaultServiceRequest") 100 | ->setMethods(["get"]) 101 | ->disableOriginalConstructor() 102 | ->getMock(); 103 | 104 | $mockServiceRequest 105 | ->expects($this->once()) 106 | ->method("get") 107 | ->with($this->equalTo($feedUrl)) 108 | ->willReturn(file_get_contents(__DIR__."/xml/list-feed.xml")); 109 | 110 | ServiceRequestFactory::setInstance($mockServiceRequest); 111 | 112 | $listFeed = $this->worksheet->getListFeed(["reverse" => "true", "sq" => "age > 45"]); 113 | $this->assertTrue($listFeed instanceof ListFeed); 114 | } 115 | 116 | public function testGetCellFeed() 117 | { 118 | $feedUrl = "https://spreadsheets.google.com/feeds/cells/tA3TdJ0RIVEem3xQZhG2Ceg/od8/private/full"; 119 | 120 | $mockServiceRequest = $this->getMockBuilder(DefaultServiceRequest::class) 121 | ->setMethods(["get"]) 122 | ->disableOriginalConstructor() 123 | ->getMock(); 124 | 125 | $mockServiceRequest 126 | ->expects($this->once()) 127 | ->method("get") 128 | ->with($this->equalTo($feedUrl)) 129 | ->willReturn(file_get_contents(__DIR__."/xml/cell-feed.xml")); 130 | 131 | ServiceRequestFactory::setInstance($mockServiceRequest); 132 | 133 | $this->assertTrue($this->worksheet->getCellFeed() instanceof CellFeed); 134 | } 135 | 136 | public function testGetCellFeedWithQuery() 137 | { 138 | $feedUrl = "https://spreadsheets.google.com/feeds/cells/tA3TdJ0RIVEem3xQZhG2Ceg/od8/private/full?sq=age+%3E+45"; 139 | 140 | $mockServiceRequest = $this->getMockBuilder(DefaultServiceRequest::class) 141 | ->setMethods(["get"]) 142 | ->disableOriginalConstructor() 143 | ->getMock(); 144 | 145 | $mockServiceRequest 146 | ->expects($this->once()) 147 | ->method("get") 148 | ->with($this->equalTo($feedUrl)) 149 | ->willReturn(file_get_contents(__DIR__."/xml/cell-feed.xml")); 150 | 151 | ServiceRequestFactory::setInstance($mockServiceRequest); 152 | 153 | $this->assertTrue($this->worksheet->getCellFeed(["sq" => "age > 45"]) instanceof CellFeed); 154 | } 155 | 156 | public function testGetCsv() 157 | { 158 | $mockRequest = $this->getMockBuilder(DefaultServiceRequest::class) 159 | ->setMethods(["get"]) 160 | ->disableOriginalConstructor() 161 | ->getMock(); 162 | $mockRequest->expects($this->once()) 163 | ->method("get") 164 | ->with($this->equalTo("https://docs.google.com/spreadsheets/d/15LRDjnN-VvhG2tYOoVLfCH40D6JoW5NfFiqSTc5U/export?gid=0&format=csv")); 165 | 166 | ServiceRequestFactory::setInstance($mockRequest); 167 | 168 | $this->worksheet->getCsv(); 169 | } 170 | 171 | public function testUpdate() 172 | { 173 | $mockRequest = $this->getMockBuilder(DefaultServiceRequest::class) 174 | ->setMethods(["put"]) 175 | ->disableOriginalConstructor() 176 | ->getMock(); 177 | $mockRequest->expects($this->once()) 178 | ->method("put") 179 | ->with( 180 | $this->equalTo("https://spreadsheets.google.com/feeds/worksheets/tA3TdJ0RIVEem3xQZhG2Ceg/private/full/od8/0"), 181 | $this->logicalAnd( 182 | $this->stringContains("New WS"), 183 | $this->stringContains("150"), 184 | $this->stringContains("7") 185 | ) 186 | ); 187 | 188 | ServiceRequestFactory::setInstance($mockRequest); 189 | 190 | $this->worksheet->update("New WS", 7, 150); 191 | } 192 | 193 | public function testDelete() 194 | { 195 | $mockRequest = $this->getMockBuilder(DefaultServiceRequest::class) 196 | ->setMethods(["delete"]) 197 | ->disableOriginalConstructor() 198 | ->getMock(); 199 | $mockRequest->expects($this->once()) 200 | ->method("delete") 201 | ->with( 202 | $this->equalTo("https://spreadsheets.google.com/feeds/worksheets/tA3TdJ0RIVEem3xQZhG2Ceg/private/full/od8/0") 203 | ); 204 | 205 | ServiceRequestFactory::setInstance($mockRequest); 206 | 207 | $this->worksheet->delete(); 208 | } 209 | 210 | public function testGetEditUrl() 211 | { 212 | $this->assertEquals( 213 | "https://spreadsheets.google.com/feeds/worksheets/tA3TdJ0RIVEem3xQZhG2Ceg/private/full/od8/0", 214 | $this->worksheet->getEditUrl() 215 | ); 216 | } 217 | 218 | public function testGetListFeedUrl() 219 | { 220 | $this->assertEquals( 221 | "https://spreadsheets.google.com/feeds/list/tA3TdJ0RIVEem3xQZhG2Ceg/od8/private/full", 222 | $this->worksheet->getListFeedUrl() 223 | ); 224 | } 225 | 226 | public function testGetCellFeedUrl() 227 | { 228 | $this->assertEquals( 229 | "https://spreadsheets.google.com/feeds/cells/tA3TdJ0RIVEem3xQZhG2Ceg/od8/private/full", 230 | $this->worksheet->getCellFeedUrl() 231 | ); 232 | } 233 | 234 | public function testGetExportCsvUrl() 235 | { 236 | $this->assertEquals( 237 | "https://docs.google.com/spreadsheets/d/15LRDjnN-VvhG2tYOoVLfCH40D6JoW5NfFiqSTc5U/export?gid=0&format=csv", 238 | $this->worksheet->getExportCsvUrl() 239 | ); 240 | } 241 | 242 | } 243 | -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/xml/batch-response-error.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://spreadsheets.google.com/feeds/cells/15LBU0RDjnN-VvhG2tYOoVLfCH40D6JoW5NfFiqSTc5U/ov45g5m/private/full/batch/1459043728174 4 | 2016-03-27T01:55:28.200Z 5 | 6 | Batch Feed 7 | 8 | https://spreadsheets.google.com/feeds/cells/15LBU0RDjnN-VvhG2tYOoVLfCH40D6JoW5NfFiqSTc5U/ov45g5m/private/full/R2C1 9 | 2016-03-23T22:28:14.711Z 10 | 11 | A2 12 | 111 13 | 14 | 15 | 111 16 | A1 17 | 18 | 19 | 20 | 21 | https://spreadsheets.google.com/feeds/cells/15LBU0RDjnN-VvhG2tYOoVLfCH40D6JoW5NfFiqSTc5U/ov45g5m/private/full/R2C2 22 | 2016-03-23T22:28:14.711Z 23 | 24 | B2 25 | 222 26 | 27 | 28 | 222 29 | A2 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/xml/batch-response.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://spreadsheets.google.com/feeds/cells/15LBU0RDjnN-VvhG2tYOoVLfCH40D6JoW5NfFiqSTc5U/ov45g5m/private/full/batch/1459043728174 4 | 2016-03-27T01:55:28.200Z 5 | 6 | Batch Feed 7 | 8 | https://spreadsheets.google.com/feeds/cells/15LBU0RDjnN-VvhG2tYOoVLfCH40D6JoW5NfFiqSTc5U/ov45g5m/private/full/R2C1 9 | 2016-03-23T22:28:14.711Z 10 | 11 | A2 12 | 111 13 | 14 | 15 | 111 16 | A1 17 | 18 | 19 | 20 | 21 | https://spreadsheets.google.com/feeds/cells/15LBU0RDjnN-VvhG2tYOoVLfCH40D6JoW5NfFiqSTc5U/ov45g5m/private/full/R2C2 22 | 2016-03-23T22:28:14.711Z 23 | 24 | B2 25 | 222 26 | 27 | 28 | 222 29 | A2 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/xml/cell-feed-with-ampersand.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | a & b < c 4 | 5 | <id>https://spreadsheets.google.com//R2C1</id> 6 | <link rel="edit" type="application/atom+xml" href="https://spreadsheets.google.com//R2C1"/> 7 | <gs:cell row="2" col="1" inputValue="a & b < c">a & b < c</gs:cell> 8 | </entry> -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/xml/cell-feed.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <feed xmlns="http://www.w3.org/2005/Atom" xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:gs="http://schemas.google.com/spreadsheets/2006" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"> 3 | <id>https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full</id> 4 | <updated>2016-03-20T20:13:24.888Z</updated> 5 | <category scheme="http://schemas.google.com/spreadsheets/2006" term="http://schemas.google.com/spreadsheets/2006#cell" /> 6 | <title type="text">Sheet1 7 | 8 | 9 | 10 | 11 | 12 | 13 | asimlqt22 14 | asimlqt22@gmail.com 15 | 16 | 6 17 | 1 18 | 1010 19 | 26 20 | 21 | https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full/R1C1 22 | 2016-03-20T20:13:24.888Z 23 | 24 | A1 25 | Name 26 | 27 | 28 | Name 29 | 30 | 31 | https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full/R1C2 32 | 2016-03-20T20:13:24.888Z 33 | 34 | B1 35 | Age 36 | 37 | 38 | Age 39 | 40 | 41 | https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full/R2C1 42 | 2016-03-20T20:13:24.888Z 43 | 44 | A2 45 | Asim 46 | 47 | 48 | Asim 49 | 50 | 51 | https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full/R2C2 52 | 2016-03-20T20:13:24.888Z 53 | 54 | B2 55 | 99 56 | 57 | 58 | 99 59 | 60 | 61 | https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full/R3C1 62 | 2016-03-20T20:13:24.888Z 63 | 64 | A3 65 | Other 66 | 67 | 68 | Other 69 | 70 | 71 | https://spreadsheets.google.com/feeds/cells/15L06yklgflGRDjnN-VvhGYOoVLCH40DJoW5fFiqSTc5U/od6/private/full/R3C2 72 | 2016-03-20T20:13:24.888Z 73 | 74 | B3 75 | 18 76 | 77 | 78 | 18 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/xml/list-feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://spreadsheets.google.com/feeds/list/G3345eEsfsk60/od6/private/full 4 | 2014-11-17T21:26:55.831Z 5 | 6 | Sheet1 7 | 8 | 9 | 10 | 11 | 12 | asimlqt22 13 | asimlqt22@gmail.com 14 | 15 | 4 16 | 1 17 | 18 | https://spreadsheets.google.com/feeds/list/G3345eEsfsk60/od6/private/full/cokwr 19 | 2014-11-17T21:26:55.831Z 20 | 21 | asim 22 | age: 60, _cpzh4: bug 23 | 24 | 25 | asim 26 | 30 27 | bug 28 | 29 | 30 | https://spreadsheets.google.com/feeds/list/G3345eEsfsk60/od6/private/full/cre1l 31 | 2014-11-17T21:26:55.831Z 32 | 33 | Cassie 34 | age: 61 35 | 36 | 37 | Cassie 38 | 31 39 | 40 | 41 | https://spreadsheets.google.com/feeds/list/G3345eEsfsk60/od6/private/full/chk2m 42 | 2014-11-17T21:26:55.831Z 43 | 44 | Alex 45 | age: 20 46 | 47 | 48 | Alex 49 | 20 50 | 51 | 52 | https://spreadsheets.google.com/feeds/list/G3345eEsfsk60/od6/private/full/ciyn3 53 | 2014-11-17T21:26:55.831Z 54 | 55 | Test 56 | age: 75 57 | 58 | 59 | Test 60 | 75 61 | 62 | -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/xml/spreadsheet-feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://spreadsheets.google.com/feeds/spreadsheets/private/full 4 | 2014-02-22T22:35:38.954Z 5 | 6 | Available Spreadsheets - asimlqt22@gmail.com 7 | 8 | 9 | 10 | 2 11 | 1 12 | 13 | https://spreadsheets.google.com/feeds/spreadsheets/private/full/tFEgU8ywJkkjcZjGs 14 | 2014-02-07T18:33:44.826Z 15 | 16 | Notes 17 | Notes 18 | 19 | 20 | 21 | 22 | asimlqt22 23 | asimlqt22@gmail.com 24 | 25 | 26 | 27 | https://spreadsheets.google.com/feeds/spreadsheets/private/full/t0Zf6pG69DruUL6qAqD 28 | 2013-08-18T23:40:45.357Z 29 | 30 | Test Spreadsheet 31 | Test Spreadsheet 32 | 33 | 34 | 35 | 36 | asimlqt22 37 | asimlqt22@gmail.com 38 | 39 | 40 | -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/xml/spreadsheet.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://spreadsheets.google.com/feeds/spreadsheets/private/full/tFEgU8ywJkkjcZjG 4 | 2014-02-07T18:33:44.826Z 5 | 6 | Test Spreadsheet 7 | Test Spreadsheet 8 | 9 | 10 | 11 | 12 | asimlqt22 13 | asimlqt22@gmail.com 14 | 15 | -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/xml/worksheet-feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://spreadsheets.google.com/feeds/worksheets/tFEgU8ywJkkjcZjGsXV/private/full 4 | 2014-02-07T18:33:44.826Z 5 | 6 | Test Spreadsheet 7 | 8 | 9 | 10 | 11 | 12 | asimlqt22 13 | asimlqt22@gmail.com 14 | 15 | 1 16 | 1 17 | 18 | https://spreadsheets.google.com/feeds/worksheets/tFEgU8ywJkkjcZjGsXV/private/full/od6 19 | 2013-12-27T15:24:52.148Z 20 | 21 | Sheet1 22 | Sheet1 23 | 24 | 25 | 26 | 27 | 28 | 100 29 | 20 30 | 31 | 32 | https://spreadsheets.google.com/feeds/worksheets/tFEgU8ywJkkjcZjGsXV/private/full/od6 33 | 2013-12-27T15:24:52.148Z 34 | 35 | Sheet2 36 | Sheet2 37 | 38 | 39 | 40 | 41 | 42 | 100 43 | 20 44 | 45 | -------------------------------------------------------------------------------- /tests/Google/Spreadsheet/xml/worksheet.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://spreadsheets.google.com/feeds/worksheets/tA3TdJ0RIVEem3xQZhG2Ceg/private/full/od8 4 | 2013-02-10T21:12:33.843Z 5 | 6 | Test 7 | Test 8 | 9 | 10 | 11 | 12 | 13 | 14 | 100 15 | 10 16 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://spreadsheets.google.com/feeds/cells/tA3TdJ0RIVEem3xQZhG2Ceg/ocv/private/full 4 | 2013-02-17T17:01:53.656Z 5 | 6 | Sheet 1 7 | 8 | 9 | 10 | 11 | 12 | 13 | asimlqt22 14 | asimlqt22@gmail.com 15 | 16 | 8 17 | 1 18 | 100 19 | 10 20 | 21 | https://spreadsheets.google.com/feeds/cells/tA3TdJ0RIVEem3xQZhG2Ceg/ocv/private/full/R1C1 22 | 2013-02-17T17:01:53.656Z 23 | 24 | A1 25 | name 26 | 27 | 28 | name 29 | 30 | 31 | https://spreadsheets.google.com/feeds/cells/tA3TdJ0RIVEem3xQZhG2Ceg/ocv/private/full/R1C2 32 | 2013-02-17T17:01:53.656Z 33 | 34 | B1 35 | age 36 | 37 | 38 | age 39 | 40 | 41 | https://spreadsheets.google.com/feeds/cells/tA3TdJ0RIVEem3xQZhG2Ceg/ocv/private/full/R2C1 42 | 2013-02-17T17:01:53.656Z 43 | 44 | A2 45 | Asim 46 | 47 | 48 | Asim 49 | 50 | 51 | https://spreadsheets.google.com/feeds/cells/tA3TdJ0RIVEem3xQZhG2Ceg/ocv/private/full/R2C2 52 | 2013-02-17T17:01:53.656Z 53 | 54 | B2 55 | 33 56 | 57 | 58 | 33 59 | 60 | 61 | https://spreadsheets.google.com/feeds/cells/tA3TdJ0RIVEem3xQZhG2Ceg/ocv/private/full/R3C1 62 | 2013-02-17T17:01:53.656Z 63 | 64 | A3 65 | John 66 | 67 | 68 | John 69 | 70 | 71 | https://spreadsheets.google.com/feeds/cells/tA3TdJ0RIVEem3xQZhG2Ceg/ocv/private/full/R3C2 72 | 2013-02-17T17:01:53.656Z 73 | 74 | B3 75 | 45 76 | 77 | 78 | 45 79 | 80 | 81 | https://spreadsheets.google.com/feeds/cells/tA3TdJ0RIVEem3xQZhG2Ceg/ocv/private/full/R4C1 82 | 2013-02-17T17:01:53.656Z 83 | 84 | A4 85 | John 86 | 87 | 88 | John 89 | 90 | 91 | https://spreadsheets.google.com/feeds/cells/tA3TdJ0RIVEem3xQZhG2Ceg/ocv/private/full/R4C2 92 | 2013-02-17T17:01:53.656Z 93 | 94 | B4 95 | 45 96 | 97 | 98 | 45 99 | 100 | 101 | --------------------------------------------------------------------------------