Example #1
0
 /**
  * Installs a packagist package
  *
  * @param string $package_name
  * @param string|boolean $version_param
  * @param boolean-
  *
  * @return boolean
  */
 public static function install($package_name, $version_param = false, $die_on_duplicate = true)
 {
     $package_info = json_decode(file_get_contents(self::URL . "/{$package_name}.json"), true);
     if (!isset($package_info['status'])) {
         //has package already been added to the app's packagist file
         $exists = isset(self::$_packages[$package_name]) ? self::$_packages[$package_name] : false;
         //check for matching version either new or existing ugradable
         $to_install = self::match($package_info, $version_param);
         if ($to_install === false && $exists !== true && $exists !== false) {
             $to_install = self::match($package_info, $exists);
         }
         if ($to_install !== false) {
             echo "Downloading {$package_name} " . $to_install["version"] . "\n";
             //download requires
             if (isset($to_install["require"])) {
                 foreach ($to_install["require"] as $rpackage => $version) {
                     if ($rpackage == "php") {
                         $php_vmatch = [];
                         preg_match('/([\\>\\=]+)\\s*([0-9\\.]+)/', $version, $php_vmatch);
                         if (version_compare(phpversion(), $php_vmatch[2], $php_vmatch[1]) == false) {
                             die("PHP version {$version} required");
                         }
                     } elseif (strpos($rpackage, '/') !== false) {
                         self::install($rpackage, $version, false);
                     }
                 }
             }
             //get directory names and create if not existing yet
             $name = $to_install["source"]["url"];
             $name = substr($name, strlen('https://github.com/'));
             $name = str_replace('/', '-', substr($name, 0, strrpos($name, '.')));
             $id = substr($to_install["dist"]["reference"], 0, 7);
             $package_directory = App::libs()->directory('Packagist.' . strtolower($name));
             $package_sub = $package_directory->directory("{$name}-{$id}");
             if ($package_sub->exists()) {
                 if ($die_on_duplicate) {
                     die("Package version already installed\n");
                 } else {
                     echo "Package version already installed\n";
                     return false;
                 }
             }
             if (!$package_directory->exists()) {
                 $package_directory->create();
             }
             //download file
             $package_zip = (string) FileHandler::system('package.zip');
             $fp = fopen($package_zip, 'w');
             $ch = curl_init($to_install["dist"]["url"]);
             curl_setopt($ch, CURLOPT_TIMEOUT, 50);
             curl_setopt($ch, CURLOPT_FILE, $fp);
             curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
             curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
             curl_exec($ch);
             curl_close($ch);
             fclose($fp);
             //extract package.zip
             $zip = new \ZipArchive();
             $zip->open($package_zip);
             $zip->extractTo($package_directory);
             //remove zip
             unlink($package_zip);
             //add .exclude file
             $package_sub->file(".exclude")->write('');
             //get existing installed version
             $prev_versions = $package_directory->directories();
             //remove any existing key from autoload
             $prev_version_found = false;
             foreach ($prev_versions as $prev_version) {
                 $prev_version_name = $prev_version->name();
                 if ($prev_version_name !== "{$name}-{$id}" && isset(self::$_autoload[$prev_version_name])) {
                     $prev_version_found = $prev_version_name;
                     unset(self::$_autoload[$prev_version_name]);
                 }
             }
             //let the user know the previous version has been removed from autoload
             if ($prev_version_found !== false) {
                 echo "A previously installed version was detected and removed from the autoload.json in favor of the new version. The package files still exist in Libs/Packagist/{$name}/{$prev_version_found}\n";
             }
             //add autoload
             $classmap = [];
             if (isset($to_install['autoload'])) {
                 // go through autoload
                 foreach ($to_install['autoload'] as $spec => $mapping) {
                     if ($spec == 'classmap') {
                         // loop through the files and fetch the fully qualified classnames
                         // through regex
                         foreach ($mapping as $file) {
                             // can also be directory
                             $d = $package_sub->directory($file);
                             $f = $package_sub->file($file, substr_count($file, '.'));
                             if ($d->exists()) {
                                 // look up files inside directory
                                 $d_files = $d->files(true);
                                 foreach ($d_files as $d_f) {
                                     $classes = $d_f->classes();
                                     foreach ($classes as $class) {
                                         $source = substr("{$d_f}", strlen("{$d}") + 1);
                                         $classmap[$class] = "{$file}/{$source}";
                                     }
                                 }
                             } else {
                                 $classes = $f->classes();
                                 foreach ($classes as $class) {
                                     $classmap[$class] = $file;
                                 }
                             }
                         }
                     } else {
                         if ($spec == 'files') {
                             if (!isset($classmap['files'])) {
                                 $classmap['files'] = [];
                             }
                             foreach ($mapping as $file) {
                                 $classmap['files'][] = $file;
                             }
                         } else {
                             // psr -> go through mapping
                             foreach ($mapping as $prefix => $source) {
                                 // get all files in source
                                 $directory = $package_sub->directory($source);
                                 $files = $directory->files(true);
                                 // loop through files and add to class mapping
                                 foreach ($files as $file) {
                                     $classes = $file->classes();
                                     foreach ($classes as $class) {
                                         $classmap[$class] = $source . substr($file, strlen($directory));
                                     }
                                 }
                             }
                         }
                     }
                 }
                 self::$_autoload["{$name}-{$id}"] = $classmap;
             }
             self::$_packages[$package_name] = '^' . trim($to_install["version"], 'v');
             self::save();
             return true;
         }
     }
     return false;
 }