Fix PHP warning: Trying to access array offset on value of type null
[roundcube-nextcloud_sql_addressbook.git] / nextcloud_sql_addressbook.php
1 <?php
2 require_once __DIR__ . '/nextcloud_sql_addressbook_backend.php';
3
4 /**
5  * Make a user's Nextcloud address books available in Roundcube.
6  *
7  * Directly accesses the database, which is much faster than using CardDAV.
8  *
9  * @author  Christian Weiske <cweiske@cweiske.de>
10  * @license AGPLv3+ http://www.gnu.org/licenses/agpl.html
11  */
12 class nextcloud_sql_addressbook extends rcube_plugin
13 {
14     /**
15      * Main roundcube instance
16      *
17      * @var rcube
18      */
19     protected $rcube;
20
21     /**
22      * Database table prefix
23      *
24      * @var string
25      */
26     protected $prefix = 'oc_';
27
28     /**
29      * Database instance
30      */
31     protected $db;
32
33     /**
34      * Initialization method, needs to be implemented by the plugin itself
35      *
36      * @return void
37      */
38     public function init()
39     {
40         $this->load_config();
41         $this->add_hook('addressbooks_list', [$this, 'addressbooks_list']);
42         $this->add_hook('addressbook_get', [$this, 'addressbook_get']);
43
44         $this->rcube = rcube::get_instance();
45
46         $this->db = rcube_db::factory(
47             $this->rcube->config->get('nextcloud_sql_addressbook_dsn')
48         );
49         $this->db->set_debug((bool) $this->rcube->config->get('sql_debug'));
50
51         $this->prefix = $this->rcube->config->get(
52             'nextcloud_sql_addressbook_dbtableprefix', 'oc_'
53         );
54
55         // use this address books for autocompletion queries
56         $config = rcmail::get_instance()->config;
57         $sources = (array) $config->get(
58             'autocomplete_addressbooks', array('sql')
59         );
60         foreach ($this->listAddressbooks() as $addressBook) {
61             if (!in_array($addressBook['id'], $sources)) {
62                 $sources[] = $addressBook['id'];
63             }
64         }
65         $config->set('autocomplete_addressbooks', $sources);
66     }
67
68     /**
69      * Load the nextcloud address book names
70      *
71      * The "id" may not contain any "-" because that would break "_cid",
72      * the "contact IDs" which are "$contactid-$addressbookid".
73      * See rcmail_get_cids()
74      *
75      * @param array $arguments Unknown data, with a "sources" key that we have
76      *                         to modify
77      *
78      * @return array Arguments with our address books added to the "sources" key
79      */
80     public function addressbooks_list($arguments)
81     {
82         $arguments['sources'] = array_merge(
83             $arguments['sources'], $this->listAddressbooks()
84         );
85         return $arguments;
86     }
87
88     /**
89      * Build a list of address books for the user
90      *
91      * @return array Array of arrays with the following keys:
92      *               id, name, groups, readonly, undelete, autocomplete
93      */
94     protected function listAddressbooks()
95     {
96         if (!isset($this->rcube->user->data)) {
97             return [];
98         }
99
100         $principalUri = 'principals/users/'
101             . $this->rcube->user->data['username'];
102
103         $sql = 'SELECT id, displayname'
104              . ' FROM ' . $this->prefix . 'addressbooks'
105              . ' WHERE principaluri = ?'
106              . ' ORDER BY displayname';
107         $stmt = $this->db->query($sql, [$principalUri]);
108         $addressBooks = [];
109         foreach ($stmt as $row) {
110             $addressBooks[] = [
111                 'id'           => 'nextcloud_' . $row['id'],
112                 'name'         => $row['displayname'] . ' (Nextcloud)',
113                 'groups'       => false,
114                 'readonly'     => true,
115                 'undelete'     => false,
116                 'autocomplete' => true,
117             ];
118         }
119         return $addressBooks;
120     }
121
122     /**
123      * Return a adress book object for the given address book ID
124      *
125      * @param array $arguments Some data with an "id" key that contains the
126      *                         address book ID
127      *
128      * @return array $arguments with added "instance" key
129      */
130     public function addressbook_get($arguments)
131     {
132         $parts = explode('_', $arguments['id'], 2);
133         if (count($parts) != 2 || $parts[0] != 'nextcloud') {
134             return $arguments;
135         }
136
137         $id = $parts[1];
138         //FIXME: security check if this ID really belongs to the user
139
140         $arguments['instance'] = new nextcloud_sql_addressbook_backend(
141             $id, $this->db, $this->prefix
142         );
143
144         return $arguments;
145     }
146 }
147 ?>