getParam( $response, 'favicon_generation_result' ); $result = $this->getParam( $response, 'result' ); $status = $this->getParam( $result, 'status' ); if ( $status != 'success' ) { $msg = $this->getParam( $result, 'error_message', false ); $msg = $msg != NULL ? $msg : 'An error occured'; throw new InvalidArgumentException( $msg ); } $favicon = $this->getParam( $response, 'favicon' ); $this->params[RFG_PACKAGE_URL] = $this->getParam( $favicon, 'package_url' ); $this->params[RFG_COMPRESSION] = $this->getParam( $favicon, 'compression' ) == 'true'; $this->params[RFG_HTML_CODE] = $this->getParam( $favicon, 'html_code' ); $this->params[RFG_FILES_URLS] = $this->getParam( $favicon, 'files_urls' ); $filesLoc = $this->getParam( $response, 'files_location' ); $this->params[RFG_FILES_IN_ROOT] = $this->getParam( $filesLoc, 'type' ) == 'root'; $this->params[RFG_FILES_PATH] = $this->params[RFG_FILES_IN_ROOT] ? '/' : $this->getParam( $filesLoc, 'path' ); $this->params[RFG_PREVIEW_PICTURE_URL] = $this->getParam( $response, 'preview_picture_url', false ); $this->params[RFG_CUSTOM_PARAMETER] = $this->getParam( $response, 'custom_parameter', false ); $this->params[RFG_VERSION] = $this->getParam($response, 'version', false ); $this->params[RFG_NON_INTERACTIVE_API_REQUEST] = $this->getParam($response, 'non_interactive_request', false ); } /** * For example: "http://realfavicongenerator.net/files/1234f5d2s34f3ds2/package.zip" */ public function getPackageUrl() { return $this->params[RFG_PACKAGE_URL]; } /** * For example: array( "http://realfavicongenerator.net/files/1234f5d2s34f3ds2/apple-touch-icon.png", ... ) */ public function getFilesURLs() { return $this->params[RFG_FILES_URLS]; } /** * For example: "<link ..." */ public function getHtmlCode() { return $this->params[RFG_HTML_CODE]; } /** * true if the user chose to compress the pictures, false otherwise. */ public function isCompressed() { return $this->params[RFG_COMPRESSION]; } /** * true if the favicon files are to be stored in the root directory of the target web site, false otherwise. */ public function isFilesInRoot() { return $this->params[RFG_FILES_IN_ROOT]; } /** * Indicate where the favicon files should be stored in the target web site. For example: "/", "/path/to/icons". */ public function getFilesLocation() { return $this->params[RFG_FILES_PATH]; } /** * For example: "http://realfavicongenerator.net/files/1234f5d2s34f3ds2/preview.png" */ public function getPreviewUrl() { return $this->params[RFG_PREVIEW_PICTURE_URL]; } /** * Return the customer parameter, as it was transmitted during the invocation of the API. */ public function getCustomParameter() { return $this->params[RFG_CUSTOM_PARAMETER]; } /** * Return version of RealFaviconGenerator used to generate the favicon. Save this value to later check for updates. */ public function getVersion() { return $this->params[RFG_VERSION]; } /** * Return the non-interactive API request that matches the current interactive request. */ public function getNonInteractiveAPIRequest() { return $this->params[RFG_NON_INTERACTIVE_API_REQUEST]; } private function getParam( $params, $paramName, $throwIfNotFound = true ) { if ( isset( $params[$paramName] ) ) { return $params[$paramName]; } else if ( $throwIfNotFound ) { throw new InvalidArgumentException( "Cannot find parameter " . $paramName ); } } /** * Download and extract the files referenced by the response sent back by RealFaviconGenerator. * * Warning: as this method does HTTP accesses, calling it can take a few seconds. Better invoke it * in an Ajax call, to not slow down the user experience. */ public function downloadAndUnpack( $outputDirectory = NULL ) { global $wp_filesystem; if ( $outputDirectory == NULL ) { $outputDirectory = get_temp_dir(); } $outputDirectory = $this->append_directory_separator( $outputDirectory ); if ( $this->getPackageUrl() != NULL ) { $extractedPath = $outputDirectory . 'favicon_package'; if ( ! file_exists( $extractedPath ) ) { if ( mkdir( $extractedPath, 0755, true ) !== true ) { throw new InvalidArgumentException( sprintf( __( 'Cannot create directory %s to store the favicon package content', FBRFG_PLUGIN_SLUG), $extractedPath ) ); } } try { $this->downloadZipFile( $outputDirectory, $extractedPath, $this->getPackageUrl() ); } catch(Exception $e) { // Zip file download failed, try getting files directly $this->downloadFilesDirectly( $extractedPath, array() ); } } if ( $this->getPreviewUrl() != NULL ) { $previewPath = $outputDirectory . 'favicon_preview.png'; $this->downloadFile( $previewPath, $this->getPreviewUrl() ); $this->params[RFG_PREVIEW_PATH] = $previewPath; } } public function downloadFilesDirectly( $outputDirectory, $filesURLs ) { foreach($this->getFilesURLs() as $fileURL ) { $parts = parse_url( $fileURL ); $filePath = $outputDirectory . DIRECTORY_SEPARATOR . basename( $parts['path'] ); $this->downloadFile( $filePath, $fileURL ); } $this->params[RFG_FAVICON_PRODUCTION_PACKAGE_PATH] = $outputDirectory; if ( $this->isCompressed() ) { $this->params[RFG_FAVICON_COMPRESSED_PACKAGE_PATH] = $extractedPath; $this->params[RFG_FAVICON_UNCOMPRESSED_PACKAGE_PATH] = NULL; } else { $this->params[RFG_FAVICON_COMPRESSED_PACKAGE_PATH] = NULL; $this->params[RFG_FAVICON_UNCOMPRESSED_PACKAGE_PATH] = $extractedPath; } } public function downloadZipFile( $packageDirectory, $extractedPath, $packageUrl ) { $packagePath = $packageDirectory . 'favicon_package.zip'; $this->downloadFile( $packagePath, $packageUrl ); $ret = WP_Filesystem(); $result = unzip_file( $packagePath, $extractedPath ); if ( $result !== true ) { $explanation = ( is_wp_error( $result ) ) ? $result->get_error_message() : __( 'Unknown reason', Favicon_By_RealFaviconGenerator_Common::PLUGIN_SLUG ); if ( get_class($wp_filesystem) != 'WP_Filesystem_Direct' ) { $explanation .= ' ' . __( "Apparently WordPress has no direct access to the file system (it uses another mean such as FTP). " . "This may be the root cause of this issue.", Favicon_By_RealFaviconGenerator_Common::PLUGIN_SLUG ); } throw new InvalidArgumentException( sprintf( __( 'Error while unziping the favicon package %s to directory %s', Favicon_By_RealFaviconGenerator_Common::PLUGIN_SLUG ), $packagePath, $extractedPath ) . ': ' . $explanation ); } if ( $this->isCompressed() ) { // As of today, when the user chooses the compress the picture, // the package is provided in two flavors, in two distinct directories. // Later, only the compressed version will be provided. Thus, the following code // handles both scenarios. if ( is_dir( $extractedPath . DIRECTORY_SEPARATOR . 'compressed' ) ) { $this->params[RFG_FAVICON_COMPRESSED_PACKAGE_PATH] = $extractedPath . DIRECTORY_SEPARATOR . 'compressed'; } else { $this->params[RFG_FAVICON_COMPRESSED_PACKAGE_PATH] = $extractedPath; } if ( is_dir( $extractedPath . DIRECTORY_SEPARATOR . 'uncompressed' ) ) { $this->params[RFG_FAVICON_UNCOMPRESSED_PACKAGE_PATH] = $extractedPath . DIRECTORY_SEPARATOR . 'uncompressed'; } else { $this->params[RFG_FAVICON_UNCOMPRESSED_PACKAGE_PATH] = $extractedPath; } $this->params[RFG_FAVICON_PRODUCTION_PACKAGE_PATH] = $this->params[RFG_FAVICON_COMPRESSED_PACKAGE_PATH]; } else { $this->params[RFG_FAVICON_COMPRESSED_PACKAGE_PATH] = NULL; $this->params[RFG_FAVICON_UNCOMPRESSED_PACKAGE_PATH] = $extractedPath; $this->params[RFG_FAVICON_PRODUCTION_PACKAGE_PATH] = $this->params[RFG_FAVICON_UNCOMPRESSED_PACKAGE_PATH]; } } /** * Directory where the compressed files are stored. Method downloadAndUnpack must be called first in order to populate this field. * Can be NULL. */ public function getCompressedPackagePath() { return $this->params[RFG_FAVICON_COMPRESSED_PACKAGE_PATH]; } /** * Directory where the uncompressed files are stored. Method downloadAndUnpack must be called first in order to populate this field. * Can be NULL. */ public function getUncompressedPackagePath() { return $this->params[RFG_FAVICON_UNCOMPRESSED_PACKAGE_PATH]; } /** * Directory where the production favicon files are stored. * These are the files to deployed to the targeted web site. When the user asked for compression, * this is the path to the compressed folder. Else, this is the path to the regular files folder. * Method downloadAndUnpack must be called first in order to populate this field. */ public function getProductionPackagePath() { return $this->params[RFG_FAVICON_PRODUCTION_PACKAGE_PATH]; } /** * Path to the preview picture. */ public function getPreviewPath() { return $this->params[RFG_PREVIEW_PATH]; } private function downloadFile( $localPath, $url ) { $resp = wp_remote_get( $url, array( 'filename' => $localPath, 'stream' => true ) ); if ( ( $resp == NULL ) || ( $resp == false ) || ( is_wp_error( $resp ) ) || ( $resp['response'] == NULL ) || ( $resp['response']['code'] == NULL ) || ( $resp['response']['code'] != 200 ) ) { $explanation = is_wp_error( $resp ) ? ( ': ' . $resp->get_error_message() ) : '' ; throw new InvalidArgumentException( sprintf( __( 'Cannot download file at %s', Favicon_By_RealFaviconGenerator_Common::PLUGIN_SLUG ), $url ) . $explanation ); } if ( ( ! file_exists( $localPath ) ) || ( filesize( $localPath ) <= 0 ) ) { throw new InvalidArgumentException( __( 'Cannot store downloaded file locally', Favicon_By_RealFaviconGenerator_Common::PLUGIN_SLUG ) ); } } public function append_directory_separator( $filename ) { return $filename . ( ( $this->ends_with( $filename, DIRECTORY_SEPARATOR )) ? '' : DIRECTORY_SEPARATOR ); } // See http://stackoverflow.com/questions/834303/startswith-and-endswith-functions-in-php#answer-10473026 public function ends_with( $haystack, $needle ) { return $needle === "" || ( ( $temp = strlen( $haystack ) - strlen( $needle ) ) >= 0 && strpos( $haystack, $needle, $temp ) !== false ); } }