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