├── .gitignore ├── examples ├── credentials.php └── example.php ├── .travis.yml ├── src ├── Exception.php └── Wunderlist.php ├── phpunit.xml.dist ├── composer.json ├── LICENSE ├── Wunderlist-SRP.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | -------------------------------------------------------------------------------- /examples/credentials.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class Exception extends \Exception 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | tests 9 | 10 | 11 | 12 | 13 | src 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jeroendesloovere/wunderlist-php-api", 3 | "type": "library", 4 | "description": "This Wunderlist PHP class connects to Wunderlist API.", 5 | "keywords": ["wunderlist", "to-do", "reminders", "tasks", "api", "php"], 6 | "homepage": "https://github.com/jeroendesloovere/wunderlist-php-api", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Jeroen Desloovere", 11 | "email": "info@jeroendesloovere.be", 12 | "homepage": "http://jeroendesloovere.be", 13 | "role": "Developer" 14 | } 15 | ], 16 | "require": { 17 | "php": ">=5.3.3" 18 | }, 19 | "autoload": { 20 | "psr-4": { "JeroenDesloovere\\Wunderlist\\": "src/" } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Jeroen Desloovere 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Wunderlist-SRP.md: -------------------------------------------------------------------------------- 1 | # Wunderlist 2 | 3 | src/ 4 | Wunderlist.php 5 | 6 | 7 | ## Wunderlist.php 8 | 9 | ``` php 10 | lists = new Lists($service); 24 | //$this->tasks = new Tasks($service); 25 | 26 | return $this; 27 | } 28 | } 29 | ``` 30 | 31 | ``` php 32 | service = $service; 53 | } 54 | } 55 | ``` 56 | 57 | ``` php 58 | service->doCall(); 72 | } 73 | 74 | public function insert($title) 75 | { 76 | $this->service->doCall(); 77 | } 78 | } 79 | ``` 80 | 81 | ## Usage 82 | 83 | ### Example 84 | 85 | ``` php 86 | // define wunderlist 87 | $api = new Wunderlist($apiKey, $apiSecret); 88 | 89 | // execute functions 90 | $api->lists->delete('list-id'); 91 | $api->lists->insert('title'); 92 | ``` -------------------------------------------------------------------------------- /examples/example.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | 11 | // add your own credentials in this file 12 | require_once __DIR__ . '/credentials.php'; 13 | 14 | // required to load (only when not using an autoloader) 15 | require_once __DIR__ . '/../vendor/autoload.php'; 16 | 17 | use JeroenDesloovere\Wunderlist\Wunderlist; 18 | 19 | // define API 20 | $api = new Wunderlist($username, $password); 21 | 22 | /* 23 | * Profile 24 | */ 25 | 26 | // get profile 27 | $items = $api->getProfile(); 28 | 29 | // get settings 30 | //$items = $api->getSettings(); 31 | 32 | /* 33 | * Lists 34 | */ 35 | 36 | // get all lists 37 | //$items = $api->getLists(); 38 | 39 | // get a list 40 | //$items = $api->getList('ENTER_YOUR_LIST_ID_HERE'); 41 | 42 | // get shares for a list 43 | //$items = $api->getListShares('ENTER_YOUR_LIST_ID_HERE'); 44 | 45 | /* 46 | * Tasks 47 | */ 48 | 49 | // get all tasks 50 | //$items = $api->getTasks(); 51 | 52 | // get all tasks from inbox 53 | //$items = $api->getTasksFromInbox(); 54 | 55 | // get a task 56 | //$items = $api->getTask('ENTER_YOUR_TASK_ID_HERE'); 57 | 58 | // get all task messages 59 | //$items = $api->getTaskMessages('ENTER_YOUR_TASK_ID_HERE'); 60 | 61 | /* 62 | * Other 63 | */ 64 | 65 | // get all events 66 | //$items = $api->getEvents(); 67 | 68 | // get all friends 69 | //$items = $api->getFriends(); 70 | 71 | // get all reminders 72 | //$items = $api->getReminders(); 73 | 74 | // get all shares 75 | //$items = $api->getShares(); 76 | 77 | // get all services 78 | //$items = $api->getServices(); 79 | 80 | /* 81 | * Inserts 82 | */ 83 | 84 | $listId = ''; 85 | //$taskId = ''; 86 | 87 | // insert a list 88 | //$items = $api->insertList('NEW'); 89 | 90 | // insert a task 91 | //$items = $api->insertTask('NEW TASK', $listId); 92 | 93 | /* 94 | * Deletes 95 | */ 96 | 97 | // delete list 98 | //$items = $api->deleteList($listId); 99 | 100 | // delete task 101 | //$items = $api->deleteTask($taskId); 102 | 103 | // dump items 104 | print_r($items); 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wunderlist PHP Class 2 | [![Latest Stable Version](http://img.shields.io/packagist/v/jeroendesloovere/wunderlist-php-api.svg)](https://packagist.org/packages/jeroendesloovere/wunderlist-php-api) 3 | [![License](http://img.shields.io/badge/license-MIT-lightgrey.svg)](https://github.com/jeroendesloovere/wunderlist-php-api/blob/master/LICENSE) 4 | [![Build Status](https://travis-ci.org/jeroendesloovere/wunderlist-php-api.svg?branch=master)](https://travis-ci.org/jeroendesloovere/wunderlist-php-api) 5 | 6 | > Wunderlist is a to-do-task app with lots of possibilities. Lists can be created with tasks, sub-tasks, reminders, files and notes. Lists, tasks and sub-tasks can be re-arranged. Lists can be shared with other users and tasks can be starred. 7 | 8 | This Wunderlist PHP Class connects to the Wunderlist API and has all functions implemented to insert/update/delete lists, tasks, reminders, files, notes, ... 9 | 10 | This class is based on [PENDOnl/Wunderlist2-PHP-Wrapper](https://github.com/PENDOnl/Wunderlist2-PHP-Wrapper), but I've **rewritten it from the ground up** to match the latest PHP PSR-code-stylings. Works perfectly using Composer. 11 | 12 | ## Usage 13 | 14 | ### Installation 15 | 16 | ``` json 17 | { 18 | "require": { 19 | "jeroendesloovere/wunderlist-php-api": "dev-master" 20 | } 21 | } 22 | ``` 23 | 24 | > Add the above in your `composer.json` file when using [Composer](https://getcomposer.org). 25 | 26 | ### Example 27 | ``` php 28 | // required to load (only when not using an autoloader) 29 | require_once __DIR__ . '/src/Wunderlist.php'; 30 | 31 | // define API 32 | $api = new \JeroenDesloovere\Wunderlist\Wunderlist('username', 'password'); 33 | 34 | // get profile 35 | $profile = $api->getProfile(); 36 | 37 | // get lists 38 | $lists = $api->getLists(); 39 | 40 | // get tasks 41 | $tasks = $api->getTasks(); 42 | 43 | // ... 44 | ``` 45 | 46 | > [View all examples](/examples/example.php) or check [the Wunderlist class](/src/Wunderlist.php). 47 | 48 | ## Documentation 49 | 50 | The class is well documented inline. If you use a decent IDE you'll see that each method is documented with PHPDoc. 51 | 52 | ## Contributing 53 | 54 | Contributions are **welcome** and will be fully **credited**. 55 | 56 | ### Pull Requests 57 | 58 | > To add or update code 59 | 60 | - **Coding Syntax** - Please keep the code syntax consistent with the rest of the package. 61 | - **Add unit tests!** - Your patch won't be accepted if it doesn't have tests. 62 | - **Document any change in behavior** - Make sure the README and any other relevant documentation are kept up-to-date. 63 | - **Consider our release cycle** - We try to follow [semver](http://semver.org/). Randomly breaking public APIs is not an option. 64 | - **Create topic branches** - Don't ask us to pull from your master branch. 65 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. 66 | - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting. 67 | 68 | ### Issues 69 | 70 | > For bug reporting or code discussions. 71 | 72 | More info on how to work with GitHub on help.github.com. 73 | 74 | ## Credits 75 | 76 | - [Jeroen Desloovere](https://github.com/jeroendesloovere) 77 | - [All Contributors](https://github.com/jeroendesloovere/wunderlist-php-api/contributors) 78 | 79 | ## License 80 | 81 | The module is licensed under [MIT](./LICENSE). In short, this license allows you to do everything as long as the copyright statement stays present. -------------------------------------------------------------------------------- /src/Wunderlist.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class Wunderlist 20 | { 21 | // API URL 22 | const API_URL = 'https://api.wunderlist.com'; 23 | 24 | // internal constant to enable/disable debugging 25 | const DEBUG = false; 26 | 27 | // current class version 28 | const VERSION = '1.0.0'; 29 | 30 | /** 31 | * Authorization token 32 | * 33 | * @var string 34 | */ 35 | protected $authToken; 36 | 37 | /** 38 | * The password that will be used for authenticating 39 | * 40 | * @var string 41 | */ 42 | protected $password; 43 | 44 | /** 45 | * The username/email that will be used for authenticating 46 | * 47 | * @var string 48 | */ 49 | protected $username; 50 | 51 | /** 52 | * Constructs the Wunderlist API 53 | * 54 | * @param string $username 55 | * @param string $password 56 | * @return void 57 | */ 58 | public function __construct($username, $password) 59 | { 60 | // define credentials 61 | $this->username = (string) $username; 62 | $this->password = (string) $password; 63 | 64 | // authenticate credentials 65 | $this->authenticate(); 66 | } 67 | 68 | /** 69 | * Authenticate credentials by logging in 70 | */ 71 | protected function authenticate() 72 | { 73 | // init parameters 74 | $parameters = array(); 75 | 76 | // build parameters 77 | $parameters['email'] = $this->username; 78 | $parameters['password'] = $this->password; 79 | 80 | // login to check if credentials are correct 81 | $response = $this->doCall('login', $parameters, 'POST'); 82 | 83 | if ($response) { 84 | // define authorization token 85 | $this->authToken = $response['token']; 86 | } else { 87 | // error 88 | throw new WunderlistException('Could not Authenticate.'); 89 | } 90 | } 91 | 92 | /** 93 | * Delete list 94 | * 95 | * @param string $listId 96 | * @return bool 97 | */ 98 | public function deleteList($listId) 99 | { 100 | // delete list 101 | $result = $this->doCall($listId, null, 'DELETE'); 102 | 103 | // if delete was successfull an empty result is return 104 | return (is_array($result) && count($result) == 0); 105 | } 106 | 107 | /** 108 | * Delete task 109 | * 110 | * @param string $taskId 111 | * @return bool 112 | */ 113 | public function deleteTask($taskId) 114 | { 115 | // delete list 116 | $result = $this->doCall($taskId, null, 'DELETE'); 117 | 118 | // if delete was successfull an empty result is return 119 | return (is_array($result) && count($result) == 0); 120 | } 121 | 122 | /** 123 | * Call a certain method with its parameters 124 | * 125 | * @param string $endPoint 126 | * @param string $parameters[optional] 127 | * @param string $method[optional] 128 | * @return false or array 129 | */ 130 | protected function doCall($endPoint, $parameters = array(), $method = 'GET') 131 | { 132 | // check if curl is available 133 | if (!function_exists('curl_init')) { 134 | throw new WunderlistException('This method requires cURL (http://php.net/curl), it seems like the extension isn\'t installed.'); 135 | } 136 | 137 | // define url 138 | $url = self::API_URL . '/' . $endPoint; 139 | 140 | // init curl 141 | $curl = curl_init(); 142 | 143 | // set options 144 | curl_setopt($curl, CURLOPT_URL, $url); 145 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 146 | curl_setopt($curl, CURLOPT_TIMEOUT, 10); 147 | 148 | // init headers 149 | $headers = array(); 150 | 151 | // we have an authorization token 152 | if (!empty($this->authToken)) { 153 | // add to header 154 | $headers[] = 'authorization: Bearer ' . $this->authToken; 155 | } 156 | 157 | // define headers with the request 158 | if (!empty($headers)) { 159 | // add headers 160 | curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); 161 | } 162 | 163 | // parameters are set 164 | if (!empty($parameters)) { 165 | curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($parameters) ); 166 | } 167 | 168 | // method is POST, used for login or inserts 169 | if ($method == 'POST') { 170 | // define post method 171 | curl_setopt($curl, CURLOPT_POST, true); 172 | // method is DELETE 173 | } elseif ($method == 'DELETE') { 174 | curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE'); 175 | } 176 | 177 | // execute 178 | $response = curl_exec($curl); 179 | 180 | // debug is on 181 | if (self::DEBUG) { 182 | echo $url . '
'; 183 | print_r($response); 184 | echo '

