/**
  * Download an extension
  *
  * global $wp_filesystem; must me initialized
  *
  * @param string $extension_name
  * @param array $data Extension data from the "available extensions" array
  * @return string|WP_Error WP Filesystem path to the downloaded directory
  */
 private function download($extension_name, $data)
 {
     $wp_error_id = 'fw_extension_download';
     if (empty($data['download'])) {
         return new WP_Error($wp_error_id, sprintf(__('Extension "%s" has no download sources.', 'fw'), $this->get_extension_title($extension_name)));
     }
     /** @var WP_Filesystem_Base $wp_filesystem */
     global $wp_filesystem;
     $wp_fs_tmp_dir = FW_WP_Filesystem::real_path_to_filesystem_path($this->get_tmp_dir());
     if ($wp_filesystem->exists($wp_fs_tmp_dir)) {
         // just in case it already exists, clear everything, it may contain old files
         if (!$wp_filesystem->rmdir($wp_fs_tmp_dir, true)) {
             return new WP_Error($wp_error_id, sprintf(__('Cannot remove temporary directory: %s', 'fw'), $wp_fs_tmp_dir));
         }
     }
     if (!FW_WP_Filesystem::mkdir_recursive($wp_fs_tmp_dir)) {
         return new WP_Error($wp_error_id, sprintf(__('Cannot create temporary directory: %s', 'fw'), $wp_fs_tmp_dir));
     }
     foreach ($data['download'] as $source => $source_data) {
         switch ($source) {
             case 'github':
                 if (empty($source_data['user_repo'])) {
                     return new WP_Error($wp_error_id, sprintf(__('"%s" extension github source "user_repo" parameter is required', 'fw'), $this->get_extension_title($extension_name)));
                 }
                 $transient_name = 'fw_ext_mngr_gh_dl';
                 $transient_ttl = HOUR_IN_SECONDS;
                 $cache = get_site_transient($transient_name);
                 if ($cache === false) {
                     $cache = array();
                 }
                 if (isset($cache[$source_data['user_repo']])) {
                     $download_link = $cache[$source_data['user_repo']]['zipball_url'];
                 } else {
                     $http = new WP_Http();
                     $response = $http->get(apply_filters('fw_github_api_url', 'https://api.github.com') . '/repos/' . $source_data['user_repo'] . '/releases/latest');
                     unset($http);
                     $response_code = intval(wp_remote_retrieve_response_code($response));
                     if ($response_code !== 200) {
                         if ($response_code === 403) {
                             $json_response = json_decode($response['body'], true);
                             if ($json_response) {
                                 return new WP_Error($wp_error_id, __('Github error:', 'fw') . ' ' . $json_response['message']);
                             }
                         } elseif ($response_code) {
                             return new WP_Error($wp_error_id, sprintf(__('Failed to access Github repository "%s" releases. (Response code: %d)', 'fw'), $source_data['user_repo'], $response_code));
                         } elseif (is_wp_error($response)) {
                             return new WP_Error($wp_error_id, sprintf(__('Failed to access Github repository "%s" releases. (%s)', 'fw'), $source_data['user_repo'], $response->get_error_message()));
                         } else {
                             return new WP_Error($wp_error_id, sprintf(__('Failed to access Github repository "%s" releases.', 'fw'), $source_data['user_repo']));
                         }
                     }
                     $release = json_decode($response['body'], true);
                     unset($response);
                     if (empty($release)) {
                         return new WP_Error($wp_error_id, sprintf(__('"%s" extension github repository "%s" has no releases.', 'fw'), $this->get_extension_title($extension_name), $source_data['user_repo']));
                     }
                     $cache[$source_data['user_repo']] = array('zipball_url' => 'https://github.com/' . $source_data['user_repo'] . '/archive/' . $release['tag_name'] . '.zip', 'tag_name' => $release['tag_name']);
                     set_site_transient($transient_name, $cache, $transient_ttl);
                     $download_link = $cache[$source_data['user_repo']]['zipball_url'];
                     unset($release);
                 }
                 $http = new WP_Http();
                 $response = $http->request($download_link, array('timeout' => $this->download_timeout));
                 unset($http);
                 if (($response_code = intval(wp_remote_retrieve_response_code($response))) !== 200) {
                     if ($response_code) {
                         return new WP_Error($wp_error_id, sprintf(__('Cannot download the "%s" extension zip. (Response code: %d)', 'fw'), $this->get_extension_title($extension_name), $response_code));
                     } elseif (is_wp_error($response)) {
                         return new WP_Error($wp_error_id, sprintf(__('Cannot download the "%s" extension zip. %s', 'fw'), $this->get_extension_title($extension_name), $response->get_error_message()));
                     } else {
                         return new WP_Error($wp_error_id, sprintf(__('Cannot download the "%s" extension zip.', 'fw'), $this->get_extension_title($extension_name)));
                     }
                 }
                 $zip_path = $wp_fs_tmp_dir . '/temp.zip';
                 // save zip to file
                 if (!$wp_filesystem->put_contents($zip_path, $response['body'])) {
                     return new WP_Error($wp_error_id, sprintf(__('Cannot save the "%s" extension zip.', 'fw'), $this->get_extension_title($extension_name)));
                 }
                 unset($response);
                 $unzip_result = unzip_file(FW_WP_Filesystem::filesystem_path_to_real_path($zip_path), $wp_fs_tmp_dir);
                 if (is_wp_error($unzip_result)) {
                     return $unzip_result;
                 }
                 // remove zip file
                 if (!$wp_filesystem->delete($zip_path, false, 'f')) {
                     return new WP_Error($wp_error_id, sprintf(__('Cannot remove the "%s" extension downloaded zip.', 'fw'), $this->get_extension_title($extension_name)));
                 }
                 $unzipped_dir_files = $wp_filesystem->dirlist($wp_fs_tmp_dir);
                 if (!$unzipped_dir_files) {
                     return new WP_Error($wp_error_id, __('Cannot access the unzipped directory files.', 'fw'));
                 }
                 /**
                  * get first found directory
                  * (if everything worked well, there should be only one directory)
                  */
                 foreach ($unzipped_dir_files as $file) {
                     if ($file['type'] == 'd') {
                         return $wp_fs_tmp_dir . '/' . $file['name'];
                     }
                 }
                 return new WP_Error($wp_error_id, sprintf(__('The unzipped "%s" extension directory not found.', 'fw'), $this->get_extension_title($extension_name)));
                 break;
             default:
                 return new WP_Error($wp_error_id, sprintf(__('Unknown "%s" extension download source "%s"', 'fw'), $this->get_extension_title($extension_name), $source));
         }
     }
 }
 /**
  * {@inheritdoc}
  * @internal
  */
 public function _download_framework($version, $wp_filesystem_download_directory)
 {
     /** @var WP_Filesystem_Base $wp_filesystem */
     global $wp_filesystem;
     $user_slash_repo = fw()->manifest->get($this->manifest_key);
     $http = new WP_Http();
     $response = $http->get('https://api.github.com/repos/' . $user_slash_repo . '/releases');
     unset($http);
     if (wp_remote_retrieve_response_code($response) !== 200) {
         return new WP_Error('fw_ext_update_github_framework_download_releases_failed', __('Failed to access Github repository releases.', 'fw'));
     }
     $releases = json_decode($response['body'], true);
     unset($response);
     if (empty($releases)) {
         return new WP_Error('fw_ext_update_github_framework_download_no_releases', __('Github repository has no releases.', 'fw'));
     }
     $release = false;
     foreach ($releases as $_release) {
         if ($_release['tag_name'] === $version) {
             $release = $_release;
         }
     }
     if (empty($release)) {
         return new WP_Error('fw_ext_update_github_framework_download_not_existing_release', sprintf(__('Requested version (release) for download does not exists "%s".', 'fw'), $version));
     }
     $http = new WP_Http();
     $response = $http->request($release['zipball_url'], array('timeout' => $this->download_timeout));
     unset($http);
     if (wp_remote_retrieve_response_code($response) !== 200) {
         return new WP_Error('fw_ext_update_github_framework_download_failed', __('Failed to download framework zip.', 'fw'));
     }
     $zip_path = $wp_filesystem_download_directory . '/temp.zip';
     // save zip to file
     $wp_filesystem->put_contents($zip_path, $response['body']);
     unset($response);
     unzip_file(FW_WP_Filesystem::filesystem_path_to_real_path($zip_path), $wp_filesystem_download_directory);
     // remove zip file
     $wp_filesystem->delete($zip_path, false, 'f');
     $unzipped_dir = $wp_filesystem->dirlist($wp_filesystem_download_directory);
     $unzipped_dir = $wp_filesystem_download_directory . '/' . key($unzipped_dir);
     return $unzipped_dir;
 }
 private function perform_zip_download(FW_Ext_Download_Source $download_source, array $opts, $wp_fs_tmp_dir)
 {
     $wp_error_id = 'fw_extension_download';
     /** @var WP_Filesystem_Base $wp_filesystem */
     global $wp_filesystem;
     $zip_path = $wp_fs_tmp_dir . '/temp.zip';
     $download_result = $download_source->download($opts, $zip_path);
     /**
      * Pass further the error, if the service returned one.
      */
     if (is_wp_error($download_result)) {
         return $download_result;
     }
     $extension_name = $opts['extension_name'];
     $unzip_result = unzip_file(FW_WP_Filesystem::filesystem_path_to_real_path($zip_path), $wp_fs_tmp_dir);
     if (is_wp_error($unzip_result)) {
         return $unzip_result;
     }
     // remove zip file
     if (!$wp_filesystem->delete($zip_path, false, 'f')) {
         return new WP_Error($wp_error_id, sprintf(__('Cannot remove the "%s" extension downloaded zip.', 'fw'), $this->get_extension_title($extension_name)));
     }
     $unzipped_dir_files = $wp_filesystem->dirlist($wp_fs_tmp_dir);
     if (!$unzipped_dir_files) {
         return new WP_Error($wp_error_id, __('Cannot access the unzipped directory files.', 'fw'));
     }
     /**
      * get first found directory
      * (if everything worked well, there should be only one directory)
      */
     foreach ($unzipped_dir_files as $file) {
         if ($file['type'] == 'd') {
             return $wp_fs_tmp_dir . '/' . $file['name'];
         }
     }
     return new WP_Error($wp_error_id, sprintf(__('The unzipped "%s" extension directory not found.', 'fw'), $this->get_extension_title($extension_name)));
 }
 /**
  * @param string $user_slash_repo Github 'user/repo'
  * @param string $version Requested version to download
  * @param string $wp_filesystem_download_directory Allocated temporary empty directory
  * @param string $title Used in messages
  *
  * @return string|WP_Error Path to the downloaded directory
  */
 private function download($user_slash_repo, $version, $wp_filesystem_download_directory, $title)
 {
     $http = new WP_Http();
     $response = $http->get($this->get_github_api_url('/repos/' . $user_slash_repo . '/releases/tags/' . $version));
     unset($http);
     $response_code = intval(wp_remote_retrieve_response_code($response));
     if ($response_code !== 200) {
         if ($response_code === 403) {
             $json_response = json_decode($response['body'], true);
             if ($json_response) {
                 return new WP_Error('fw_ext_update_github_download_releases_failed', __('Github error:', 'fw') . ' ' . $json_response['message']);
             }
         }
         if ($response_code) {
             return new WP_Error('fw_ext_update_github_download_releases_failed', sprintf(__('Failed to access Github repository "%s" releases. (Response code: %d)', 'fw'), $user_slash_repo, $response_code));
         } else {
             return new WP_Error('fw_ext_update_github_download_releases_failed', sprintf(__('Failed to access Github repository "%s" releases.', 'fw'), $user_slash_repo));
         }
     }
     $release = json_decode($response['body'], true);
     unset($response);
     if (empty($release)) {
         return new WP_Error('fw_ext_update_github_download_no_release', sprintf(__('%s github repository "%s" does not have the "%s" release.', 'fw'), $title, $user_slash_repo, $version));
     }
     $http = new WP_Http();
     $response = $http->request('https://github.com/' . $user_slash_repo . '/archive/' . $release['tag_name'] . '.zip', array('timeout' => $this->download_timeout));
     unset($http);
     if (intval(wp_remote_retrieve_response_code($response)) !== 200) {
         return new WP_Error('fw_ext_update_github_download_failed', sprintf(__('Cannot download %s zip.', 'fw'), $title));
     }
     /** @var WP_Filesystem_Base $wp_filesystem */
     global $wp_filesystem;
     $zip_path = $wp_filesystem_download_directory . '/temp.zip';
     // save zip to file
     if (!$wp_filesystem->put_contents($zip_path, $response['body'])) {
         return new WP_Error('fw_ext_update_github_save_download_failed', sprintf(__('Cannot save %s zip.', 'fw'), $title));
     }
     unset($response);
     $unzip_result = unzip_file(FW_WP_Filesystem::filesystem_path_to_real_path($zip_path), $wp_filesystem_download_directory);
     if (is_wp_error($unzip_result)) {
         return $unzip_result;
     }
     // remove zip file
     if (!$wp_filesystem->delete($zip_path, false, 'f')) {
         return new WP_Error('fw_ext_update_github_remove_downloaded_zip_failed', sprintf(__('Cannot remove %s zip.', 'fw'), $title));
     }
     $unzipped_dir_files = $wp_filesystem->dirlist($wp_filesystem_download_directory);
     if (!$unzipped_dir_files) {
         return new WP_Error('fw_ext_update_github_unzipped_dir_fail', __('Cannot access the unzipped directory files.', 'fw'));
     }
     /**
      * get first found directory
      * (if everything worked well, there should be only one directory)
      */
     foreach ($unzipped_dir_files as $file) {
         if ($file['type'] == 'd') {
             return $wp_filesystem_download_directory . '/' . $file['name'];
         }
     }
     return new WP_Error('fw_ext_update_github_unzipped_dir_not_found', sprintf(__('The unzipped %s directory not found.', 'fw'), $title));
 }