diff options
Diffstat (limited to 'site/app/controllers/addons_controller.php')
-rw-r--r-- | site/app/controllers/addons_controller.php | 788 |
1 files changed, 270 insertions, 518 deletions
diff --git a/site/app/controllers/addons_controller.php b/site/app/controllers/addons_controller.php index 5d7e1a3..385d231 100644 --- a/site/app/controllers/addons_controller.php +++ b/site/app/controllers/addons_controller.php @@ -46,10 +46,10 @@ class AddonsController extends AppController { var $name = 'Addons'; - var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox', 'checkAdvancedSearch'); - var $uses = array('Addon', 'AddonCollection', 'AddonTag', 'Addontype', 'Application', - 'Feature', 'File', 'GlobalStat', 'License', 'Platform', 'Preview', 'Tag', 'Translation', - 'Review', 'Version', 'Collection', 'CollectionPromo'); + var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox'); + var $uses = array('Addon', 'AddonTag', 'Addontype', 'Application', + 'Feature', 'File', 'Platform', 'Preview', 'Tag', 'Translation', + 'Review', 'Version'); var $components = array('Amo', 'Image', 'Pagination', 'Session', 'Userfunc'); var $helpers = array('Html', 'Link', 'Time', 'Localization', 'Ajax', 'Number', 'Pagination'); var $namedArgs = true; @@ -67,13 +67,13 @@ class AddonsController extends AppController redirectWithNewLocaleAndExit(array('addon',$this->params['url']['addons-author-addons-select'])); } - // Set of available link sharing services with associated labels and + // Set of available link sharing services with associated labels and // submission URL templates. // @TODO: Move this to a model class when share counts are enabled in DB - $this->link_sharing_services = array( + $this->link_sharing_services = array( // see: http://digg.com/tools/integrate#3 - 'digg' => array( + 'digg' => array( 'label' => ___('addons_share_label_digg', 'Digg this!'), 'url' => 'http://digg.com/submit?url={URL}&title={TITLE}&bodytext={DESCRIPTION}&media=news&topic=tech_news' ), @@ -112,14 +112,15 @@ class AddonsController extends AppController */ function share($id = null) { global $valid_status; - + global $app_listedtypes; + $_conditions = array( 'Addon.id' => $id, 'Addon.inactive' => 0, - 'Addon.addontype_id' => array( - ADDON_EXTENSION, ADDON_THEME, ADDON_DICT, + 'Addon.addontype_id' => array_merge(array( + ADDON_EXTENSION, ADDON_THEME, ADDON_DICT, ADDON_SEARCH, ADDON_LPAPP, ADDON_PLUGIN - ), + ), $app_listedtypes[APP_SUGAR]), 'Addon.status' => $valid_status ); $addon = $this->Addon->find($_conditions, null , null , 1); @@ -134,17 +135,17 @@ class AddonsController extends AppController $this->publish('addon_id', $id); - // Build a suitable link title based on the addon name, version, and + // Build a suitable link title based on the addon name, version, and // the site title. - $title = + $title = sprintf( - _('addons_display_pagetitle'), + _('addons_display_pagetitle'), $addon['Translation']['name']['string'].' '. $addon['Version'][0]['version'] - ) . + ) . ' :: '. sprintf( - _('addons_home_pagetitle'), + _('addons_home_pagetitle'), APP_PRETTYNAME ); @@ -157,24 +158,21 @@ class AddonsController extends AppController $this->layout = 'ajax'; } - + /** * Display an addon * @param int $id the id of the addon */ function display($id = null) { global $valid_status; - $this->publish('jsAdd', array('jquery-ui/ui.lightbox')); - $this->publish('cssAdd', array('jquery-lightbox')); - $this->layout = 'amo2009'; - $this->set('bodyclass', 'inverse'); - - $this->forceShadowDb(); + $this->Amo->clean($id); $this->publish('bigHeader', true); $this->publish('bigHeaderText', sprintf(_('addons_home_header_details'), APP_PRETTYNAME)); - + + $this->layout='mozilla'; + $loggedIn = $this->Session->check('User')? true : false; $this->set('loggedIn', $loggedIn); @@ -182,7 +180,7 @@ class AddonsController extends AppController $this->flash(sprintf(_('error_missing_argument'), 'addon_id'), '/', 3); return; } - + $_conditions = array( 'Addon.id' => $id, 'Addon.inactive' => 0, @@ -190,58 +188,23 @@ class AddonsController extends AppController 'Addon.status' => $valid_status ); - $this->Addon->bindOnly('User', 'Version', 'Tag', 'AddonTag'); - $addon_data = $this->Addon->find($_conditions, null , null , 1); + global $app_listedtypes; + $_conditions['Addon.addontype_id'] = array_merge($_conditions['Addon.addontype_id'], $app_listedtypes[APP_SUGAR]); + $addon_data = $this->Addon->find($_conditions, null , null , 1); + if (empty($addon_data)) { $this->flash(_('error_addon_notfound'), '/', 3); return; } - // sandbox check - if ($addon_data['Addon']['status'] != STATUS_PUBLIC) { - $this->publish('addonStatus', STATUS_SANDBOX); - $this->status = $valid_status; - } - - $_latest_version = $this->Version->getVersionByAddonId($addon_data['Addon']['id'], $this->status); - if ($_latest_version > 0) { - $version = $this->Version->findAllById($_latest_version, null, "Version.created DESC", 0); - $addon_data['Version'] = $version; - $this->publish('hasversion', true); - $compat_apps = $this->Version->getCompatibleApps($_latest_version); - $this->publish('compatible_apps', array_slice($compat_apps, 0, 1)); - $addon_data['compatible_apps'] = $compat_apps; - } else { - $this->publish('hasversion', false); - $this->publish('compatible_apps', array()); - } - - // if the latest version is incompatible with the current app, redirect - // to a the first valid, compatible version. - if (!empty($compat_apps)) { - $is_compatible = false; - foreach ($compat_apps as $app) { - if ($app['Application']['application_id'] == APP_ID) { - $is_compatible = true; - break; - } - } - if (!$is_compatible) { - global $app_shortnames; - $targetapp = array_search($compat_apps[0]['Application']['application_id'], $app_shortnames); - $this->redirect("/{$targetapp}/addon/{$id}", null, true, false); - return; - } - } - // TODO: Look up the current share totals for this addon. // $share_counts = $this->ShareCount->getTotalCountsForAddon( // $addon_data['Addon']['id'] // ); // $this->set('link_sharing_counts', $share_counts); - // Not using publish() here because this will all be app constants, + // Not using publish() here because this will all be app constants, // localized strings with placeholders, or counts from the DB. $this->set('link_sharing_services', $this->link_sharing_services); @@ -252,7 +215,7 @@ class AddonsController extends AppController else { $this->publish('isAuthor', false); } - + // get other addons for the author(s) foreach ($addon_data['User'] as $_user) $_userids[] = $_user['id']; @@ -274,6 +237,24 @@ class AddonsController extends AppController if (in_array($addon_data['Addon']['addontype_id'], array(ADDON_PLUGIN))) { $this->redirect('/browse/type:' . $addon_data['Addon']['addontype_id']); } + + // sandbox check + if ($addon_data['Addon']['status'] != STATUS_PUBLIC) { + $this->publish('addonStatus', STATUS_SANDBOX); + $this->status = $valid_status; + } + + $_latest_version = $this->Version->getVersionByAddonId($addon_data['Addon']['id'], $this->status); + if ($_latest_version > 0) { + $version = $this->Version->findAllById($_latest_version, null, "Version.created DESC", 0); + $addon_data['Version'] = $version; + $this->publish('hasversion', true); + $compat_apps = $this->Version->getCompatibleApps($_latest_version); + $this->publish('compatible_apps', array_slice($compat_apps, 0, 1)); + } else { + $this->publish('hasversion', false); + $this->publish('compatible_apps', array()); + } $this->publish('previews', $this->Preview->findAllByAddonId($id, array('id', 'addon_id', 'caption'), 'highlight desc')); @@ -281,7 +262,7 @@ class AddonsController extends AppController $this->publish('addonIconPath', $this->Image->getAddonIconURL($id), false); $this->publish('addonPreviewPath', $this->Image->getHighlightedPreviewURL($id)); $this->pageTitle = sprintf(_('addons_display_pagetitle'), $addon_data['Translation']['name']['string']). ' :: '.sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME); - + // get the tags that are related to the addon, so that they have translation data $_related_tag_ids = array(); foreach ($addon_data['Tag'] as $tagvalue){ @@ -300,12 +281,12 @@ class AddonsController extends AppController $this->Platform->unbindFully(); $platforms = $this->Platform->findAll(); $this->publish('platforms', $platforms); - + // Grab the latest 3 reviews by ID, one per user. $review_ids = array(); - $_latest_reviews = + $_latest_reviews = $this->Review->findLatestReviewsForAddon($addon_data['Addon']['id'], 3, 1); - foreach($_latest_reviews as $_r) + foreach($_latest_reviews as $_r) $review_ids[] = $_r['id']; // Fetch the actual reviews from IDs @@ -315,8 +296,9 @@ class AddonsController extends AppController $reviews = array(); $this->publish('reviews', $reviews); - $this->publish('review_count', empty($reviews) ? 0 : $addon_data['Addon']['totalreviews']); - + $this->publish('review_count', empty($reviews) ? + 0 : $this->Review->countLatestReviewsForAddon($addon_data['Addon']['id'])); + // does user have a review already? $user = $this->Session->read('User'); if (!empty($user) && $_latest_version > 0) { @@ -325,253 +307,83 @@ class AddonsController extends AppController } else { $this->publish('hasreview', false); } - - // find collections this add-on is in - $pop_collections = array(); - $_pop_coll_ids = $this->AddonCollection->getPopularCollectionsForAddon($id, 3, APP_ID); - if (!empty($_pop_coll_ids)) { - $pop_collections = $this->Collection->findAllById($_pop_coll_ids, - array('id', 'uuid', 'nickname', 'name'), - 'FIELD(Collection.id,'.implode(',', $_pop_coll_ids).')', null, null, -1); - } - $this->publish('pop_collections', $pop_collections); - $collection_count = $this->AddonCollection->getCollectionCountForAddon($id, APP_ID); - $this->publish('collection_count', $collection_count, false); - - // Fetch user's collections if logged in - $userCollections = false; - if (!empty($user)) { - $userCollectionIds = $this->User->getCollections($user['id'], APP_ID, array($id)); - $userCollections = $this->Collection->findAll(array( - 'Collection.id' => $userCollectionIds, - 'Collection.collection_type' => '<> '.Collection::COLLECTION_TYPE_AUTOPUBLISHER - ), array('id', 'name', 'uuid', 'nickname')); - $this->publish('userCollections', $userCollections); - - // if an addon was just added to a collection, display a success message - if (false !== ($coll_uuid = $this->Session->read('collection_addon_added'))) { - $collection_id = $this->Collection->getIdForUUID($coll_uuid); - $coll_addon_added = $this->Collection->findById($collection_id, null, null, -1); - $this->Session->delete('collection_addon_added'); - $this->publish('coll_addon_added', $coll_addon_added); - } - } - + // Collapse categories menu $this->publish('collapse_categories', true); } - + + /** * Display the home page for the entire site. */ function home() { $this->forceShadowDb(); - - $this->layout='amo2009'; + global $valid_status, $app_listedtypes; + + $this->layout='mozilla'; $this->pageTitle = sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME); - - $this->publish('stats_downloaded', - $this->GlobalStat->getNamedCount('addons_downloaded')); - $this->publish('stats_inuse', - $this->GlobalStat->getNamedCount('addons_in_use')); - - $this->publish('teaser_collection_promos', $this->_findTeaserCollections()); - $this->publish('teaser_collections_categories', $this->CollectionPromo->titles_and_taglines); - $this->publish('popular_collections', $this->_findPopularCollections()); - $this->publish('promoted_collections', $this->_findCollectionPromoList(true)); - - list($featured_type, $featured_addons) = $this->_getFeatured(); - $this->publish('featured_type', $featured_type); - $this->publish('featured_addons', $featured_addons); - + + $feature_ids = $this->Addon->getRecommendedAddons(7); + $featureAddons = $this->Addon->getAddonList($feature_ids, array( + 'all_tags', 'authors', 'compatible_apps', 'files', 'latest_version', + 'list_details')); + $this->publish('featureAddons', $featureAddons); + unset($feature_ids, $featureAddons); + + // Get recommended and popular lists. + $list_num = 4; + $associations = array('single_tag'); + + $rec_addon_ids = $this->Addon->getRecommendedAddons($list_num); + $rec_addons = $this->Addon->getAddonList($rec_addon_ids, $associations); + $pop_addon_ids = $this->Addon->getAddonsFromCategory(STATUS_PUBLIC, + $app_listedtypes[APP_ID], 'all', 'popular', 'DESC', $list_num, 1, '', false); + $pop_addons = $this->Addon->getAddonList($pop_addon_ids, $associations); + $new_addon_ids = $this->Addon->getAddonsFromCategory(STATUS_PUBLIC, + $app_listedtypes[APP_ID], 'all', 'newest', 'DESC', $list_num, 1, '', false); + $new_addons = $this->Addon->getAddonList($new_addon_ids, $associations); + $upd_addon_ids = $this->Addon->getAddonsFromCategory(STATUS_PUBLIC, + $app_listedtypes[APP_ID], 'all', 'updated', 'DESC', $list_num, 1, '', false); + $upd_addons = $this->Addon->getAddonList($upd_addon_ids, $associations); + unset($list_num, $rec_addon_ids, $pop_addon_ids, $new_addon_ids, $upd_addon_ids); + + $this->publish('recAddons', $rec_addons); + $this->publish('popAddons', $pop_addons); + $this->publish('newAddons', $new_addons); + $this->publish('updAddons', $upd_addons); + // The platforms section is necessary because of CakePHP bug #1183 // (https://trac.cakephp.org/ticket/1183). We need the translated // strings in the model to offer the right platform to users. $this->Platform->unbindFully(); $platforms = $this->Platform->findAll(); $this->publish('platforms', $platforms); - + $this->publish('baseurl', $this->base); $this->publish('bigHeader', true); $this->publish('bigHeaderText', sprintf(_('addons_home_header_details'), APP_PRETTYNAME)); - + // add rss links to global feeds + // @partial translation fallback, 5/13/08 $this->publish('rssAdd', array( array('/browse/type:1/cat:all/format:rss?sort=newest', _('rss_newestaddons')), array('/browse/type:1/cat:all/format:rss?sort=updated', ___('rss_updatedaddons', 'Updated Add-ons')), - array('/browse/type:1/cat:all/format:rss?sort=popular', ___('rss_popularaddons', 'Popular Add-ons')), array('/recommended/format:rss', _('rss_featuredaddons')), - )); - } - - /* Used to populate the homepage addons by xhr. */ - function ajaxy() { - list($featured_type, $featured_addons) = $this->_getFeatured(); - $this->publish('featured_type', $featured_type); - $this->publish('featured_addons', $featured_addons); - $this->Platform->unbindFully(); - $platforms = $this->Platform->findAll(); - $this->publish('platforms', $platforms); - } - - function _getFeatured() { - global $app_listedtypes; - - $associations = array( - 'single_tag', 'all_tags', 'authors', 'compatible_apps', 'files', - 'latest_version', 'list_details' - ); - $list_num = 5; - - $featured_type = isset($_GET['featured']) ? - $_GET['featured'] : 'recommended'; - switch ($featured_type) { - case 'popular': - $featured_addon_ids = $this->Addon->getAddonsFromCategory( - STATUS_PUBLIC, $app_listedtypes[APP_ID], 'all', 'popular', - 'DESC', $list_num, 1, '', false - ); - break; - case 'added': - $featured_addon_ids = $this->Addon->getAddonsFromCategory( - STATUS_PUBLIC, $app_listedtypes[APP_ID], 'all', 'newest', - 'DESC', $list_num, 1, '', false - ); - break; - case 'updated': - $featured_addon_ids = $this->Addon->getAddonsFromCategory( - STATUS_PUBLIC, $app_listedtypes[APP_ID], 'all', 'updated', - 'DESC', $list_num, 1, '', false - ); - break; - case 'recommended': - default: - $featured_addon_ids = $this->Addon->getRecommendedAddons($list_num); - break; - } - $featured_addons = $this->Addon->getAddonList($featured_addon_ids, $associations); - - return array($featured_type, $featured_addons); - } - - /** - * Assemble collections for the teaser section of the home page. - * - * @return array - */ - function _findTeaserCollections() { - - if (APP_ID != APP_FIREFOX) { - - // FYF collections for teaser are only appropriate for Firefox. - return array(); - - } else { - $promoCatList = $this->_findCollectionPromoList(); - $teaser_collections = array(); - - $associations = array( - 'single_tag', 'all_tags', 'authors', 'compatible_apps', 'files', - 'latest_version', 'list_details' - ); - - foreach($promoCatList as $index => $collectionId) { - $addons = $this->Addon->getAddonsFromCollection($collectionId, 'RAND()', null, 3); - $teaser_collections[] = $this->Addon->getAddonList($addons, $associations); - } - - return $teaser_collections; - } - - } - - /** - * Assemble list of collections promoted per promotion category - * - * @return array - **/ - function _findCollectionPromoList($bindFully = false) { - $collectionPromos = $this->CollectionPromo->findAll(); - $promoCats = $this->CollectionPromo->titles_and_taglines; - $promoCatList = array(); - - //Doing this to merge collection ids into promotion categories and allow locale-specific selections to override - for($i = 0; $i < count($promoCats); $i++) { - $collection = false; - - if(isset($collectionPromos[LANG][$i])) { - $collection = $collectionPromos[LANG][$i]; - } elseif(isset($collectionPromos['all'][$i])) { - $collection = $collectionPromos['all'][$i]; - } - - if($collection) { - $id = array_keys($collection); - $id = $id[0]; - - if($bindFully) { - $promoCatList[] = $this->Collection->findById($id); - } else { - $promoCatList[] = $id; - } - } - } - - return $promoCatList; - } - - - - - - /** - * Fetch top 5 popular collections by subscriber count, return a - * stripped-down data structure for use by view. - * - * @return array - */ - function _findPopularCollections() { - - // Unbind and re-bind with just users and addons, then look up top 5 - // popular collections in descending order. - $this->Collection->unbindFully(); - $this->Collection->bindModel(array( - 'hasAndBelongsToMany' => array( - 'Users' => $this->Collection->hasAndBelongsToMany_full['Users'], - 'Addon' => $this->Collection->hasAndBelongsToMany_full['Addon'] - ) - )); - $collections = $this->Collection->findAll(array( - 'Collection.listed' => 1, - 'Collection.application_id' => APP_ID - ), null, 'Collection.subscribers DESC', 5); - - // Reduce the results from the model to the minimal set needed - // by the view, because escaping is expensive. - $pop_collections = array(); - foreach ($collections as $c) { - $authors = array(); - foreach ($c['Users'] as $u) { - $authors[] = array( - 'id' => $u['id'], - 'firstname' => $u['firstname'], - 'lastname' => $u['lastname'], - 'nickname' => $u['nickname'] - ); - } - $pop_collections[] = array( - 'uuid' => $c['Collection']['uuid'], - 'nickname' => $c['Collection']['nickname'], - 'authors' => $authors, - 'icon_url' => $this->Image->getCollectionIconURL($c['Collection']['id']), - 'name' => $c['Translation']['name']['string'], - 'description' => $c['Translation']['description']['string'], - 'subscribers' => $c['Collection']['subscribers'], - 'addons_count' => count($c['Addon']) - ); + )); + + // User name for Welcome message + if ($session = $this->Session->read('User')) { + if (!empty($session['firstname'])) + $welcomeName = $session['firstname']; + elseif (!empty($session['nickname'])) + $welcomeName = $session['nickname']; + elseif (!empty($session['lastname'])) + $welcomeName = $session['lastname']; + else + $welcomeName = ''; + + $this->publish('welcomeName', $welcomeName); } - - return $pop_collections; } /** @@ -581,7 +393,7 @@ class AddonsController extends AppController global $valid_status; // Get the type of addon, defaulting to themes - $addontype = isset($this->namedArgs['type']) ? + $addontype = isset($this->namedArgs['type']) ? $this->namedArgs['type'] : ADDON_THEME; // Get the addon category, defaulting to 'all' @@ -590,7 +402,7 @@ class AddonsController extends AppController $this->Tag->unbindFully(); $this_tag = $this->Tag->findById($category); - + // show experimental add-ons? if (isset($this->params['url']['exp'])) { /* experimental add-ons requested */ @@ -629,7 +441,7 @@ class AddonsController extends AppController $sort_by = $this->namedArgs['sort']; else $sort_by = ''; - + $allowed_sort_by = array( 'name', 'updated', 'newest', 'popular', 'rated' ); @@ -657,7 +469,7 @@ class AddonsController extends AppController list($_order,$_limit,$_page) = $this->Pagination->init(); $addons = $this->Addon->getAddonsByCategory( - null, $displaystatuses, $addontype, $category, + null, $displaystatuses, $addontype, $category, $sort_by, $sort_dir, $_limit, $_page, '', true ); @@ -670,16 +482,16 @@ class AddonsController extends AppController $this->publish('subcats', $subcats); $this->publish('all_total', $all_total); $this->publish('subcat_totals', $subcat_totals); - + $format = (isset($this->namedArgs['format']) ? $this->namedArgs['format'] : 'html'); - + $this->set('content_wide', true); // display 2 features next to each other - + $this->publish('collapse_categories', true); - + switch($addontype) { - case ADDON_THEME: - $this->pageTitle = sprintf(___('addons_browse_categories_header_theme'), $this_tag['Translation']['name']['string'], APP_PRETTYNAME); + case ADDON_THEME: + $this->pageTitle = sprintf(___('addons_browse_categories_header_theme'), $this_tag['Translation']['name']['string'], APP_PRETTYNAME); break; default: $this->pageTitle = sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME); @@ -687,7 +499,7 @@ class AddonsController extends AppController $this->publish('bigHeader', true); $this->publish('bigHeaderText', sprintf(_('addons_home_header_details'), APP_PRETTYNAME)); - + $this->layout = 'mozilla'; $this->render('browse_thumbs'); @@ -698,8 +510,7 @@ class AddonsController extends AppController */ function browse() { global $app_listedtypes, $hybrid_categories; - - $this->forceShadowDb(); + if (!isset($this->namedArgs['type'])) { // @TODO throw a 404 error $this->redirect('/'); @@ -717,7 +528,7 @@ class AddonsController extends AppController $this->redirect('/'); break; } - + if (!isset($this->namedArgs['cat'])) { switch ($this->namedArgs['type']) { case ADDON_SEARCH: @@ -729,7 +540,7 @@ class AddonsController extends AppController case ADDON_PLUGIN: // undeleted this -cpollett $this->_plugins(); break; - + case ADDON_DICT: $this->_dictionaries(); break; @@ -743,7 +554,7 @@ class AddonsController extends AppController } return; } - + /* redirect category hybrids to respective addontype page * (unless we have selected a full listing page (?sort=something)) */ $cat = $this->namedArgs['cat']; @@ -752,7 +563,7 @@ class AddonsController extends AppController $this->redirect("/browse/type:{$hybrid_categories[APP_ID][$cat]}"); return; } - + /* display generic cat landing page or full category listing page */ if (isset($_GET['sort']) || isset($this->namedArgs['sort'])) { @@ -769,47 +580,6 @@ class AddonsController extends AppController } } - function _buildMinimalAddonDetails($addons) { - $view_data = array(); - - foreach ($addons as $addon) { - $addon_id = $addon['Addon']['id']; - - $r = array( - 'icon_url' => - $this->Image->getAddonIconURL($addon_id), - 'preview_url' => - $this->Image->getHighlightedPreviewURL($addon_id), - 'version' => - $addon['Version'][0]['version'] - ); - - $a_fields = array( - 'id','guid','averagerating','created','modified', - 'weeklydownloads','totaldownloads' - ); - foreach ($a_fields as $field) - $r[$field] = $addon['Addon'][$field]; - - $t_fields = array('name','summary','description'); - foreach ($t_fields as $field) - $r[$field] = $addon['Translation'][$field]['string']; - - $u_fields = array('id', 'firstname', 'lastname', 'nickname'); - $r['authors'] = array(); - if (!empty($addon['User'])) foreach ($addon['User'] as $idx=>$user) { - foreach ($u_fields as $field) - $r['authors'][$idx][$field] = $user[$field]; - } - - $r['latestversion'] = $addon['Version'][0]['version']; - - $view_data[] = $r; - } - - return $view_data; - } - /** * Generic landing page for a specific add-on category * @@ -818,85 +588,61 @@ class AddonsController extends AppController * @access private */ function _categoryLanding() { - global $valid_status, $app_listedtypes; - + global $valid_status; + $valid_status = array(STATUS_PUBLIC); $format = $this->setLayoutForFormat(); - + $addontype = $this->namedArgs['type']; $this->Amo->clean($addontype); - $this->publish('type_id', $addontype); - + $category = $this->namedArgs['cat']; $this->Amo->clean($category); - $this->publish('cat_id', $category); - $this->Tag->unbindFully(); $this_tag = $this->Tag->findById($category); - $this->publish('this_tag', $this_tag); - - // Build a minimal set of addon details for publishing to view. - $_feat_ids = $this->AddonTag->getRandomAddons($category, true, 6, null, $addontype=='all' ? null : $addontype); - if (count($_feat_ids) > 0) { - $_order_by = 'FIELD(Addon.id, '.implode(',', $_feat_ids).')'; + + // fetch 5 recommended add-ons for slider + $_feat_ids = $this->AddonTag->getRandomAddons($category, true, 5, null, $addontype=='all' ? null : $addontype); + if (!empty($_feat_ids)) { + $featureAddons = $this->Addon->getListAddons($_feat_ids, $valid_status, + 'FIELD(Addon.id,'.implode(',', $_feat_ids).')', true); } else { - $_order_by = 'Addon.id'; + $featureAddons = false; } - $featureAddons = $this->Addon->getListAddons($_feat_ids, $valid_status, $_order_by, true); - - $this->publish('featured_addons', $featureAddons); - - $list_num = 10; - - $pop_addon_ids = $this->Addon->getAddonsFromCategory( - STATUS_PUBLIC, $app_listedtypes[APP_ID], $category, - 'popular', 'DESC', $list_num, 1, '', false - ); - $pop_addons = $this->_buildMinimalAddonDetails( - $this->Addon->getListAddons($pop_addon_ids, $valid_status, 'Addon.weeklydownloads DESC') - ); - - $this->publish('popular_addons', $pop_addons); - - $new_addon_ids = $this->Addon->getAddonsFromCategory( - STATUS_PUBLIC, $app_listedtypes[APP_ID], $category, 'newest', - 'DESC', $list_num, 1, '', false - ); - $new_addons = $this->_buildMinimalAddonDetails( - $this->Addon->getListAddons($new_addon_ids, $valid_status, 'Addon.created DESC') - ); - - $this->publish('new_addons', $new_addons); - - $upd_addon_ids = $this->Addon->getAddonsFromCategory( - STATUS_PUBLIC, $app_listedtypes[APP_ID], $category, - 'rated', 'DESC', $list_num, 1, '', false - ); - $upd_addons = $this->_buildMinimalAddonDetails( - $this->Addon->getListAddons($upd_addon_ids, $valid_status, 'Addon.bayesianrating DESC') - ); - - $this->publish('updated_addons', $upd_addons); - + + // fetch another 3 random add-ons + $_feat_ids = $this->AddonTag->getRandomAddons($category, false, 3, null, $addontype=='all' ? null : $addontype); + if (!empty($_feat_ids)) { + $randomAddons = $this->Addon->getListAddons($_feat_ids, $valid_status, + 'FIELD(Addon.id,'.implode(',', $_feat_ids).')', false); + } else { + $randomAddons = false; + } + + $this->publish('featureAddons', $featureAddons); + $this->publish('randomAddons', $randomAddons); + unset($featureAddons); + unset($randomAddons); + // fetch all platforms $this->Platform->unbindFully(); $platforms = $this->Platform->findAll(); $this->publish('platforms', $platforms); - + + // set data available to view + $this->publish('type_id', $addontype); + $this->publish('cat_id', $category); + $this->publish('this_tag', $this_tag); $this->set('content_wide', false); // display features next to each other $this->publish('collapse_categories', false); - + // set layout details $this->publish('bigHeader', true); - $this->publish('bigHeaderText', - sprintf(_('addons_home_header_details'), APP_PRETTYNAME)); - - $this->pageTitle = $this_tag['Translation']['name']['string']. " :: " . - sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME); - $this->publish('rssAdd', array( - "/browse/type:{$addontype}/cat:{$category}/format:rss?sort=updated" - )); + $this->publish('bigHeaderText', sprintf(_('addons_home_header_details'), APP_PRETTYNAME)); + + $this->pageTitle = $this_tag['Translation']['name']['string']. " :: " . sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME); + $this->publish('rssAdd', array("/browse/type:{$addontype}/cat:{$category}/format:rss?sort=updated")); $this->render('category_landing'); } @@ -904,16 +650,21 @@ class AddonsController extends AppController * Add-on listing page for a specific category * * Relevant URL format: /browse/type:1/cat:15?sort=name - * + * * @access private */ function _browseAddonsInCategory() { global $valid_status, $app_listedtypes; - + $addontype = $this->namedArgs['type']; $category = $this->namedArgs['cat']; $format = $this->setLayoutForFormat(); - + + // we are sugar + if (true) { + $this_tag = $category == 'all' ? array() : $this->Tag->findById($category); + $addontype = $addontype == 'all' ? $app_listedtypes[APP_SUGAR] : $addontype; + } else // type:1 && cat:all shows a global add-ons list (not extensions only) if ($addontype == ADDON_EXTENSION && $category == 'all') { $this_tag = array(); @@ -922,7 +673,7 @@ class AddonsController extends AppController $this->Tag->unbindFully(); $this_tag = $this->Tag->findById($category); } - + // determine list sort order if (isset($this->params['url']['sort'])) $sort_by = $this->params['url']['sort']; @@ -947,7 +698,7 @@ class AddonsController extends AppController $sort_dir = 'asc'; break; } - + // show experimental add-ons? if (isset($this->params['url']['exp'])) { /* experimental add-ons requested */ @@ -970,7 +721,7 @@ class AddonsController extends AppController } $this->set('show_exp', $show_exp); $displaystatuses = ($show_exp ? $valid_status : array(STATUS_PUBLIC)); - + if ($format != 'rss') { // initialize pagination component $this->Pagination->total = $this->Addon->countAddonsInCategory( @@ -984,7 +735,7 @@ class AddonsController extends AppController $_limit = 20; $_page = 1; } - + // get enough addons for one page. $addons = $this->Addon->getAddonsByCategory(null, $displaystatuses, $addontype, $category, $sort_by, $sort_dir, $_limit, $_page, '', true); @@ -993,14 +744,14 @@ class AddonsController extends AppController return; } $this->publish('addons', $addons); - + // get platforms (if we are not in RSS mode) if ($format != 'rss') { $this->Platform->unbindFully(); $platforms = $this->Platform->findAll(); $this->publish('platforms', $platforms); } - + // get other categories list (or all, if this is a complete list) $_tags = $this->Tag->query("SELECT DISTINCT t.id FROM tags AS t " ."INNER JOIN addons_tags AS at ON (t.id = at.tag_id) " @@ -1018,14 +769,15 @@ class AddonsController extends AppController foreach($tag_list as $_tag) $_tag_names[] = $_tag['Translation']['name']['string']; array_multisort($_tag_names, SORT_ASC, $tag_list); } - + // set data available to view $this->publish('this_tag', $this_tag); $this->set('type', $addontype); $this->publish('tagList', $tag_list); - + // set layout details and render view if ($category == 'all') { + // @partial translation fallback, 5/13/08 switch ($sort_by) { case 'popular': $_title = ___('browse_addons_popular'); break; case 'updated': $_title = ___('browse_addons_updated'); break; @@ -1040,15 +792,15 @@ class AddonsController extends AppController if ($format != 'rss') { $this->pageTitle = $_title . " :: " . sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME); $this->publish('subpagetitle', $_title); - + // preserve GET variables in RSS feed URLs $_rss_get = array(); foreach($_GET as $_getkey => $_getitem) if ($_getkey != 'url') $_rss_get[] = urlencode($_getkey).'='.urlencode($_getitem); $this->publish('rssAdd', array("/browse/type:{$this->namedArgs['type']}/cat:{$category}/format:rss?".implode('&', $_rss_get))); - + $this->set('collapse_categories', true); - + $this->render('browse'); } else { // RSS feed @@ -1067,9 +819,9 @@ class AddonsController extends AppController global $hybrid_categories, $valid_status; $valid_status = array(STATUS_PUBLIC); - + $format = (isset($this->namedArgs['format']) ? $this->namedArgs['format'] : 'html'); - + // fetch the category belonging to this hybrid page $category = array_search(ADDON_SEARCH, $hybrid_categories[APP_ID]); if ($category) { @@ -1079,20 +831,20 @@ class AddonsController extends AppController $this_tag = null; } $this->publish('this_tag', $this_tag); - + // fetch a list of all subcategories $subcats = $this->Amo->getTags(APP_ID, ADDON_SEARCH); $this->publish('subcats', $subcats); - + // make subcategory ID list to grab recommendations from $subcat_ids = array(); foreach ($subcats as $subcat) $subcat_ids[] = $subcat['Tag']['id']; // add hybrid category for possible other recommendations $subcat_ids[] = $this_tag['Tag']['id']; - - // fetch up to 4 recommended add-ons - $_feat_ids = $this->AddonTag->getRandomAddons($subcat_ids, true, 4); + + // fetch up to 2 recommended add-ons + $_feat_ids = $this->AddonTag->getRandomAddons($subcat_ids, true, 2); if (!empty($_feat_ids)) { $featureAddons = $this->Addon->getListAddons($_feat_ids, $valid_status, null, true); @@ -1100,12 +852,22 @@ class AddonsController extends AppController $featureAddons = array(); } $this->publish('featureAddons', $featureAddons); - + + // fetch 2 random ones. + $_feat_ids = $this->AddonTag->getRandomAddons($subcat_ids, false, 2); + if (!empty($_feat_ids)) { + $randomAddons = $this->Addon->getListAddons($_feat_ids, $valid_status, + null, true); + } else { + $randomAddons = false; + } + $this->publish('randomAddons', $randomAddons); + // fetch all platforms $this->Platform->unbindFully(); $platforms = $this->Platform->findAll(); $this->publish('platforms', $platforms); - + if ($format != 'rss') { $this->set('content_wide', true); // display 2 features next to each other $this->set('collapse_categories', true); @@ -1115,7 +877,7 @@ class AddonsController extends AppController $this->publish('bigHeaderText', sprintf(_('addons_home_header_details'), APP_PRETTYNAME)); $this->layout='mozilla'; //$this->publish('rssAdd', array("/browse/type:".ADDON_SEARCH."/format:rss")); - + $this->render('searchengines'); } else { // RSS feed @@ -1135,15 +897,15 @@ class AddonsController extends AppController $this->render('plugins'); return; } - + /** * dictionaries / language tools landing page */ function _dictionaries() { global $valid_status, $native_languages; - + $format = (isset($this->namedArgs['format']) ? $this->namedArgs['format'] : 'html'); - + // get list of target locales $conditions = array( 'Addon.addontype_id' => array(ADDON_DICT, ADDON_LPAPP), @@ -1155,7 +917,7 @@ class AddonsController extends AppController $target_locales = array(); foreach ($target_locales_raw as $tloc) $target_locales[] = $tloc[0]['target_locale']; unset($target_locales_raw); - + // get list of dictionaries and language packs for each target locale $dicts = array(); foreach($target_locales as $tloc) { @@ -1164,7 +926,7 @@ class AddonsController extends AppController ADDON_DICT => array(), ADDON_LPAPP => array() ); - + // get addons for this target locale $conditions = array( 'LOWER(Addon.target_locale)' => $tloc, @@ -1174,7 +936,7 @@ class AddonsController extends AppController ); $this->Addon->unbindfully(); $dicts_raw = $this->Addon->findAll($conditions, null, null, null, null, 2); - + $_dict_ids = array(); foreach ($dicts_raw as $_dict) $_dict_ids[] = $_dict['Addon']['id']; @@ -1183,24 +945,24 @@ class AddonsController extends AppController $tloc_dicts = $this->Addon->getListAddons($_dict_ids, array(STATUS_PUBLIC), null, true); foreach ($tloc_dicts as $dict) { // add add-ons to results array if (empty($dict['File'])) continue; - + // purge add-ons incompatible with this app $compat = $this->Version->getCompatibleApps($dict['Version'][0]['id']); $thisapp_compat = false; foreach ($compat as $compat_app) $thisapp_compat = $thisapp_compat || ($compat_app['Application']['application_id'] == APP_ID); if (!$thisapp_compat) continue; - + $dicts[$tloc][$dict['Addon']['addontype_id']][] = $dict; } unset($dict, $compat, $thisapp_compat, $compat_app); - + /* determine the effective display name for this target locale */ $locale_parts = explode('-', strtolower(str_replace('_', '-', $tloc))); // normalize region part if (isset($locale_parts[1])) $locale_parts[1] = strtoupper($locale_parts[1]); $normalized_locale = implode('-', $locale_parts); - + $displayname = false; while (true) { $locale = strtolower(implode('-', $locale_parts)); @@ -1241,12 +1003,12 @@ class AddonsController extends AppController // sort dictionary list by effective display name uasort($dicts, create_function('$a,$b', 'return strcasecmp($a["displayname"],$b["displayname"]);')); $this->publish('dicts', $dicts); - + // fetch all platforms $this->Platform->unbindFully(); $platforms = $this->Platform->findAll(); $this->publish('platforms', $platforms); - + // set layout details $this->pageTitle = _('langtools_header_dicts_and_langpacks') .' :: ' . sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME); @@ -1254,7 +1016,7 @@ class AddonsController extends AppController $this->publish('bigHeaderText', sprintf(_('addons_home_header_details'), APP_PRETTYNAME)); $this->layout = 'mozilla'; $this->set('collapse_categories', true); - + $this->render('dictionaries'); } @@ -1265,20 +1027,20 @@ class AddonsController extends AppController global $valid_status; $valid_status = array(STATUS_PUBLIC); - + $format = (isset($this->namedArgs['format']) ? $this->namedArgs['format'] : 'html'); - + // fetch a list of all subcategories $subcats = $this->Amo->getTags(APP_ID, ADDON_THEME); $this->publish('subcats', $subcats); - + // make subcategory ID list to grab recommendations from $subcat_ids = array(); foreach ($subcats as $subcat) $subcat_ids[] = $subcat['Tag']['id']; - + // fetch up to 2 recommended add-ons - $_feat_ids = $this->AddonTag->getRandomAddons($subcat_ids, true, 4); + $_feat_ids = $this->AddonTag->getRandomAddons($subcat_ids, true, 2); if (!empty($_feat_ids)) { $featureAddons = $this->Addon->getListAddons($_feat_ids, $valid_status, null, true); @@ -1286,12 +1048,22 @@ class AddonsController extends AppController $featureAddons = array(); } $this->publish('featureAddons', $featureAddons); - + + // fetch 2 random ones. + $_feat_ids = $this->AddonTag->getRandomAddons($subcat_ids, false, 2); + if (!empty($_feat_ids)) { + $randomAddons = $this->Addon->getListAddons($_feat_ids, $valid_status, + null, true); + } else { + $randomAddons = array(); + } + $this->publish('randomAddons', $randomAddons); + // fetch all platforms $this->Platform->unbindFully(); $platforms = $this->Platform->findAll(); $this->publish('platforms', $platforms); - + // set layout details $this->set('content_wide', true); // display 2 features next to each other $this->set('collapse_categories', true); @@ -1299,7 +1071,7 @@ class AddonsController extends AppController $this->publish('bigHeader', true); $this->publish('bigHeaderText', sprintf(_('addons_home_header_details'), APP_PRETTYNAME)); $this->layout = 'mozilla'; - + $this->render('themes_landing'); } @@ -1313,7 +1085,7 @@ class AddonsController extends AppController //override sandbox, recommended page is only public $this->publish('addonStatus', array(STATUS_PUBLIC)); $this->status = array(STATUS_PUBLIC); - + $criteria = "Feature.start < NOW() AND Feature.end > NOW() AND Feature.application_id ='" . APP_ID . "' AND " ."(Feature.locale = '" . LANG . "' or Feature.locale IS NULL)"; if (isset($this->namedArgs['format']) && $this->namedArgs['format'] == 'rss') { @@ -1323,14 +1095,14 @@ class AddonsController extends AppController $isrss = false; $order = "RAND()"; } - + $_addon_ids = array(); - + if(isset($this->namedArgs['cat'])) { $category = $this->namedArgs['cat']; - $this->Amo->clean($category); + $this->Amo->clean($category); $criteria = "feature > 0 AND tag_id='".$category."'"; $featAddons = $this->AddonTag->findAll($criteria); @@ -1338,23 +1110,21 @@ class AddonsController extends AppController $_addon_ids[] = $_addon['AddonTag']['addon_id']; } else { - $featAddons = $this->Feature->findAll($criteria); + $featAddons = $this->Feature->findAll($criteria); foreach ($featAddons as $_addon) $_addon_ids[] = $_addon['Addon']['id']; } - if (!empty($_addon_ids)) { + if (!empty($_addon_ids)) $featAddons = $this->Addon->getListAddons($_addon_ids, $this->status, $order, true); - } else { + else $featAddons = array(); - } - - + if (!$isrss) { // get platforms (if we are not in RSS mode) $this->Platform->unbindFully(); $platforms = $this->Platform->findAll(); $this->publish('platforms', $platforms); - + $this->layout='mozilla'; $this->pageTitle = _('addons_recommended_pagetitle').' :: '.sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME); $this->publish('addons', $featAddons); @@ -1368,7 +1138,7 @@ class AddonsController extends AppController $this->render('rss/addons', 'rss'); } } - + /** * page to display eula prior to installation */ @@ -1376,14 +1146,13 @@ class AddonsController extends AppController $this->Amo->clean($lightbox); $this->Amo->clean($addon_id); $this->Amo->clean($file_id); - - $this->layout='amo2009'; - + + $this->layout='mozilla'; if (!$addon_id || !is_numeric($addon_id)) { $this->flash(sprintf(_('error_missing_argument'), 'addon_id'), '/', 3); return; } - + $this->Addon->unbindFully(); $this->Addon->bindModel( array( @@ -1403,31 +1172,22 @@ class AddonsController extends AppController ) ) ); - + $this_addon = $this->Addon->findById($addon_id); if (empty($this_addon)) { $this->flash(_('error_addon_notfound'), '/', 3); return; } - + if (isset($file_id)) { $this->File->unbindFully(); $this_file = $this->File->findById($file_id); $this_addon['Version'] = $this->Version->findAllById($this_file['File']['version_id'], null, null, 0); - - // is this the latest public version? - if ($this_addon['Addon']['status'] == STATUS_PUBLIC) { - $latest_version_id = $this->Version->getVersionByAddonId($addon_id, $this_addon['Addon']['status']); - $this->publish('is_latest', ($latest_version_id === $this_addon['Version'][0]['Version']['id']), false); - } else { - $this->publish('is_latest', false, false); - } - $this->Platform->unbindFully(); $platforms = $this->Platform->findAllById($this_file['File']['platform_id']); $this->publish('platforms', $platforms); } - else { + else { $this->publish('policy', 1); } // get the tags that are related to the addon, so that they have translation data @@ -1437,12 +1197,13 @@ class AddonsController extends AppController } $related_tags = $this->Tag->findAll(array('Tag.id' => $_related_tag_ids, 'Tag.application_id' => APP_ID)); unset($_related_tag_ids); - + $this->publish('relatedTags', $related_tags); $this->publish('addon', $this_addon); + $this->publish('addonIconPath', $this->Image->getAddonIconURL($addon_id), false); $this->pageTitle = sprintf(_('addons_display_pagetitle'), $this_addon['Translation']['name']['string']). ' :: '.sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME); - + } @@ -1452,16 +1213,16 @@ class AddonsController extends AppController function previews($id) { $this->Amo->clean($id); $this->layout = 'mozilla'; - + if (!$id || !is_numeric($id)) { $this->flash(sprintf(_('error_missing_argument'), 'addon_id'), '/', 3); return; } - + $addon_data = $this->Addon->find(array( 'Addon.id' => $id, 'Addon.inactive' => '0', - 'Addon.status' => array(STATUS_PUBLIC, STATUS_SANDBOX, STATUS_NOMINATED)), + 'Addon.status' => array(STATUS_PUBLIC, STATUS_SANDBOX, STATUS_NOMINATED)), null , null , 1); if (empty($addon_data)) { $this->flash(_('error_addon_notfound'), '/', 3); @@ -1491,20 +1252,14 @@ class AddonsController extends AppController */ function versions($id) { global $valid_status; - + $this->Amo->clean($id); // unbind addon from all references but its authors $bindusers = array('hasAndBelongsToMany' => array('User' => $this->Addon->hasAndBelongsToMany['User'])); $this->Addon->unbindFully(); $this->Addon->bindModel($bindusers); - $addon = $this->Addon->find(array('Addon.id'=>$id, - 'Addon.status'=>$valid_status, 'Addon.inactive'=>0), null, null, - null, null, 0); - if (empty($addon)) { - $this->flash(_('error_addon_notfound'), '/', 3); - return; - } + $addon = $this->Addon->findById($id, null, null, null, null, 0); // show all valid (even experimental) statuses on versions page $version_list = $this->Version->getVersionIdsByAddonId($id, $valid_status); @@ -1512,39 +1267,36 @@ class AddonsController extends AppController $version_ids = array(); $comp_apps_by_id = array(); foreach ($version_list as $single_id) { - $cur_id = $single_id['Version']['id']; + $cur_id = $single_id['Version']['id']; $version_ids[] = $cur_id; $compat_apps = $this->Version->getCompatibleApps($cur_id); $comp_apps_by_id[$cur_id] = array_slice($compat_apps, 0, 1); - } - - if (!empty($version_ids)) { + } + + if (!empty($version_ids)) { $versions = $this->Version->findAllById($version_ids, null, "Version.created DESC", null, null, 1); - - for($i =0 ; $i < count($versions); $i++) { - $versions[$i]['Compatibility'] = $comp_apps_by_id[$versions[$i]['Version']['id'] ]; - } - } + + for($i =0 ; $i < count($versions); $i++) { + $versions[$i]['Compatibility'] = $comp_apps_by_id[$versions[$i]['Version']['id'] ]; + } + } else $versions = array(); - + $this->Platform->unbindFully(); $platforms = $this->Platform->findAll(); $this->publish('addon', $addon); $this->publish('versions', $versions); $this->publish('platforms', $platforms); - + $_title = sprintf(_('addons_versions_pagetitle'), $addon['Translation']['name']['string']); if (!isset($this->namedArgs['format']) || $this->namedArgs['format'] != 'rss') { $this->publish('addonIconPath', $this->Image->getAddonIconURL($id)); $this->pageTitle = $_title. ' :: '.sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME); $this->publish('subpagetitle', $_title); $this->publish('rssAdd', array("/addons/versions/{$id}/format:rss")); - - $this->publish('breadcrumbs', array( - sprintf(___('addons_home_pagetitle'), APP_PRETTYNAME) => '/', - $addon['Translation']['name']['string'] => "/addon/{$id}" - )); + + $this->layout = 'mozilla'; $this->render(); } else { $this->publish('rss_title', $_title); @@ -1559,19 +1311,19 @@ class AddonsController extends AppController function rss($type='') { $this->Amo->clean($type); $type = strtolower($type); - + switch($type) { case 'newest': $this->redirect('/browse/type:1/cat:all/format:rss?sort=newest'); return; break; - + default: $this->redirect('/'); return; } } - + } ?> |