'; 185 | } 186 | 187 | // get HTTP response code 188 | $httpCode = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE); 189 | 190 | // close 191 | curl_close($curl); 192 | 193 | // response is empty or false 194 | if (empty($response)) { 195 | throw new WunderlistException('Error: ' . $response); 196 | } 197 | 198 | // init result 199 | $result = false; 200 | 201 | // successfull response 202 | if (($httpCode == 200) || ($httpCode == 201)) { 203 | $result = json_decode($response, true); 204 | } 205 | 206 | // return 207 | return $result; 208 | } 209 | 210 | /** 211 | * Get events 212 | * 213 | * @return array 214 | */ 215 | public function getEvents() 216 | { 217 | return $this->doCall('me/events'); 218 | } 219 | 220 | /** 221 | * Get friends 222 | * 223 | * @return array 224 | */ 225 | public function getFriends() 226 | { 227 | return $this->doCall('me/friends'); 228 | } 229 | 230 | /** 231 | * Get a list 232 | * 233 | * @param string $listId 234 | * @return array 235 | */ 236 | public function getList($listId) 237 | { 238 | return $this->doCall('me/' . $listId); 239 | } 240 | 241 | /** 242 | * Get shares for a list 243 | * 244 | * @param string $listId 245 | * @return array 246 | */ 247 | public function getListShares($listId) 248 | { 249 | return $this->doCall('me/' . $listId . '/shares'); 250 | } 251 | 252 | /** 253 | * Get lists 254 | * 255 | * @return array 256 | */ 257 | public function getLists() 258 | { 259 | return $this->doCall('me/lists'); 260 | } 261 | 262 | /** 263 | * Get profile from user 264 | * 265 | * @return array 266 | */ 267 | public function getProfile() 268 | { 269 | return $this->doCall('me'); 270 | } 271 | 272 | /** 273 | * Get quota 274 | * 275 | * @return array 276 | */ 277 | public function getQuota() 278 | { 279 | return $this->doCall('me/quota'); 280 | } 281 | 282 | /** 283 | * Get reminders 284 | * 285 | * @return array 286 | */ 287 | public function getReminders() 288 | { 289 | return $this->doCall('me/reminders'); 290 | } 291 | 292 | /** 293 | * Get services 294 | * 295 | * @return array 296 | */ 297 | public function getServices() 298 | { 299 | return $this->doCall('me/services'); 300 | } 301 | 302 | /** 303 | * Get settings 304 | * 305 | * @return array 306 | */ 307 | public function getSettings() 308 | { 309 | return $this->doCall('me/settings'); 310 | } 311 | 312 | /** 313 | * Get shares 314 | * 315 | * @return array 316 | */ 317 | public function getShares() 318 | { 319 | return $this->doCall('me/shares'); 320 | } 321 | 322 | /** 323 | * Get a task 324 | * 325 | * @param string $taskId 326 | * @return array 327 | */ 328 | public function getTask($taskId) 329 | { 330 | return $this->doCall('me/' . $taskId); 331 | } 332 | 333 | /** 334 | * Get messages for a task 335 | * 336 | * @param string $taskId 337 | * @return array 338 | */ 339 | public function getTaskMessages($taskId) 340 | { 341 | return $this->doCall('me/' . $taskId . '/messages'); 342 | } 343 | 344 | /** 345 | * Get tasks 346 | * 347 | * @return array 348 | */ 349 | public function getTasks() 350 | { 351 | return $this->doCall('me/tasks'); 352 | } 353 | 354 | /** 355 | * Get tasks from inbox 356 | * 357 | * @return array 358 | */ 359 | public function getTasksFromInbox() 360 | { 361 | return $this->doCall('inbox/tasks'); 362 | } 363 | 364 | /** 365 | * Insert list 366 | * 367 | * @param string $title 368 | * @return array 369 | */ 370 | public function insertList($title) 371 | { 372 | // init parameters 373 | $parameters = array(); 374 | 375 | // build parameters 376 | $parameters['title'] = (string) $title; 377 | 378 | // insert list 379 | return $this->doCall('me/lists', $parameters, 'POST'); 380 | } 381 | 382 | /** 383 | * Insert task 384 | * 385 | * @param string $title 386 | * @param string $listId 387 | * @param string $parentId[optional] 388 | * @param string $dueDate[optional] 389 | * @param bool $starred[optional] 390 | * @return array 391 | */ 392 | public function insertTask($title, $listId, $parentId = null, $dueDate = null, $starred = false) 393 | { 394 | // init parameters 395 | $parameters = array(); 396 | 397 | // build parameters 398 | $parameters['title'] = (string) $title; 399 | $parameters['list_id'] = (string) $listId; 400 | $parameters['starred'] = ((bool) $starred) ? 1 : 0; 401 | 402 | // we have a parent id 403 | if ($parentId !== null) { 404 | // add to parameters 405 | $parameters['parent_id'] = $parentId; 406 | } 407 | 408 | // we have a due date 409 | if ($dueDate !== null) { 410 | // is no time 411 | if (!strtotime($dueDate)) { 412 | // throw error 413 | throw new WunderlistException('Parameters dueDate is invalid.'); 414 | } 415 | 416 | // add parameter 417 | $parameters['due_date'] = date('Y-m-d', strtotime($dueDate)); 418 | } 419 | 420 | // return insert task 421 | return $this->doCall('me/tasks', $parameters, 'POST'); 422 | } 423 | } 424 | --------------------------------------------------------------------------------