├── .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 | [](https://packagist.org/packages/jeroendesloovere/wunderlist-php-api)
3 | [](https://github.com/jeroendesloovere/wunderlist-php-api/blob/master/LICENSE)
4 | [](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 |
--------------------------------------------------------------------------------