/**
  * 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();
 }
 public function Addons()
 {
     $list = Addon::get();
     $search = $this->request->getVar('search');
     $type = $this->request->getVar('type');
     $compat = $this->request->getVar('compatibility');
     $tags = $this->request->getVar('tags');
     $sort = $this->request->getVar('sort');
     $view = $this->request->getVar('view');
     if (!$view) {
         $view = 'list';
     }
     if (!in_array($sort, array('name', 'downloads', 'newest'))) {
         $sort = null;
     }
     // Proxy out a search to elastic if any parameters are set.
     if ($search || $type || $compat || $tags) {
         $filter = new BoolAnd();
         $query = new Query();
         $query->setSize(count($list));
         if ($search) {
             $match = new Match();
             $match->setField('_all', $search);
             $query->setQuery($match);
         }
         if ($type) {
             $filter->addFilter(new Term(array('type' => $type)));
         }
         if ($compat) {
             $filter->addFilter(new Terms('compatible', (array) $compat));
         }
         if ($tags) {
             $filter->addFilter(new Terms('tag', (array) $tags));
         }
         if ($type || $compat || $tags) {
             $query->setFilter($filter);
         }
         $list = new ResultList($this->elastica->getIndex(), $query);
         if ($sort) {
             $ids = $list->column('ID');
             if ($ids) {
                 $list = Addon::get()->byIDs($ids);
             } else {
                 $list = new ArrayList();
             }
         }
     } else {
         if (!$sort) {
             $sort = 'downloads';
         }
     }
     switch ($sort) {
         case 'name':
             $list = $list->sort('Name');
             break;
         case 'newest':
             $list = $list->sort('Released', 'DESC');
             break;
         case 'downloads':
             $list = $list->sort('Downloads', 'DESC');
             break;
     }
     $list = new PaginatedList($list, $this->request);
     $list->setPageLength(16);
     return $list;
 }