/**
  * Updates all add-ons.
  *
  * @param Boolean Clear existing addons before updating them.
  * Will also clear their search index, and cascade the delete for associated data.
  * @param Array Limit to specific addons, using their name incl. vendor prefix.
  */
 public function update($clear = false, $limitAddons = null)
 {
     if ($clear && !$limitAddons) {
         Addon::get()->removeAll();
         AddonAuthor::get()->removeAll();
         AddonKeyword::get()->removeAll();
         AddonLink::get()->removeAll();
         AddonVendor::get()->removeAll();
         AddonVersion::get()->removeAll();
     }
     foreach (SilverStripeVersion::get() as $version) {
         $this->silverstripes[$version->ID] = $version->getConstraint();
     }
     // This call to packagist can be expensive. Requests are served from a cache if usePackagistCache() returns true
     $cache = SS_Cache::factory('addons');
     if ($this->usePackagistCache() && ($packages = $cache->load('packagist'))) {
         $packages = unserialize($packages);
     } else {
         $packages = $this->packagist->getPackages();
         $cache->save(serialize($packages), 'packagist');
     }
     $this->elastica->startBulkIndex();
     foreach ($packages as $package) {
         $name = $package->getName();
         $versions = $package->getVersions();
         if ($limitAddons && !in_array($name, $limitAddons)) {
             continue;
         }
         $addon = Addon::get()->filter('Name', $name)->first();
         if (!$addon) {
             $addon = new Addon();
             $addon->Name = $name;
             $addon->write();
         }
         usort($versions, function ($a, $b) {
             return version_compare($a->getVersionNormalized(), $b->getVersionNormalized());
         });
         $this->updateAddon($addon, $package, $versions);
     }
     $this->elastica->endBulkIndex();
 }