MDL-15666 - change all the portfolio plugins and callers to use exceptions
[moodle.git] / portfolio / type / boxnet / lib.php
1 <?php
2 require_once($CFG->libdir.'/filelib.php');
3 require_once($CFG->libdir.'/boxlib.php');
5 class portfolio_plugin_boxnet extends portfolio_plugin_push_base {
7     public $boxclient;
8     private $ticket;
9     private $authtoken;
10     private $folders;
11     private $accounttree;
13     public static function get_name() {
14         return get_string('pluginname', 'portfolio_boxnet');
15     }
17     public function prepare_package() {
18         // if we need to create the folder, do it now
19         if ($newfolder = $this->get_export_config('newfolder')) {
20             if (!$created = $this->boxclient->createFolder($newfolder, array('share' => $this->get_export_config('sharefolder')))) {
21                 throw new portfolio_plugin_exception('foldercreatefailed', 'portfolio_boxnet');
22             }
23             $this->folders[$created['folder_id']] = $created['folder_name'];
24             $this->set_export_config(array('folder' => $created['folder_id']));
25         }
26         // don't do anything else for this plugin, we want to send all files as they are.
27     }
29     public function send_package() {
30         foreach ($this->exporter->get_tempfiles() as $file) {
31             $return = $this->boxclient->uploadFile(
32                 array(
33                     'file'      => $file,
34                     'folder_id' => $this->get_export_config('folder'),
35                     'share'     => $this->get_export_config('sharefile'),
36                 )
37             );
38             if (array_key_exists('status', $return) && $return['status'] == 'upload_ok'
39                 && array_key_exists('id', $return) && count($return['id']) == 1) {
40                 $this->rename_file($return['id'][array_pop(array_keys($return['id']))], $file->get_filename());
41                 // if this fails, the file was sent but not renamed - this triggers a warning but is not fatal.
42             }
43         }
44         if ($this->boxclient->isError()) {
45             throw new portfolio_plugin_exception('sendfailed', 'portfolio_boxnet', $this->boxclient->getErrorMsg());
46         }
47     }
49     public function get_export_summary() {
50         $allfolders = $this->get_folder_list();
51         if ($newfolder = $this->get_export_config('newfolder')) {
52             $foldername = $newfolder . ' (' . get_string('tobecreated', 'portfolio_boxnet') . ')';
53         } else {
54             $foldername = $allfolders[$this->get_export_config('folder')];
55         }
56         return array(
57             get_string('targetfolder', 'portfolio_boxnet') => $foldername
58         );
59     }
61     public function get_continue_url() {
62         return 'http://box.net/files#0:f:' . $this->get_export_config('folder');
63     }
65     public function expected_time($callertime) {
66         return $callertime;
67     }
69     public static function has_admin_config() {
70         return true;
71     }
73     public static function get_allowed_config() {
74         return array('apikey');
75     }
77     public function has_export_config() {
78         return true;
79     }
81     public function get_allowed_user_config() {
82         return array('authtoken', 'authtokenctime');
83     }
85     public function get_allowed_export_config() {
86         return array('folder', 'newfolder', 'sharefile', 'sharefolder');
87     }
89     public function export_config_form(&$mform) {
90         $folders = $this->get_folder_list();
91         $strrequired = get_string('required');
92         $mform->addElement('checkbox', 'plugin_sharefile', get_string('sharefile', 'portfolio_boxnet'));
93         $mform->addElement('text', 'plugin_newfolder', get_string('newfolder', 'portfolio_boxnet'));
94         $mform->addElement('checkbox', 'plugin_sharefolder', get_string('sharefolder', 'portfolio_boxnet'));
95         if (empty($folders)) {
96             $mform->addRule('plugin_newfolder', $strrequired, 'required', null, 'client');
97         }
98         else {
99             $mform->addElement('select', 'plugin_folder', get_string('existingfolder', 'portfolio_boxnet'), $folders);
100         }
101     }
103     public function export_config_validation($data) {
104         if ((!array_key_exists('plugin_folder', $data) || empty($data['plugin_folder']))
105             && (!array_key_exists('plugin_newfolder', $data) || empty($data['plugin_newfolder']))) {
106             return array(
107                 'plugin_folder' => get_string('notarget', 'portfolio_boxnet'),
108                 'plugin_newfolder' => get_string('notarget', 'portfolio_boxnet'));
109         }
110         $allfolders = $this->get_folder_list();
111         if (in_array($data['plugin_newfolder'], $allfolders)) {
112             return array('plugin_newfolder' => get_string('folderclash', 'portfolio_boxnet'));
113         }
114     }
116     public function admin_config_form(&$mform) {
117         global $CFG;
118         $strrequired = get_string('required');
119         $mform->addElement('text', 'apikey', get_string('apikey', 'portfolio_boxnet'));
120         $helpparams = array(
121             'boxnet_apikey',
122             get_string('apikeyhelp', 'portfolio_boxnet'),
123             'portfolio',
124         );
125         $mform->setHelpButton('apikey', $helpparams);
126         $mform->addRule('apikey', $strrequired, 'required', null, 'client');
127     }
129     public function steal_control($stage) {
130         if ($stage != PORTFOLIO_STAGE_CONFIG) {
131             return false;
132         }
133         if ($this->authtoken) {
134             return false;
135         }
136         if (!$this->ensure_ticket()) {
137             throw new portfolio_plugin_exception('noticket', 'portfolio_boxnet');
138         }
139         $token = $this->get_user_config('authtoken', $this->get('user')->id);
140         $ctime= $this->get_user_config('authtokenctime', $this->get('user')->id);
141         if (!empty($token) && (($ctime + 60*60*20) > time())) {
142             $this->authtoken = $token;
143             $this->boxclient->auth_token = $token;
144             return false;
145         }
146         return 'http://www.box.net/api/1.0/auth/'.$this->ticket;
147     }
149     public function post_control($stage, $params) {
150         if ($stage != PORTFOLIO_STAGE_CONFIG) {
151             return;
152         }
153         if (!array_key_exists('auth_token', $params) || empty($params['auth_token'])) {
154             throw new portfolio_plugin_exception('noauthtoken', 'portfolio_boxnet');
155         }
156         $this->authtoken = $params['auth_token'];
157         $this->boxclient->auth_token = $this->authtoken;
158         $this->set_user_config(array('authtoken' => $this->authtoken, 'authtokenctime' => time()), $this->get('user')->id);
159     }
161     private function ensure_ticket() {
162         if (!empty($this->boxclient)) {
163             return true;
164         }
165         $this->boxclient = new boxclient($this->get_config('apikey'), '');
166         $ticket_return = $this->boxclient->getTicket();
167         if ($this->boxclient->isError() || empty($ticket_return)) {
168             throw new portfolio_plugin_exception('noticket', 'portfolio_boxnet');
169         }
170         $this->ticket = $ticket_return['ticket'];
171         return $this->ticket;
172     }
174     private function ensure_account_tree() {
175         if (!empty($this->accounttree)) {
176             return;
177         }
178         if (empty($this->ticket)
179             || empty($this->authtoken)
180             || empty($this->boxclient)) {
181             // if we don't have these we're pretty much screwed
182             throw new portfolio_plugin_exception('folderlistfailed', 'portfolio_boxnet');
183             return false;
184         }
185         $this->accounttree = $this->boxclient->getAccountTree();
186         if ($this->boxclient->isError()) {
187             throw new portfolio_plugin_exception('folderlistfailed', 'portfolio_boxnet');
188         }
189         if (!is_array($this->accounttree)) {
190             return false;
191         }
192     }
194     private function get_folder_list() {
195         if (!empty($this->folders)) {
196             return $this->folders;
197         }
198         $this->ensure_account_tree();
199         $folders = array();
200         foreach ($this->accounttree['folder_id'] as $key => $id) {
201             if (empty($id)) {
202                 continue;
203             }
204             $name = $this->accounttree['folder_name'][$key];
205             if (!empty($this->accounttree['shared'][$key])) {
206                 $name .= ' (' . get_string('sharedfolder', 'portfolio_boxnet') . ')';
207             }
208             $folders[$id] = $name;
209         }
210         $this->folders = $folders;
211         return $folders;
212     }
214     private function rename_file($fileid, $newname) {
215         // look at moving this to the boxnet client class
216         $this->ensure_account_tree();
217         $count = 1;
218         $bits = explode('.', $newname);
219         $suffix = '';
220         if (count($bits) == 1) {
221             $prefix = $newname;
222         } else {
223             $suffix = '.' . array_pop($bits);
224             $prefix = implode('.', $bits);
225         }
226         while (true) {
227             if (!array_key_exists('file_name', $this->accounttree) || !in_array($newname, $this->accounttree['file_name'])) {
228                 for ($i = 0; $i < 2; $i++) {
229                     if ($this->boxclient->renameFile($fileid, $newname)) {
230                         return true;
231                     }
232                 }
233                 debugging("tried three times to rename file and failed");
234                 return false;
235             }
236             $newname = $prefix . '(' . $count . ')' . $suffix;
237             $count++;
238         }
239         return false;
240     }
242     public function instance_sanity_check() {
243         if (!$this->get_config('apikey')) {
244             return 'err_noapikey';
245         }
246     //@TODO see if we can verify the api key without actually getting an authentication token
247     }
249     public static function allows_multiple() {
250         return false;
251     }