Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
   1  <?php
   2  require_once($CFG->libdir.'/portfolio/plugin.php');
   3  require_once($CFG->libdir.'/filelib.php');
   4  require_once($CFG->libdir.'/boxlib.php');
   5  
   6  class portfolio_plugin_boxnet extends portfolio_plugin_push_base {
   7  
   8      public $boxclient;
   9      private $ticket;
  10      private $authtoken;
  11      private $folders;
  12      private $accounttree;
  13  
  14      public static function get_name() {
  15          return get_string('pluginname', 'portfolio_boxnet');
  16      }
  17  
  18      public function prepare_package() {
  19          // don't do anything for this plugin, we want to send all files as they are.
  20      }
  21  
  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              $created = $this->boxclient->create_folder($newfolder);
  26              if (empty($created->id)) {
  27                  throw new portfolio_plugin_exception('foldercreatefailed', 'portfolio_boxnet');
  28              }
  29              $this->folders[$created->id] = $created->name;
  30              $this->set_export_config(array('folder' => $created->id));
  31          }
  32          foreach ($this->exporter->get_tempfiles() as $file) {
  33              $return = $this->boxclient->upload_file($file, $this->get_export_config('folder'));
  34              if (!empty($result->type) && $result->type == 'error') {
  35                  throw new portfolio_plugin_exception('sendfailed', 'portfolio_boxnet', $result->message);
  36              }
  37              $createdfile = reset($return->entries);
  38              if (!empty($createdfile->id)) {
  39                  $result = $this->rename_file($createdfile->id, $file->get_filename());
  40                  // If this fails, the file was sent but not renamed.
  41              }
  42          }
  43      }
  44  
  45      public function get_export_summary() {
  46          $allfolders = $this->get_folder_list();
  47          if ($newfolder = $this->get_export_config('newfolder')) {
  48              $foldername = $newfolder . ' (' . get_string('tobecreated', 'portfolio_boxnet') . ')';
  49          } else if ($this->get_export_config('folder')) {
  50              $foldername = $allfolders[$this->get_export_config('folder')];
  51          } else {
  52              $foldername = '/';
  53          }
  54          return array(
  55              get_string('targetfolder', 'portfolio_boxnet') => s($foldername)
  56          );
  57      }
  58  
  59      public function get_interactive_continue_url() {
  60          return 'https://app.box.net/files/0/f/' . $this->get_export_config('folder') . '/';
  61      }
  62  
  63      public function expected_time($callertime) {
  64          // We're forcing this to be run 'interactively' because the plugin
  65          // does not support running in cron.
  66          return PORTFOLIO_TIME_LOW;
  67      }
  68  
  69      public static function has_admin_config() {
  70          return true;
  71      }
  72  
  73      public static function get_allowed_config() {
  74          return array('clientid', 'clientsecret');
  75      }
  76  
  77      public function has_export_config() {
  78          return true;
  79      }
  80  
  81      public function get_allowed_export_config() {
  82          return array('folder', 'newfolder');
  83      }
  84  
  85      public function export_config_form(&$mform) {
  86          $folders = $this->get_folder_list();
  87          $mform->addElement('text', 'plugin_newfolder', get_string('newfolder', 'portfolio_boxnet'));
  88          $mform->setType('plugin_newfolder', PARAM_RAW);
  89          $folders[0] = '/';
  90          ksort($folders);
  91          $mform->addElement('select', 'plugin_folder', get_string('existingfolder', 'portfolio_boxnet'), $folders);
  92      }
  93  
  94      public function export_config_validation(array $data) {
  95          $allfolders = $this->get_folder_list();
  96          if (in_array($data['plugin_newfolder'], $allfolders)) {
  97              return array('plugin_newfolder' => get_string('folderclash', 'portfolio_boxnet'));
  98          }
  99      }
 100  
 101      public static function admin_config_form(&$mform) {
 102          global $CFG;
 103  
 104          $mform->addElement('text', 'clientid', get_string('clientid', 'portfolio_boxnet'));
 105          $mform->addRule('clientid', get_string('required'), 'required', null, 'client');
 106          $mform->setType('clientid', PARAM_RAW_TRIMMED);
 107  
 108          $mform->addElement('text', 'clientsecret', get_string('clientsecret', 'portfolio_boxnet'));
 109          $mform->addRule('clientsecret', get_string('required'), 'required', null, 'client');
 110          $mform->setType('clientsecret', PARAM_RAW_TRIMMED);
 111  
 112          $a = new stdClass();
 113          $a->servicesurl = 'https://app.box.com/developers/services';
 114          $mform->addElement('static', 'setupinfo', get_string('setupinfo', 'portfolio_boxnet'),
 115              get_string('setupinfodetails', 'portfolio_boxnet', $a));
 116  
 117          if (!is_https()) {
 118              $mform->addElement('static', 'warninghttps', '', get_string('warninghttps', 'portfolio_boxnet'));
 119          }
 120      }
 121  
 122      public function steal_control($stage) {
 123          if ($stage != PORTFOLIO_STAGE_CONFIG) {
 124              return false;
 125          }
 126          if (empty($this->boxclient)) {
 127              $returnurl = new moodle_url('/portfolio/add.php', array('postcontrol' => 1, 'type' => 'boxnet',
 128                  'sesskey' => sesskey()));
 129              $this->boxclient = new boxnet_client($this->get_config('clientid'), $this->get_config('clientsecret'), $returnurl, '');
 130          }
 131          if ($this->boxclient->is_logged_in()) {
 132              return false;
 133          }
 134          return $this->boxclient->get_login_url();
 135      }
 136  
 137      public function post_control($stage, $params) {
 138          if ($stage != PORTFOLIO_STAGE_CONFIG) {
 139              return;
 140          }
 141          if (!$this->boxclient->is_logged_in()) {
 142              throw new portfolio_plugin_exception('noauthtoken', 'portfolio_boxnet');
 143          }
 144      }
 145  
 146      /**
 147       * Get the folder list.
 148       *
 149       * This is limited to the folders in the root folder.
 150       *
 151       * @return array of folders.
 152       */
 153      protected function get_folder_list() {
 154          if (empty($this->folders)) {
 155              $folders = array();
 156              $result = $this->boxclient->get_folder_items();
 157              foreach ($result->entries as $item) {
 158                  if ($item->type != 'folder') {
 159                      continue;
 160                  }
 161                  $folders[$item->id] = $item->name;
 162                  if (!empty($item->shared)) {
 163                      $folders[$item->id] .= ' (' . get_string('sharedfolder', 'portfolio_boxnet') . ')';
 164                  }
 165              }
 166              $this->folders = $folders;
 167          }
 168          return $this->folders;
 169      }
 170  
 171      /**
 172       * Rename a file.
 173       *
 174       * If the name is already taken, we append the current date to the file
 175       * to prevent name conflicts.
 176       *
 177       * @param int $fileid The file ID.
 178       * @param string $newname The new name.
 179       * @return bool Whether it succeeded or not.
 180       */
 181      protected function rename_file($fileid, $newname) {
 182          $result = $this->boxclient->rename_file($fileid, $newname);
 183          if (!empty($result->type) && $result->type == 'error') {
 184              $bits = explode('.', $newname);
 185              $suffix = '';
 186              if (count($bits) == 1) {
 187                  $prefix = $newname;
 188              } else {
 189                  $suffix = '.' . array_pop($bits);
 190                  $prefix = implode('.', $bits);
 191              }
 192              $newname = $prefix . ' (' . date('Y-m-d H-i-s') . ')' . $suffix;
 193              $result = $this->boxclient->rename_file($fileid, $newname);
 194              if (empty($result->type) || $result->type != 'error') {
 195                  return true;
 196              } else {
 197                  // We could not rename the file for some reason...
 198                  debugging('Error while renaming the file on Box.net', DEBUG_DEVELOPER);
 199              }
 200          } else {
 201              return true;
 202          }
 203          return false;
 204      }
 205  
 206      public function instance_sanity_check() {
 207          global $CFG;
 208          if (!$this->get_config('clientid') || !$this->get_config('clientsecret')) {
 209              return 'missingoauthkeys';
 210          } else if (!is_https()) {
 211              return 'missinghttps';
 212          }
 213      }
 214  
 215      public static function allows_multiple_instances() {
 216          return false;
 217      }
 218  
 219      public function supported_formats() {
 220          return array(PORTFOLIO_FORMAT_FILE, PORTFOLIO_FORMAT_RICHHTML);
 221      }
 222  
 223      /*
 224       * for now , boxnet doesn't support this,
 225       * because we can't dynamically construct return urls.
 226       */
 227      public static function allows_multiple_exports() {
 228          return false;
 229      }
 230  }