Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/site/app/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'site/app/controllers')
-rw-r--r--site/app/controllers/addons_controller.php788
-rw-r--r--site/app/controllers/admin_controller.php154
-rw-r--r--site/app/controllers/api_controller.php2
-rw-r--r--site/app/controllers/collections_controller.php959
-rw-r--r--site/app/controllers/compatibility_controller.php21
-rw-r--r--site/app/controllers/components/amo.php90
-rw-r--r--site/app/controllers/components/audit.php84
-rw-r--r--site/app/controllers/components/developers.php98
-rw-r--r--site/app/controllers/components/editors.php395
-rw-r--r--site/app/controllers/components/email.php9
-rw-r--r--site/app/controllers/components/image.php31
-rw-r--r--site/app/controllers/components/search.php108
-rw-r--r--site/app/controllers/components/stats.php88
-rw-r--r--site/app/controllers/developers_controller.php1643
-rw-r--r--site/app/controllers/downloads_controller.php15
-rw-r--r--site/app/controllers/editors_controller.php1054
-rw-r--r--site/app/controllers/files_controller.php20
-rw-r--r--site/app/controllers/images_controller.php19
-rw-r--r--site/app/controllers/pages_controller.php19
-rw-r--r--site/app/controllers/reviews_controller.php4
-rw-r--r--site/app/controllers/search_controller.php75
-rw-r--r--site/app/controllers/statistics_controller.php34
-rw-r--r--site/app/controllers/tests_controller.php1
-rw-r--r--site/app/controllers/users_controller.php75
-rw-r--r--site/app/controllers/versions_controller.php28
25 files changed, 2237 insertions, 3577 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;
}
}
-
+
}
?>
diff --git a/site/app/controllers/admin_controller.php b/site/app/controllers/admin_controller.php
index d9ae3ec..7495e90 100644
--- a/site/app/controllers/admin_controller.php
+++ b/site/app/controllers/admin_controller.php
@@ -39,7 +39,7 @@
class AdminController extends AppController
{
var $name = 'Admin';
- var $uses = array('Addon', 'Addontype', 'Application', 'Approval', 'Appversion', 'Cannedresponse', 'Collection', 'CollectionPromo', 'Eventlog', 'Feature', 'File', 'Group', 'Platform', 'Tag', 'Translation', 'User', 'Version', 'Memcaching');
+ var $uses = array('Addon', 'Addontype', 'Application', 'Approval', 'Appversion', 'Cannedresponse', 'Eventlog', 'Feature', 'File', 'Group', 'Platform', 'Tag', 'Translation', 'User', 'Version', 'Memcaching');
var $components = array('Amo', 'Audit', 'Developers', 'Error', 'Versioncompare');
var $helpers = array('Html', 'Javascript');
//These defer to their own access checks
@@ -67,11 +67,12 @@ class AdminController extends AppController
$this->set('jsAdd', array('developers',
'jquery-compressed.js',
- 'jquery.autocomplete.pack.js'));
+ 'jquery.autocomplete.js'));
$this->set('suppressJQuery', 1);
$this->breadcrumbs = array('Admin Control Panel' => '/admin/index');
$this->set('breadcrumbs', $this->breadcrumbs);
+ $this->set('suppressJQuery', 1);
$this->set('subpagetitle', 'Admin Control Panel');
@@ -113,7 +114,7 @@ class AdminController extends AppController
}
if (!defined('USERAPP')) {
- define('USERAPP', 1); // Firefox
+ define('USERAPP', SITE_APP); // Firefox
}
$this->Session->write('Features', array('userlang' => USERLANG, 'userapp' => USERAPP));
@@ -151,10 +152,11 @@ class AdminController extends AppController
$this->set('last24', $last24);
//Counts
- $count['extensions'] = $this->Addon->query("SELECT COUNT(*) FROM addons WHERE addontype_id=".ADDON_EXTENSION);
- $count['themes'] = $this->Addon->query("SELECT COUNT(*) FROM addons WHERE addontype_id=".ADDON_THEME);
- $count['dictionaries'] = $this->Addon->query("SELECT COUNT(*) FROM addons WHERE addontype_id=".ADDON_DICT);
- $count['searchengines'] = $this->Addon->query("SELECT COUNT(*) FROM addons WHERE addontype_id=".ADDON_SEARCH);
+ $count['activities'] = $this->Addon->query("SELECT COUNT(*) FROM addons WHERE addontype_id=".ADDON_ACTIVITY);
+ //$count['extensions'] = $this->Addon->query("SELECT COUNT(*) FROM addons WHERE addontype_id=".ADDON_EXTENSION);
+ //$count['themes'] = $this->Addon->query("SELECT COUNT(*) FROM addons WHERE addontype_id=".ADDON_THEME);
+ //$count['dictionaries'] = $this->Addon->query("SELECT COUNT(*) FROM addons WHERE addontype_id=".ADDON_DICT);
+ //$count['searchengines'] = $this->Addon->query("SELECT COUNT(*) FROM addons WHERE addontype_id=".ADDON_SEARCH);
$now = time();
$count['activeSessions'] = $this->Addon->query("SELECT COUNT(*) FROM cake_sessions WHERE expires > {$now}");
$this->set('count', $count);
@@ -522,77 +524,6 @@ class AdminController extends AppController
$this->set('page', 'applications');
$this->render('applications_create');
}
-
- /**
- * Collections Manager
- */
- function collections($action='') {
- switch($action) {
- case 'promobox':
- $this->_collectionsPromoBox();
- break;
- default:
- $this->set('page', 'collections');
- $this->render('collections');
- break;
- }
- }
-
- function _collectionsPromoBox() {
-
- if (!empty($_POST)) {
- switch ($_POST['action']) {
- case 'add':
- global $valid_languages;
- // It's easiest just to split out the stuff we need here and pass it into a custom function.
- if (preg_match('/\[(\d+)\]/', $this->data['Collection']['name'], $matches)) {
- $_collection_id = $matches[1];
- } else {
- $this->Error->addError('Collection ID must be specified in brackets.');
- }
-
- if (in_array($_POST['locale'], array_keys($valid_languages))) {
- $_locale = $_POST['locale'];
- } else if ($_POST['locale'] == 'all') {
- $_locale = '';
- } else {
- $this->Error->addError('Invalid locale specified.');
- }
-
- if (in_array($_POST['titletagline'], array_keys($this->CollectionPromo->titles_and_taglines))) {
- $_titletagline = $_POST['titletagline'];
- } else {
- $this->Error->addError('Invalid Title/TagLine specified.');
- }
-
- if ($this->Error->noErrors()) {
- $this->CollectionPromo->promoteCollection($_collection_id, $_titletagline, $_locale);
- $this->data = array(); // reset so it doesn't prefill the box again
- $this->publish('changeSuccess', true);
- }
- break;
- case 'delete':
- list($_collection_id, $_titletagline, $_locale) = explode('--',$_POST['target']);
- $_locale = ($_locale == 'all') ? '' : $_locale;
-
- if ($this->CollectionPromo->demoteCollection($_collection_id, $_titletagline, $_locale) === false) {
- $this->Error->addError('Failed to demote collection.');
- } else {
- $this->publish('changeSuccess', true);
- }
- break;
- }
- }
-
- $this->set('titles_and_taglines', $this->CollectionPromo->titles_and_taglines);
- $this->publish('promoted_collections', $this->CollectionPromo->findAll());
- $this->set('locales', LANGUAGE_CONFIG::getAllValidLanguages('english',true));
-
- $this->set('errors', $this->Error->errors);
- $this->set('page', 'collections');
- $this->set('subpage', 'promobox');
- $this->render('collections_promobox');
- }
/**
* Category Manager
@@ -607,6 +538,10 @@ class AdminController extends AppController
$this->set('breadcrumbs', $this->breadcrumbs);
$applications = array('All');
+
+ // we are sugar
+ $applications = array();
+
$_applications = $this->Amo->getApplicationName();
if (!empty($_applications)) {
foreach ($_applications as $app_id => $app_name) {
@@ -1541,7 +1476,7 @@ class AdminController extends AppController
if (!empty($this->data['User']['password'])) {
$session = $this->Session->read('User');
- if ($this->User->checkPassword($session, $this->data['User']['password'])) {
+ if (md5($this->data['User']['password']) == $session['password']) {
$this->set('config', $config);
$this->set('rand', $sessionConfig['rand']);
@@ -1629,17 +1564,16 @@ class AdminController extends AppController
if (!empty($flagged)) {
foreach ($flagged as $k => $addon) {
$version = $this->Version->findByAddon_id($addon['Addon']['id'],
- array('Version.id', 'Version.addon_id', 'Version.version'),
- 'Version.created DESC');
- if (!$version) $version = array();
+ array('Version.id', 'Version.addon_id',
+ 'Version.version'
+ ), 'Version.created DESC');
$flagged[$k] = array_merge_recursive($flagged[$k], $version);
$history = $this->Approval->find(
- "Approval.addon_id={$addon['Addon']['id']} AND
- ((Approval.reviewtype='nominated' AND Approval.action=".STATUS_NOMINATED.") OR
- (Approval.reviewtype='pending' AND Approval.action=".STATUS_PENDING."))",
- null, 'Approval.created DESC');
- if (!$history) $history = array();
+ "Approval.addon_id={$addon['Addon']['id']} AND
+ ((Approval.reviewtype='nominated' AND Approval.action=".STATUS_NOMINATED.") OR
+ (Approval.reviewtype='pending' AND Approval.action=".STATUS_PENDING."))",
+ null, 'Approval.created DESC');
$flagged[$k] = array_merge_recursive($flagged[$k], $history);
}
}
@@ -1657,8 +1591,7 @@ class AdminController extends AppController
function users($user_id = 0, $type = 'edit') {
$this->breadcrumbs['User Manager'] = '/admin/users';
$this->set('breadcrumbs', $this->breadcrumbs);
- $this->set('suppressJQuery', 0);
-
+
if (!empty($user_id)) {
$this->Amo->clean($user_id);
$this->User->id = $user_id;
@@ -1704,10 +1637,6 @@ class AdminController extends AppController
case 'edit':
default:
$this->User->save($this->data['User']);
-
- // save author "about me"
- list($localizedFields, $unlocalizedFields) = $this->User->splitLocalizedFields($this->data['User']);
- $this->User->saveTranslations($user_id, $this->params['form']['data']['User'], $localizedFields);
//Log admin action
$this->Eventlog->log($this, 'admin', 'user_edit', null, $user_id);
@@ -1718,9 +1647,6 @@ class AdminController extends AppController
} else {
$user = $this->User->read();
- // grab translated fields
- $translations = $this->User->getAllTranslations($user_id);
- $this->set('translations', $translations);
}
}
elseif (!empty($_GET['q'])) {
@@ -1731,9 +1657,6 @@ class AdminController extends AppController
$this->flash('E-mail not found.', '/admin/users');
return;
}
- // grab translated fields
- $translations = $this->User->getAllTranslations($user['User']['id']);
- $this->set('translations', $translations);
}
$this->set('page', 'users');
@@ -1803,38 +1726,5 @@ class AdminController extends AppController
$this->set('results', $results);
$this->render('userlookup', 'ajax');
}
-
- /**
- * AJAX Collection lookup. Matches either name or nickname
- */
- function collectionLookup() {
- if (!$this->SimpleAcl->actionAllowed('Admin', '%', $this->Session->read('User')) ||
- !$this->SimpleAcl->actionAllowed('Editor', '*', $this->Session->read('User')) ) {
- $this->Amo->accessDenied();
- }
- global $app_shortnames;
-
- $text = $_REQUEST['q'];
- $this->Amo->clean($text);
- $results = array();
-
- $_query = "SELECT
- collections.id, translations.localized_string, collections.nickname, collections.application_id
- FROM collections LEFT JOIN translations ON collections.name=translations.id
- WHERE (translations.locale='".LANG."'
- AND translations.localized_string LIKE '%{$text}%')
- OR collections.nickname LIKE '%{$text}%'
- ORDER BY translations.localized_string";
-
- if ($collections = $this->Collection->query($_query)) {
- foreach ($collections as $collection) {
- $_application = array_search($collection['collections']['application_id'], $app_shortnames);
- $results[] = "{$collection['translations']['localized_string']}|ID: {$collection['collections']['id']}|App: {$_application}|nickname: {$collection['collections']['nickname']};";
- }
- }
-
- $this->set('results', $results);
- $this->render('userlookup', 'ajax');
- }
}
?>
diff --git a/site/app/controllers/api_controller.php b/site/app/controllers/api_controller.php
index 33a85ce..1e41f27 100644
--- a/site/app/controllers/api_controller.php
+++ b/site/app/controllers/api_controller.php
@@ -52,7 +52,7 @@ class ApiController extends AppController
// cribbed from addonscontroller
// some of this is excessive but will likely be needed as
// development continues
- var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox', 'checkAdvancedSearch');
+ var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox');
var $uses = array('Addon', 'AddonCollection', 'Addontype', 'Application', 'Collection', 'File', 'Platform', 'Tag', 'Translation', /*'Review',*/ 'UpdateCount', 'Version');
var $components = array('Amo', 'Image', 'Pagination', 'Search', 'Session', 'Versioncompare');
var $helpers = array('Html', 'Link', 'Time', 'Localization', 'Ajax', 'Number', 'Pagination');
diff --git a/site/app/controllers/collections_controller.php b/site/app/controllers/collections_controller.php
index e9b7bfd..da80d85 100644
--- a/site/app/controllers/collections_controller.php
+++ b/site/app/controllers/collections_controller.php
@@ -39,705 +39,75 @@
class CollectionsController extends AppController
{
var $name = 'Collections';
- var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox', 'checkAdvancedSearch');
- var $uses = array('Addon', 'AddonCollection', 'Application', 'Collection', 'File',
- 'Platform', 'Preview', 'Translation', 'Version');
- var $components = array('Amo', 'CollectionsListing', 'Developers', 'Error', 'Helper', 'Image', 'Pagination', 'Session');
- var $actionHelpers = array('Html');
- var $helpers = array('Html', 'Link', 'Listing', 'Time', 'Localization', 'Pagination', 'Number', 'Form');
+ var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox');
+ var $uses = array('Addon', 'AddonTag', 'Addontype', 'Application',
+ 'Feature', 'File', 'Platform', 'Preview', 'Tag', 'Translation',
+ 'Review', 'Version', 'Collection');
+ var $components = array('Amo', 'Image', 'Pagination', 'Session', 'Userfunc', 'Search');
+ var $helpers = array('Html', 'Link', 'Time', 'Localization', 'Ajax', 'Number', 'Pagination');
var $exceptionCSRF = array("/collections/install");
var $namedArgs = true;
var $securityLevel = 'low';
function beforeFilter() {
- $this->layout='mozilla';
- $this->publish('collapse_categories', true);
- $this->publish('collectionSearch', true);
- $this->pageTitle = 'Collections' . " :: " . sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME);
- $this->publish('jsAdd', array('jquery.autocomplete.pack.js'), false);
// Disable ACLs because this controller is entirely public.
$this->SimpleAuth->enabled = false;
$this->SimpleAcl->enabled = false;
-
- // disable query caching so devcp changes are visible immediately
- if ($this->Session->check('User')) {
- foreach ($this->uses as $_model) {
- $this->$_model->caching = false;
- }
- }
-
- $this->publish('jsAdd', array('amo2009/collections', 'jquery-ui/jqModal.js'));
+ $this->layout='mozilla';
+ $this->publish('collapse_categories', true);
+ $this->pageTitle = 'Collections' . " :: " . sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME);
}
-
+
function index() {
- /* TODO: preserve get params */
- $this->redirect('/collections/editors_picks');
+
}
-
- function _listing($collections, $pagination_options=array()) {
- $ids = array();
- foreach ($collections as $c) $ids[] = $c['Collection']['id'];
-
- $collections = $this->CollectionsListing->fetchPage($ids, $pagination_options);
- list($sort_opts, $sortby) = $this->CollectionsListing->sorting();
-
- $this->publish('sort_opts', $sort_opts);
- $this->publish('sortby', $sortby);
- $this->publish('collections', $collections);
- $this->set('tabs', $this->_collectionTabs());
-
- // if a collection was just deleted, show success message
- $this->publish('collection_deleted', $this->Session->delete('collection_deleted'), false);
-
- $this->publish('breadcrumbs', array(
- sprintf(___('addons_home_pagetitle'), APP_PRETTYNAME) => '/',
- ));
-
- $this->render('listing');
- }
-
- function _collectionTabs() {
- $tabs = array(
- array('href' => 'editors_picks',
- 'text' => ___('collections_index_li_editors')),
- array('href' => 'popular',
- 'text' => ___('collections_index_li_popular')),
- );
-
- if ($this->Session->check('User')) {
- $tabs = array_merge($tabs, array(
- array('href' => 'mine',
- 'text' => ___('collections_index_li_mine')),
- array('href' => 'favorites',
- 'text' => ___('collections_index_li_favorites')),
- ));
- }
- return $tabs;
- }
-
-
- function editors_picks() {
- $this->set('selected', 'editors_picks');
- $conditions = array('Collection.collection_type' => Collection::COLLECTION_TYPE_EDITORSPICK,
- 'Collection.listed' => 1);
- $this->Collection->unbindFully();
- $collections = $this->Collection->findAll($conditions, 'Collection.id');
- $this->_listing($collections);
- }
-
- function popular() {
- $this->set('selected', 'popular');
- $this->Collection->unbindFully();
- $collections = $this->Collection->findAll(array('Collection.listed' => 1),
- 'Collection.id');
- $pagination = array('sortBy' => 'subscribers DESC');
- $this->_listing($collections, $pagination);
- }
-
- function mine() {
- $this->Amo->checkLoggedIn();
-
- $this->set('selected', 'mine');
- $this->set('filler', sprintf(___('collections_index_filler_mine'),
- $this->Html->url('/collections/add')));
-
- $user = $this->Session->read('User');
- $collections = $this->Collection->execute(
- "SELECT Collection.id
- FROM collections AS Collection JOIN collections_users
- ON Collection.id = collections_users.collection_id
- WHERE collections_users.user_id = " . $user['id']);
- $this->_listing($collections);
- }
-
- function favorites() {
- $this->Amo->checkLoggedIn();
- $this->set('selected', 'favorites');
- $this->set('filler', sprintf(___('collections_index_filler_favorites'),
- $this->Html->url('/pages/collector')));
-
- $user = $this->Session->read('User');
- $collections = $this->Collection->execute(
- "SELECT Collection.id
- FROM collections AS Collection JOIN collection_subscriptions
- ON Collection.id = collection_subscriptions.collection_id
- WHERE collection_subscriptions.user_id = " . $user['id']);
- $this->_listing($collections);
- }
-
- /**
- * Creates a collection if POSTed to, otherwise shows a collection creation form
- */
- function add() {
- $this->Amo->checkLoggedIn(); // must be logged in
-
- // view setup
- $this->layout = 'amo2009'; // TODO: remove this when the entire controller is amo2009-based
- $this->set('bodyclass', 'inverse collections-page');
- $this->publish('jsAdd', array('jquery.autocomplete.pack.js'));
- $this->publish('breadcrumbs', array(
- sprintf(___('addons_home_pagetitle'), APP_PRETTYNAME) => '/',
- ___('collections_breadcrumb') => '/collections'
- ));
-
- $initial_addons = array();
- if (!empty($this->params['url']['addons'])) {
- $_init_ids = explode(',', $this->params['url']['addons']);
- foreach ($_init_ids as &$_init_id) {
- if (!is_numeric($_init_id)) continue;
- $_addon = $this->Addon->getAddon($_init_id);
- if (empty($_addon)) continue;
- $initial_addons[] = array(
- 'id' => $_addon['Addon']['id'],
- 'name' => $_addon['Translation']['name']['string'],
- 'preview' => $this->Image->getAddonIconURL($_init_id)
- );
- }
- }
- $this->publish('initial_addons', $initial_addons);
-
- if (isset($this->data['Collection'])) {
- // clean up whitespace
- $this->data['Collection']['name'] = trim($this->data['Collection']['name']);
- $this->data['Collection']['description'] = trim($this->data['Collection']['description']);
-
- $user = $this->Session->read('User');
- $this->data['Collection']['user_id'] = $user['id'];
- $this->data['Collection']['application_id'] = APP_ID; // defaults to current app
- $this->data['Collection']['defaultlocale'] = LANG; // defaults to current lang
-
- $data = $this->data['Collection'];
- $this->Amo->clean($data);
- if ($this->Collection->save($data)) {
- $collectionid = $this->Collection->id; // new collection id
- $_coll = $this->Collection->findById($collectionid, array('Collection.uuid'));
-
- $this->Collection->addUser($this->Collection->id, $user['id'], COLLECTION_ROLE_OWNER);
-
- if (!empty($this->params['form']['addons'])) {
- // add-ons preselected
- $this->Amo->clean($this->params['form']['addons']);
- foreach ($this->params['form']['addons'] as &$addon) {
- $this->Collection->addAddonToCollection($collectionid, $user['id'], $addon);
- }
- }
-
- $this->Session->write('collection_created', $collectionid);
- $this->redirect("/collections/view/{$_coll['Collection']['uuid']}");
- return;
- } else {
- $this->set('form_errors', true);
- }
- }
- }
-
- /**
- * Non-JS only: Adds an add-on to a collection, then redirects to display page
- */
- function addtocollection() {
- $this->Amo->checkLoggedIn(); // must be logged in
-
- if (empty($this->data['addon_id']) || empty($this->data['collection_uuid'])) {
- $this->flash(sprintf(_('error_missing_argument'), 'addon_id or collection_id'), '/', 3);
- return;
- }
-
- // create new collection if requested
- if ($this->data['collection_uuid'] == 'new') {
- if (is_array($this->data['addon_id']))
- $addonids = implode(',', $this->data['addon_id']);
- else
- $addonids = $this->data['addon_id'];
- $addonids = urlencode($addonids);
- $this->redirect("/collections/add/?addons={$addonids}");
+
+ function display($id = NULL) {
+ $this->set('jsAdd', array('jquery-ui/ui.core.min.js', 'jquery-ui/ui.accordion.min.js', 'jquery-ui/jqModal.js'));
+
+ $this->Amo->clean($id);
+ if (!$id || !is_numeric($id)) {
+ $this->flash(sprintf(_('error_missing_argument'), 'collection_id'), '/', 3);
return;
}
-
- $this->Amo->clean($this->data);
- $addon_id = $this->data['addon_id'];
- $collection_id = $this->Collection->getIdForUUID($this->data['collection_uuid']);
- if (!is_numeric($addon_id) || !$collection_id) {
- $this->flash(sprintf(_('error_missing_argument'), 'addon_id or collection_id'), '/', 3);
+
+ $_conditions = array(
+ 'Collection.id' => $id,
+ 'Collection.listed' => 1,
+ );
+
+ $this->Collection->unbindFully();
+ $collection = $this->Collection->find($_conditions, null, null, 1);
+
+ if($collection == null) {
+ $this->flash(_('collection_not_found'), '/', 3);
return;
}
- $user = $this->Session->read('User');
- $added = $this->Collection->addAddonToCollection($collection_id, $user['id'], $addon_id);
- // go to add-on's display page and display success message
- $this->Session->write('collection_addon_added', $this->data['collection_uuid']);
- $this->redirect("/addon/{$addon_id}");
- return;
- }
-
- function _getSortedAddons($collection_id) {
- $sort_options = array(
- 'date-added' => ___('collections_detail_sort_date'),
- 'name' => ___('collections_detail_sort_name'),
- 'popularity' => ___('collections_detail_sort_popularity')
- );
-
- // Fetch #1. What's in the collection?
- $addonIds = $this->Addon->getAddonsFromCollection($collection_id);
-
- // Set up pagination
- $this->Pagination->total = count($addonIds);
- $this->Pagination->show = 7;
- list($order, $limit, $page) = $this->Pagination->init();
-
- // Default sorting is by date added to Collection.
- if (isset($_GET['sortby']) && array_key_exists($_GET['sortby'], $sort_options)) {
- $sortby = $_GET['sortby'];
- } else {
- $sortby = 'date-added';
- }
-
- // Fetch #2. Sort and fetch paged addon ids.
- if ($sortby == 'date-added') {
- $field = 'addons_collections.added DESC';
- $extra = 'JOIN addons_collections ON Addon.id = addons_collections.addon_id';
- $pagedIds = $this->Addon->sorted($addonIds, $field, $limit, $page, $extra);
- } else {
- if ($sortby == 'popularity') {
- $field = 'weeklydownloads DESC';
- } else if ($sortby == 'name') {
- $field = 'name';
- }
- $pagedIds = $this->Addon->sorted($addonIds, $field, $limit, $page);
- }
-
- // Fetch #3! Pull useful addon data this time.
- $addons = $this->Addon->getAddonList($pagedIds,array(
+
+ $addonIds = $this->Addon->getAddonsFromCollection($id);
+
+ $addons = $this->Addon->getAddonList($addonIds,array(
'all_tags', 'authors', 'compatible_apps', 'files', 'latest_version',
'list_details'));
-
+
foreach($addons as &$addon) {
- $a = &$addon['Addon'];
- // Get publish details for each add-on
- $publishDetails = $this->Addon->getCollectionPublishDetails($a['id'], $collection_id);
- $a = array_merge($a, $publishDetails);
- }
-
- return array($addons, $sort_options, $sortby);
- }
-
- function view($uuid = NULL) {
- if (!$uuid) {
- $this->flash(sprintf(_('error_missing_argument'), 'collection_id'), '/', 3);
- return;
+ $addonId = $addon['Addon']['id'];
+ $addon['Addon']['dateadded'] = $this->Addon->getDateAddedToCollection($addonId, $id);
}
-
- $id = $this->Collection->getIdForUuidOrNickname($uuid);
- if (!$id) {
- $this->flash(_('collection_not_found'), '/', 3);
- return;
- }
- $_conditions['Collection.id'] = $id;
-
- $collection = $this->Collection->find($_conditions, null, null, 1);
-
- list($addons, $sort_options, $sortby) = $this->_getSortedAddons($collection['Collection']['id']);
-
+
$this->publish('addons', $addons);
$this->publish('collection', $collection);
- $this->publish('sort_options', $sort_options);
- $this->publish('sortby', $sortby);
$this->pageTitle = $collection['Translation']['name']['string'] . " :: " . sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME);
-
- // User-specific stuff.
- if ($this->Session->check('User')) {
- $user = $this->Session->read('User');
- $is_subscribed = $this->Collection->isSubscribed($id, $user['id']);
- if ($is_subscribed) {
- $action = $this->Collection->getUnsubscribeUrl();
- } else {
- $action = $this->Collection->getSubscribeUrl();
- }
- $this->publish('is_subscribed', $is_subscribed);
- $this->publish('subscribe_action', $action);
- $this->_getUserRights($user, $id);
- } else {
- // Use 0 as a dummy user.
- $this->_getUserRights(array('id' => 0), $id);
- }
-
- // was the collection just created? show success message
- $collection_created = $this->Session->read('collection_created');
- if ($collection_created == $id) $this->Session->delete('collection_created');
- $this->publish('collection_created', ($collection_created == $id));
-
- $rss_url = sprintf('/collection/%s?format=rss', $collection['Collection']['uuid']);
- $this->publish('rssAdd', array(
- array($rss_url,
- sprintf(___('collection_detail_rss_title'),
- $collection['Translation']['name']['string']))
- ));
-
+
+
if (isset($_GET['format']) && $_GET['format'] == 'rss') {
- $this->publish('atom_self', $rss_url);
$this->publish('rss_title', $collection['Translation']['name']['string']);
$this->publish('rss_description', $collection['Translation']['description']['string']);
- return $this->render('rss/collection', 'rss');
- }
-
- $this->publish('breadcrumbs', array(
- sprintf(___('addons_home_pagetitle'), APP_PRETTYNAME) => '/',
- ___('collections_breadcrumb') => '/collections'
- ));
-
- $this->render('detail');
- }
-
- /**
- * Subscribes user to the collection
- */
- function subscribe($ajax = null) {
- $this->_subscribe_unsubscribe($ajax);
- }
-
- /**
- * Unsubscribe a user from a collection
- */
- function unsubscribe($ajax = null) {
- $this->_subscribe_unsubscribe($ajax);
- }
-
- /**
- * Combined function for subscribing/unsubscribing. Action is determined by
- * $this->action.
- * @access private
- * @param string $ajax undefined or 'ajax' for no-frills rendering
- * @return bool render()ed successfully?
- */
- function _subscribe_unsubscribe($ajax = null) {
- $this->Amo->checkLoggedIn(); // must be logged in
-
- $this->publish('is_ajax', ($ajax == 'ajax'));
-
- if (!in_array($this->action, array('subscribe', 'unsubscribe'))) {
- $this->flash(___('error_access_denied'), '/', 3);
- return;
- }
-
- if (empty($this->params['form']['uuid'])) { // uuid needs to be POSTed
- $this->flash(sprintf(_('error_missing_argument'), 'uuid'), '/', 3);
- return;
- }
- $uuid = $this->params['form']['uuid'];
- $id = $this->Collection->getIdForUuidOrNickname($uuid);
- if (!$id || !is_numeric($id)) {
- $this->set('success', false);
- return $this->render('subscribe');
- }
-
- $user = $this->Session->read('User');
- if ($this->action == 'subscribe') {
- $result = $this->Collection->subscribe($id, $user['id']);
- } else {
- $result = $this->Collection->unsubscribe($id, $user['id']);
+ $this->render('rss/collection', 'rss');
}
- $collection = $this->Collection->findById($id, array('id', 'name'), null, -1);
- $this->set('success', $result);
-
- $this->publish('collection', $collection);
-
- // set up view and render result
- $this->publish('breadcrumbs', array(
- sprintf(___('addons_home_pagetitle'), APP_PRETTYNAME) => '/',
- ___('collections_breadcrumb') => '/collections'
- ));
- return $this->render('subscribe');
}
-
- /**
- * Edit collection
- */
- function edit($uuid = null) {
- $this->Amo->checkLoggedIn(); // must be logged in
-
- // disable query caching so changes are visible immediately
- $this->Collection->caching = false;
-
- if (empty($uuid)) {
- $this->flash(sprintf(_('error_missing_argument'), 'collection_id'), '/', 3);
- return;
- }
- $id = $this->Collection->getIdForUuidOrNickname($uuid);
- if (!$id) {
- $this->flash(_('collection_not_found'), '/', 3);
- return;
- }
-
- // access rights
- $user = $this->Session->read('User');
- $this->publish('user', $user);
- $rights = $this->_getUserRights($user, $id);
- if (!($rights['writable'] || $rights['isadmin'])) {
- $this->flash(___('error_access_denied'), '/', 3);
- return;
- }
-
- if (!empty($this->data)) {
- // Delete collection?
- if (isset($this->data['action']) && $this->data['action'] == 'delete-coll') {
- if (!$rights['atleast_owner']) {
- $this->flash(___('error_access_denied'), '/', 3);
- return;
- }
- $this->Collection->delete($id);
- $this->Session->write('collection_deleted', true);
- $this->redirect("/collections");
- return;
- }
-
- // regular save
- $success = $this->_saveCollectionEdit($id, $rights);
-
- if ($success) {
- // grab updated collection nickname/uuid
- $updated = $this->Collection->findById($id, array('nickname', 'uuid'));
- $this->publish('collection_saved', true, false);
- if (empty($updated['Collection']['nickname']))
- $this->publish('collection_url', "/collection/{$updated['Collection']['uuid']}");
- else
- $this->publish('collection_url', "/collection/{$updated['Collection']['nickname']}");
- } else {
- $this->set('form_errors', true);
- }
- }
-
- // get collection data for display (and publish to view)
- $this->_getCollectionDataForView($id);
-
- // view setup
- $this->layout = 'amo2009'; // TODO: remove this when the entire controller is amo2009-based
- $this->set('bodyclass', 'inverse collections-page');
- $this->publish('jsAdd', array('jquery-ui/ui.core.min', 'jquery-ui/ui.tabs.min',
- 'jquery.autocomplete.pack.js'));
- $this->publish('breadcrumbs', array(
- sprintf(___('addons_home_pagetitle'), APP_PRETTYNAME) => '/',
- ___('collections_breadcrumb') => '/collections'
- ));
- }
-
- /**
- * get collection data for collection edit page (and publish it to view)
- * @param int $id collection ID
- * @return void
- * @access private
- */
- function _getCollectionDataForView($id) {
- $this->Collection->unbindModel(array('hasAndBelongsToMany'=>array('Addon')));
- $collection = $this->Collection->findById($id);
- $this->data['Collection'] = $collection;
-
- // translations
- $translations = $this->Collection->getAllTranslations($id);
- $this->publish('translations', $translations);
-
- // addons
- $addons = $this->AddonCollection->getAddonsFromCollection($id);
- $this->publish('addons', $addons);
- $addons_noscript = array();
- foreach ($addons as &$addon) {
- $addons_noscript[$addon['AddonCollection']['addon_id']] = $addon['Addon']['Translation']['name']['string'];
- }
- $this->publish('addons_noscript', $addons_noscript);
-
- // collection icon
- $this->publish('iconurl', $this->Image->getCollectionIconURL($id), false);
-
- // prepare applications
- global $app_shortnames, $app_prettynames;
- $appoptions = array();
- foreach ($app_shortnames as $sn => &$no) {
- $appoptions[$no] = $app_prettynames[$sn];
- }
- $this->publish('appoptions', $appoptions, false);
-
- // prepare collection types
- $this->publish('collection_types', array(
- Collection::COLLECTION_TYPE_NORMAL => ___('collections_type_normal'),
- Collection::COLLECTION_TYPE_AUTOPUBLISHER => ___('collections_type_autopublisher'),
- Collection::COLLECTION_TYPE_EDITORSPICK => ___('collections_type_editorspick')
- ), false);
-
- // get existing publishers and managers
- $publishers = $this->Collection->getUsers($id, array(COLLECTION_ROLE_PUBLISHER));
- $publishers_noscript = $managers_noscript = array();
- foreach ($publishers as &$p) {
- $publishers_noscript[$p['User']['id']] = $p['User']['email'];
- }
- $managers = $this->Collection->getUsers($id, array(COLLECTION_ROLE_ADMIN));
- foreach ($managers as &$m) {
- $managers_noscript[$m['User']['id']] = $m['User']['email'];
- }
- $this->publish('publishers', $publishers);
- $this->publish('publishers_noscript', $publishers_noscript);
- $this->data['Publishers']['p_onlyme'] = (int)empty($publishers);
- $this->publish('managers', $managers);
- $this->publish('managers_noscript', $managers_noscript);
- $this->data['Managers']['m_onlyme'] = (int)empty($managers);
- }
-
- /**
- * save collection data from edit page
- *
- * @param int $id Collection ID
- * @param array $rights user rights array from _getUserRights()
- * @return bool successfully saved?
- * @access private
- */
- function _saveCollectionEdit($id, $rights) {
- $disallowed_fields = array('uuid', 'access', 'subscribers',
- 'created', 'modified', 'downloads');
- if (!$rights['isadmin']) $allowed_fields[] = 'collection_type';
- $collectiondata = $this->Amo->filterFields($this->data['Collection'],
- array(), $disallowed_fields);
- $this->Collection->id = $id;
-
- list($localizedFields, $unlocalizedFields) = $this->Collection->splitLocalizedFields($collectiondata);
- // clean up whitespace
- foreach ($localizedFields as $field => &$translations) {
- foreach ($translations as $lang => &$l_string) {
- $l_string = trim($l_string);
- $this->params['form']['data']['Collection'][$field][$lang] = $l_string;
- }
- }
-
- $valid_translations = $this->Collection->validateTranslations($localizedFields);
- if ($valid_translations) {
- $this->Amo->clean($localizedFields);
- $this->Collection->saveTranslations($id, $this->params['form']['data']['Collection'], $localizedFields);
- }
-
- // handle icon removal/upload
- if (!empty($this->data['Icon']['delete'])) {
- $unlocalizedFields['icontype'] = '';
- $unlocalizedFields['icondata'] = null;
- } elseif (!empty($_FILES['icon']['name'])) {
- $iconData = $this->Developers->validateIcon($_FILES['icon']);
- if (is_array($iconData)) {
- $unlocalizedFields = array_merge($unlocalizedFields, $iconData);
- }
- }
-
- // field post-processing
- if (!isset($unlocalizedFields['listed'])) $unlocalizedFields['listed'] = 0;
- if (!empty($unlocalizedFields['nickname']))
- $unlocalizedFields['nickname'] = preg_replace(INVALID_COLLECTION_NICKNAME_CHARS,
- '_', mb_strtolower(trim($unlocalizedFields['nickname'])));
-
- if ($success = $this->Collection->save($unlocalizedFields)) {
- // save noscript data
- if ($rights['atleast_manager']) {
- // save users
- $this->_saveCollectionEditUserData($id, 'Publishers');
- $this->_saveCollectionEditUserData($id, 'Managers');
- } // at least manager
-
- // add-ons
- // remove old add-ons
- if (!empty($this->data['Addons']['delete'])) {
- foreach ($this->data['Addons']['delete'] as &$_aid) {
- $this->AddonCollection->deleteByAddonIdAndCollectionId($_aid, $id, ($rights['atleast_manager'] ? null : $user['id']));
- }
- }
- // add new add-ons
- if (!empty($this->params['form']['q'])) {
- $_aids = explode(',', $this->params['form']['q']);
- foreach ($_aids as &$_aid) {
- $_aid = trim($_aid);
- if (!empty($_aid)) {
- $_addon = $this->Addon->getAddon($_aid);
- if (!empty($_addon) && in_array($_addon['Addon']['status'], $valid_status))
- $this->Collection->addAddonToCollection($id, $user['id'], $_aid);
- }
- }
- }
- }
- return $success;
- }
-
- /**
- * save user data (managers/publishers) for collection edit
- * @param int $id collection ID
- * @param string $type "Publishers" or "Managers"
- * @return void
- * @access private
- */
- function _saveCollectionEditUserData($id, $type) {
- switch ($type) {
- case 'Publishers':
- $onlyme_fieldid = 'p_onlyme';
- $role = COLLECTION_ROLE_PUBLISHER;
- break;
- case 'Managers':
- $onlyme_fieldid = 'm_onlyme';
- $role = COLLECTION_ROLE_ADMIN;
- break;
- default:
- return;
- }
-
- if (isset($this->data[$type][$onlyme_fieldid]) && $this->data[$type][$onlyme_fieldid]) {
- // remove all existing users with this role
- $this->Collection->removeAllUsersByRole($id, $role);
- } else {
- // remove old users
- if (!empty($this->data[$type]['delete'])) {
- foreach ($this->data[$type]['delete'] as &$_pid) {
- $this->Collection->removeUser($id, $_pid);
- }
- }
- // save new users
- if (!empty($this->data[$type]['new'])) {
- $_emails = explode(',', $this->data[$type]['new']);
- foreach ($_emails as &$_em) {
- $_em = trim($_em);
- if (empty($_em)) continue;
- $_uid = $this->User->findByEmail($_em, array('id'));
- if (empty($_uid)) continue;
- $this->Collection->addUser($id, $_uid['User']['id'], $role);
- }
- }
- // don't publish them back to the view
- $this->data[$type]['new'] = '';
- }
- }
-
- /**
- * get user rights for a specific collection
- * @param array $user array from user model
- * @param int $collection_id
- * @return array of booleans ('writable', 'isadmin', 'atleast_manager',
- * 'atleast_owner', 'role')
- * @access private
- */
- function _getUserRights($user, $collection_id) {
- $writable = $this->Collection->isWritableByUser($collection_id, $user['id']);
- $isadmin = $this->SimpleAcl->actionAllowed('Admin', 'EditAnyCollection', $user);
- $role = $this->Collection->getUserRole($collection_id, $user['id']);
- $atleast_manager = ($isadmin || in_array($role, array(COLLECTION_ROLE_ADMIN, COLLECTION_ROLE_OWNER)));
- $atleast_owner = ($isadmin || $role == COLLECTION_ROLE_OWNER);
-
- $this->publish('writable', $writable, false);
- $this->publish('isadmin', $isadmin, false);
- $this->publish('atleast_manager', $atleast_manager, false);
- $this->publish('atleast_owner', $atleast_owner, false);
- $this->publish('role', $role, false);
-
- return array(
- 'writable' => $writable,
- 'isadmin' => $isadmin,
- 'atleast_manager' => $atleast_manager,
- 'atleast_owner' => $atleast_owner,
- 'role' => $role
- );
- }
-
-
- /*** Fashion Your Firefox ***/
-
+
/**
* Special "interactive collections" page for first-time users
*/
@@ -747,28 +117,28 @@ class CollectionsController extends AppController
$this->redirect('/');
exit();
}
-
+
// XXX: for accessibility (bug 462411), we use a hand-bundled accordion
// + core jquery UI file. Once jquery UI is updated to post-1.6.2rc2,
// the regular jquery UI accordion should be used (cf. jquery ui bug
// 3553, http://ui.jquery.com/bugs/ticket/3553)
$this->set('jsAdd', array('jquery-ui/jq-ui-162rc2-accordion-bundle-a11y.min.js', 'jquery-ui/jqModal.js'));
$this->set('cssAdd', array('collection-style'));
-
+
$addonIds = $this->Addon->getCategorizedAddonsFromCollection(1); // special collection ID
$addons = array();
foreach ($addonIds as $catid => $cataddons) {
$addons[$catid] = $this->Addon->getAddonList($cataddons, array('files', 'latest_version', 'list_details'));
}
$this->publish('addons', $addons);
-
+
// prepare view, then render
$this->publish('suppressHeader', true, false);
$this->publish('suppressLanguageSelector', true, false);
$this->publish('suppressCredits', true, false);
$this->pageTitle = 'Fashion Your Firefox';
}
-
+
/**
* installation dialog for collections
* @param string $method 'html' (with layout) or 'ajax' (without)
@@ -778,7 +148,7 @@ class CollectionsController extends AppController
if (!empty($_POST['addon'])) {
$addons = $this->Addon->getAddonList($_POST['addon'], array(
'compatible_apps', 'files', 'latest_version', 'list_details'));
-
+
// XXX: ugly hack allowing signed add-ons to be installed separately
// due to bug 462108 and 453545. The DB doesn't know which ones are
// signed or not so we need to hardcode them here.
@@ -795,7 +165,7 @@ class CollectionsController extends AppController
}
}
$this->publish('addons', $addons);
-
+
// fetch all platforms
$this->Platform->unbindFully();
$platforms_all = $this->Platform->findAll();
@@ -804,7 +174,7 @@ class CollectionsController extends AppController
$platforms[$pf['Platform']['id']] = $pf['Translation']['name']['string'];
}
$this->publish('platforms', $platforms);
-
+
// prepare and display view
$this->pageTitle = 'Collections' . " :: " . sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME);
$is_ajax = ($method=='ajax');
@@ -835,7 +205,7 @@ class CollectionsController extends AppController
$addons = array();
}
$this->publish('addons', $addons);
-
+
$this->set('cssAdd', array('collection-style'));
$this->publish('suppressHeader', true, false);
$this->publish('suppressLanguageSelector', true, false);
@@ -843,235 +213,4 @@ class CollectionsController extends AppController
$this->pageTitle = 'Fashion Your Firefox';
}
- /*** END Fashion Your Firefox ***/
-
-
- /*** AJAX Handlers ***/
-
- /**
- * AJAX action for looking up add-ons to add to a collection
- */
- function addonLookup() {
- global $valid_status;
-
- // Rather than change our cake parameter regex, use a normal get var
- $name = $_GET['q'];
- $this->Amo->clean($name);
-
- // search conditions
- $conditions = array(
- 'Addon.status' => $valid_status,
- 'Addon.inactive' => 0
- );
- if (mb_strlen($name) >= 4) { // fuzzy matching on long names only
- $conditions['Translation.name'] = "LIKE %{$name}%";
- } else {
- $conditions['Translation.name'] = $name;
- }
-
- $addons = $this->Addon->findAll($conditions,
- array('Addon.id', 'Addon.name'), 'Translation.name');
- if (!empty($addons)) {
- foreach ($addons as &$_addon) {
- // add icons
- $_addon['Addon']['iconpath'] = $this->Image->getAddonIconURL($_addon['Addon']['id']);
- }
- } else {
- $addons = false;
- }
-
- $this->publish('addons', $addons);
- $this->render('ajax/addon_lookup', 'ajax');
- }
-
- /**
- * central JSON dispatcher for AJAX requests
- */
- function json($action, $additional = '') {
- switch ($action) {
- case 'nickname':
- $json = $this->_checkNickname();
- break;
-
- case 'user':
- $json = $this->_handleUser($additional);
- break;
-
- case 'addon':
- $json = $this->_handleAddon($additional);
- break;
-
- default: $json = array(); break;
- }
-
- $this->publish('json', $json, false);
- $this->render('json', 'ajax');
- }
-
- /**
- * AJAX: check if collection nickname is already used
- */
- function _checkNickname() {
- $this->Amo->checkLoggedIn(); // must be logged in
- if (empty($this->params['url']['nickname'])) {
- return $this->Error->getJSONforError(sprintf(_('error_missing_argument'), 'nickname'));
- }
- $nickname = preg_replace(INVALID_COLLECTION_NICKNAME_CHARS, '_',
- mb_strtolower(trim($this->params['url']['nickname'])));
- if ($nickname != mb_strtolower($this->params['url']['nickname']))
- return array(
- 'error' => 1,
- 'error_message' => ___('collections_edit_nickname_error'),
- 'nickname' => $nickname
- );
-
- $taken = $this->Collection->isNicknameTaken($this->params['url']['nickname']);
- return array(
- 'error' => 0,
- 'nickname' => $nickname,
- 'taken' => (int)$taken
- );
- }
-
- /**
- * AJAX: Add / remove user to/from this collection's roles
- */
- function _handleUser($action) {
- if (empty($action)) return $this->Error->getJSONforError(sprintf(_('error_missing_argument'), 'action'));
- if (empty($this->params['form']['collection_id'])) return $this->Error->getJSONforError(sprintf(_('error_missing_argument'), 'collection_id'));
-
- $this->Amo->checkLoggedIn(); // must be logged in
-
- $collection_id = $this->params['form']['collection_id'];
- $role = @$this->params['form']['role'];
- $email = @$this->params['form']['email'];
- $user_id = @$this->params['form']['user_id'];
-
- $user = $this->Session->read('User');
- $rights = $this->_getUserRights($user, $collection_id);
- if (!$rights['atleast_manager']) return $this->Error->getJSONforError(___('error_access_denied'));
-
- switch ($action) {
- case 'add':
- if (empty($email)) return $this->Error->getJSONforError(sprintf(_('error_missing_argument'), 'email'));
- $roles = array('publishers' => COLLECTION_ROLE_PUBLISHER, 'managers' => COLLECTION_ROLE_ADMIN);
- if (empty($role)) return $this->Error->getJSONforError(sprintf(_('error_missing_argument'), 'role'));
-
- $newuser = $this->User->findByEmail($email, array('id'));
- if (!empty($newuser)) {
- if ($this->Collection->getUserRole($collection_id, $newuser['User']['id']) === false) {
- $this->Collection->addUser($collection_id, $newuser['User']['id'], $roles[$role]);
- return array('id' => $newuser['User']['id'], 'email' => $email);
- } else {
- return $this->Error->getJSONforError(___('error_user_exists'));
- }
- } else {
- return $this->Error->getJSONforError(___('error_user_notfound'));
- }
- break;
-
- case 'del':
- if (empty($user_id))
- return $this->Error->getJSONforError(sprintf(_('error_missing_argument'), 'user_id'));
- if ($this->Collection->removeUser($collection_id, $user_id) !== false) {
- return array('id' => $user_id);
- } else {
- return $this->Error->getJSONforError(___('error_user_notfound'));
- }
- break;
-
- default:
- return $this->Error->getJSONforError(sprintf(_('error_missing_argument'), 'action'));
- }
- }
-
- /**
- * AJAX: Add / remove add-on to/from this collection
- * @param string action one of add, del, savecomment
- * @param int collection_id (optional)
- * @param string collection_uuid (optional)
- * Either collection_id or collection_uuid must be specified, but not both.
- * @param int addon_id
- */
- function _handleAddon($action) {
- global $valid_status;
-
- if (empty($action)) return $this->Error->getJSONforError(sprintf(_('error_missing_argument'), 'action'));
- if (empty($this->params['form']['addon_id']) || !is_numeric($this->params['form']['addon_id'])) return $this->Error->getJSONforError(sprintf(_('error_missing_argument'), 'addon_id'));
- if (!empty($this->params['form']['collection_id']) && is_numeric($this->params['form']['collection_id'])) {
- $collection_id = $this->params['form']['collection_id'];
- } elseif (!empty($this->params['form']['collection_uuid']) &&
- ($collection_id = $this->Collection->getIdForUuidOrNickname($this->params['form']['collection_uuid'])) > 0) {
- // no-op
- } else {
- return $this->Error->getJSONforError(sprintf(_('error_missing_argument'), 'collection_id'));
- }
-
- $this->Amo->checkLoggedIn(); // must be logged in
-
- $addon_id = $this->params['form']['addon_id'];
-
- $user = $this->Session->read('User');
- $rights = $this->_getUserRights($user, $collection_id);
-
- if (!($rights['writable'] || $rights['isadmin'])) return $this->Error->getJSONforError(___('error_access_denied'));
-
- switch ($action) {
- case 'add':
- if ($this->AddonCollection->isAddonInCollection($addon_id, $collection_id))
- return $this->Error->getJSONforError(___('error_addon_exists'));
- $addon = $this->Addon->getAddon($addon_id);
- if (empty($addon) || !in_array($addon['Addon']['status'], $valid_status))
- return $this->Error->getJSONforError(___('error_addon_notfound'));
- if (false !== $this->Collection->addAddonToCollection($collection_id, $user['id'], $addon_id)) {
- return array(
- 'id' => $addon_id,
- 'name' => $addon['Translation']['name']['string'],
- 'iconURL' => $this->Image->getAddonIconURL($addon_id),
- 'date' => strftime(_('date'), mktime()),
- 'publisher' => $this->Html->linkUserFromModel($user)
- );
- } else {
- return $this->Error->getJSONforError(___('collection_error_saving_addon'));
- }
- break;
-
- case 'del':
- if (!$rights['isadmin'] && !$rights['atleast_manager']) {
- // publisher's own add-on?
- $res = $this->AddonCollection->deleteByAddonIdAndCollectionId($addon_id, $collection_id, $user['id']);
- } else {
- $res = $this->AddonCollection->deleteByAddonIdAndCollectionId($addon_id, $collection_id);
- }
- if ($res) {
- return array('id' => $addon_id);
- } else {
- return $this->Error->getJSONforError(___('collection_error_deleting_addon'));
- }
- break;
-
- case 'savecomment':
- if (!isset($this->params['form']['comment'])) return $this->Error->getJSONforError(sprintf(_('error_missing_argument'), 'comment'));
- $comment = strip_tags(trim($this->params['form']['comment']));
-
- $addon = $this->AddonCollection->find(array('addon_id'=>$addon_id, 'collection_id'=>$collection_id), array('user_id'));
- if (empty($addon)) return $this->Error->getJSONforError(___('error_addon_notfound'));
- if (!$rights['isadmin'] && !$rights['atleast_manager']) {
- // publisher's own add-on?
- if ($addon['AddonCollection']['user_id'] != $user['id']) return $this->Error->getJSONforError(___('error_access_denied'));
- }
- if (!$this->AddonCollection->setComment($collection_id, $addon_id, $comment)) {
- return $this->Error->getJSONforError(___('collection_error_saving_comment'));
- } else {
- return array(
- 'addon_id' => $addon_id,
- 'comment' => $comment
- );
- }
- break;
-
- default:
- return $this->Error->getJSONforError(sprintf(_('error_missing_argument'), 'action'));
- }
- }
}
diff --git a/site/app/controllers/compatibility_controller.php b/site/app/controllers/compatibility_controller.php
index fbf3cf3..9a9754f 100644
--- a/site/app/controllers/compatibility_controller.php
+++ b/site/app/controllers/compatibility_controller.php
@@ -68,7 +68,7 @@ class CompatibilityController extends AppController
$this->jsAdd = array('compatibility.js');
$this->publish('jsAdd', $this->jsAdd);
- $this->layout = 'amo2009';
+ $this->layout = 'mozilla';
$this->pageTitle = ___('compatibility_dashboard_center_header', 'Add-on Compatibility Center').' :: '.sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME);
$this->publish('expand_categories', true);
@@ -91,7 +91,6 @@ class CompatibilityController extends AppController
$data = unserialize(file_get_contents(NETAPP_STORAGE.'/compatibility-fx-'.$version.'.serialized'));
$this->publish('totals', $data['totals']);
- $this->publish('percentages', $this->_percentages($data['totals']));
$this->publish('version', $version);
$session = $this->Session->read('User');
@@ -118,7 +117,7 @@ class CompatibilityController extends AppController
if ($format == 'ajax')
$this->render('report', 'ajax');
else
- $this->render('report', 'amo2009');
+ $this->render('report', 'mozilla');
}
function developers($version = COMPAT_DEFAULT_VERSION, $format = 'html') {
@@ -175,7 +174,7 @@ class CompatibilityController extends AppController
if ($format == 'ajax')
$this->render('developers', 'ajax');
else
- $this->render('developers', 'amo2009');
+ $this->render('developers', 'mozilla');
}
function users($version = COMPAT_DEFAULT_VERSION) {
@@ -183,20 +182,6 @@ class CompatibilityController extends AppController
$this->render('users');
}
- /* Calculate compatibility percentages, making sure they add up to 100. */
- function _percentages($totals) {
- $k = array(COMPAT_OTHER, COMPAT_ALPHA, COMPAT_BETA, COMPAT_LATEST);
- $percentages = array();
-
- foreach ($k as $compat) {
- $p = $totals[$compat]['adu'] / $totals['adu95'];
- // Round to 1 decimal place.
- $percentages[$compat] = round($p * 100, 1);
- }
- // Put any over/under flow into COMPAT_LATEST, somewhat arbitrary.
- $percentages[COMPAT_LATEST] += 100 - array_sum($percentages);
- return $percentages;
- }
}
?>
diff --git a/site/app/controllers/components/amo.php b/site/app/controllers/components/amo.php
index 92ac9ac..a4c59b7 100644
--- a/site/app/controllers/components/amo.php
+++ b/site/app/controllers/components/amo.php
@@ -340,7 +340,6 @@ class AmoComponent extends Object {
$applicationModel->unbindModel(array('hasAndBelongsToMany' => array('Version'), 'hasMany' => array('Tag')));
$applications = $applicationModel->findAll('Application.supported=1', null, null, null, null, 2);
$appvids = array();
- $versions = array();
foreach ($applications as $application) {
if (!empty($application['Appversion'])) {
$appversions = array();
@@ -668,44 +667,66 @@ class AmoComponent extends Object {
* )
*/
function getNavCategories() {
- global $hybrid_categories, $app_listedtypes, $valid_status;
+ global $hybrid_categories, $app_listedtypes;
if (!empty($this->navCategories)) return $this->navCategories;
+ if(APP_ID == APP_SUGAR) {
+ $catlist = array();
+ } else
// addon type list to be added to regular categories list
- // get "Themes" category name
- if (!isset($this->controller->Addontype)) {
- loadModel('Addontype');
- $this->controller->Addontype = new Addontype();
- }
+ // @partial translation fallback, 4/23/08
+ if (_('nav_category_dicts_langpacks') != 'nav_category_dicts_langpacks') {
+ $catlist = array(
+ array('name' => _('nav_category_dicts_langpacks'),
+ 'type' => ADDON_DICT,
+ 'cat' => 0,
+ 'weight' => 0),
+ array('name' => _('nav_category_themes'),
+ 'type' => ADDON_THEME,
+ 'cat' => 0,
+ 'weight' => 0)
+ );
+ } else {
+ // get "Themes" category name
+ if (!isset($this->controller->Addontype)) {
+ loadModel('Addontype');
+ $this->controller->Addontype = new Addontype();
+ }
- $names = $this->controller->Addontype->getNames();
- $_themes_name = $names[ADDON_THEME];
-
- $catlist = array(
- array('name' => ___('langtools_header_dicts_and_langpacks'),
- 'type' => ADDON_DICT,
- 'cat' => 0,
- 'weight' => 0),
- array('name' => $_themes_name,
- 'type' => ADDON_THEME,
- 'cat' => 0,
- 'weight' => 0)
- );
+ $_themes_name = $this->controller->Addontype->getName(ADDON_THEME);
+
+ $catlist = array(
+ array('name' => _('langtools_header_dicts_and_langpacks'),
+ 'type' => ADDON_DICT,
+ 'cat' => 0,
+ 'weight' => 0),
+ array('name' => $_themes_name,
+ 'type' => ADDON_THEME,
+ 'cat' => 0,
+ 'weight' => 0)
+ );
+ }
// add plugins where appropriate
+ // @partial translation fallback, 4/27/08
if (in_array(ADDON_PLUGIN, $app_listedtypes[APP_ID])) {
- $catlist[] = array(
- 'name' => ___('addons_plugins_pagetitle'),
- 'type' => ADDON_PLUGIN,
- 'cat' => 0,
- 'weight' => 0,
- 'count' => COUNT_ADDON_PLUGIN,
- );
+ if (_('nav_category_plugins') != 'nav_category_plugins') {
+ $catlist[] = array(
+ 'name' => _('nav_category_plugins'),
+ 'type' => ADDON_PLUGIN,
+ 'cat' => 0,
+ 'weight' => 0
+ );
+ } else {
+ $catlist[] = array(
+ 'name' => _('addons_plugins_pagetitle'),
+ 'type' => ADDON_PLUGIN,
+ 'cat' => 0,
+ 'weight' => 0
+ );
+ }
}
-
- // we are sugar
- $catlist = array();
// create two sort arrays that we can use with array_multisort later
$_weights = array();
@@ -716,7 +737,7 @@ class AmoComponent extends Object {
}
// add regular categories to list
- $tags = $this->getTags();
+ $tags = $this->getTags(APP_ID, $app_listedtypes[APP_SUGAR]);
foreach ($tags as $_tag) {
/* support hybrid categories */
if (isset($hybrid_categories[APP_ID][$_tag['Tag']['id']])) {
@@ -729,26 +750,23 @@ class AmoComponent extends Object {
$_name = $_tag['Translation']['name']['string'];
$_weight = $_tag['Tag']['weight'];
- $_count = $_tag['Tag']['count'];
// add item to results array
$catlist[] = array(
'name' => $_name,
'type' => $_type,
'cat' => $_cat,
- 'weight' => $_weight,
- 'count' => $_count
+ 'weight' => $_weight
);
// add item to sort arrays too
$_names[] = strtolower($_name);
$_weights[] = $_weight;
}
-
+
// sort results array by weight and name, then return.
array_multisort($_weights, SORT_ASC, SORT_NUMERIC,
$_names, SORT_ASC, SORT_STRING, $catlist);
- // TODO: Use memcache here?
$this->navCategories = $catlist; // cache result for subsequent calls
return $catlist;
}
diff --git a/site/app/controllers/components/audit.php b/site/app/controllers/components/audit.php
index 2a2d0b3..aad6936 100644
--- a/site/app/controllers/components/audit.php
+++ b/site/app/controllers/components/audit.php
@@ -76,11 +76,11 @@ class AuditComponent extends Object {
$addonInfo = $this->controller->Addon->findById($log['Eventlog']['changed_id'], null, null, -1);
$addon = $this->link($addonInfo['Translation']['name']['string'], '/admin/addons/status/'.$log['Eventlog']['changed_id']);
- $entry = sprintf(___('audit_addon_status'), $user, $addon, $status);
+ $entry = "{$user} changed the status of {$addon} to {$status}";
break;
case 'file_recalchash':
- $entry = sprintf(___('audit_file_recalchash'), $user, $log['Eventlog']['changed_id']);
+ $entry = "{$user} recalculated the hash for file {$log['Eventlog']['changed_id']}";
break;
case 'application_create':
@@ -89,10 +89,10 @@ class AuditComponent extends Object {
$application = $this->link($applicationInfo['Translation']['name']['string'], '/admin/applications');
if ($log['Eventlog']['action'] == 'application_create') {
- $entry = sprintf(___('audit_application_create'), $user, $application);
+ $entry = "{$user} created application {$application}";
}
elseif ($log['Eventlog']['action'] == 'application_edit') {
- $entry = sprintf(___('audit_application_edit'), $user, $application);
+ $entry = "{$user} edited application {$application}";
}
break;
@@ -102,10 +102,10 @@ class AuditComponent extends Object {
$application = $this->link($applicationInfo['Translation']['name']['string'], '/admin/applications');
if ($log['Eventlog']['action'] == 'appversion_create') {
- $entry = sprintf(___('audit_appversion_create'), $user, $log['Eventlog']['added'], $application);
+ $entry = "{$user} created version {$log['Eventlog']['added']} for {$application}";
}
elseif ($log['Eventlog']['action'] == 'appversion_delete') {
- $entry = sprintf(___('audit_appversion_delete'), $user, $log['Eventlog']['removed'], $application);
+ $entry = "{$user} deleted version {$log['Eventlog']['removed']} for {$application}";
}
break;
@@ -115,15 +115,15 @@ class AuditComponent extends Object {
$tag = $this->link($tagInfo['Translation']['name']['string'], '/admin/tags');
if ($log['Eventlog']['action'] == 'tag_create') {
- $entry = sprintf(___('audit_tag_create'), $user, $tag);
+ $entry = "{$user} created tag {$tag}";
}
elseif ($log['Eventlog']['action'] == 'tag_edit') {
- $entry = sprintf(___('audit_tag_edit'), $user, $tag);
+ $entry = "{$user} edited category {$tag}";
}
break;
case 'tag_delete':
- $entry = sprintf(___('audit_tag_delete'), $user, $log['Eventlog']['removed'], $log['Eventlog']['changed_id']);
+ $entry = "{$user} deleted category {$log['Eventlog']['removed']} (ID {$log['Eventlog']['changed_id']})";
break;
case 'platform_create':
@@ -132,25 +132,25 @@ class AuditComponent extends Object {
$platform = $this->link($platformInfo['Translation']['name']['string'], '/admin/platforms');
if ($log['Eventlog']['action'] == 'platform_create') {
- $entry = sprintf(___('audit_platform_create'), $user, $platform);
+ $entry = "{$user} created platform {$platform}";
}
elseif ($log['Eventlog']['action'] == 'platform_edit') {
- $entry = sprintf(___('audit_platform_edit'), $user, $platform);
+ $entry = "{$user} edited platform {$platform}";
}
break;
case 'platform_delete':
- $entry = sprintf(___('audit_platform_delete'), $user, $log['Eventlog']['removed'], $log['Eventlog']['changed_id']);
+ $entry = "{$user} deleted platform {$log['Eventlog']['removed']} (ID {$log['Eventlog']['changed_id']})";
break;
case 'feature_add':
case 'feature_edit':
$featureInfo = $this->controller->Feature->findById($log['Eventlog']['changed_id'], null, null, -1);
- $entry = sprintf(___('audit_feature_edit'), $user, $featureInfo['Feature']['locale']);
+ $entry = "{$user} changed a feature for {$featureInfo['Feature']['locale']} locale";
break;
case 'feature_remove':
- $entry = sprintf(___('audit_admin_feature_remove'), $user, $log['Eventlog']['removed']);
+ $entry = "{$user} removed feature {$log['Eventlog']['removed']}";
break;
case 'group_create':
@@ -159,15 +159,15 @@ class AuditComponent extends Object {
$group = $this->link($groupInfo['Group']['name'], '/admin/groups');
if ($log['Eventlog']['action'] == 'group_create') {
- $entry = sprintf(___('audit_group_create'), $user, $group);
+ $entry = "{$user} created group {$group}";
}
elseif ($log['Eventlog']['action'] == 'group_edit') {
- $entry = sprintf(___('audit_group_edit'), $user, $group);
+ $entry = "{$user} edited group {$group}";
}
break;
case 'group_delete':
- $entry = sprintf(___('audit_group_delete'), $user, $log['Eventlog']['removed'], $log['Eventlog']['changed_id']);
+ $entry = "{$user} deleted group {$log['Eventlog']['removed']} (ID {$log['Eventlog']['changed_id']})";
break;
case 'group_addmember':
@@ -179,13 +179,13 @@ class AuditComponent extends Object {
$memberInfo = $this->controller->User->findById($log['Eventlog']['added'], null, null, -1);
$member = $this->link($memberInfo['User']['firstname'].' '.$memberInfo['User']['lastname'], '/admin/users/'.$log['Eventlog']['added']);
- $entry = sprintf(___('audit_group_addmember'), $user, $member, $group);
+ $entry = "{$user} added {$member} to group {$group}";
}
elseif ($log['Eventlog']['action'] == 'group_removemember') {
$memberInfo = $this->controller->User->findById($log['Eventlog']['removed'], null, null, -1);
$member = $this->link($memberInfo['User']['firstname'].' '.$memberInfo['User']['lastname'], '/admin/users/'.$log['Eventlog']['removed']);
- $entry = sprintf(___('audit_group_removemember'), $user, $member, $group);
+ $entry = "{$user} removed {$member} from group {$group}";
}
break;
@@ -195,30 +195,30 @@ class AuditComponent extends Object {
$response = $this->link($responseInfo['Translation']['name']['string'], '/admin/responses');
if ($log['Eventlog']['action'] == 'response_create') {
- $entry = sprintf(___('audit_response_create'), $user, $response);
+ $entry = "{$user} created response {$response}";
}
elseif ($log['Eventlog']['action'] == 'response_edit') {
- $entry = sprintf(___('audit_response_edit'), $user, $response);
+ $entry = "{$user} edited response {$response}";
}
break;
case 'response_delete':
- $entry = sprintf(___('audit_response_delete'), $user, $log['Eventlog']['removed'], $log['Eventlog']['changed_id']);
+ $entry = "{$user} deleted response {$log['Eventlog']['removed']} (ID {$log['Eventlog']['changed_id']})";
break;
case 'config':
- $entry = sprintf(___('audit_config'), $user, $log['Eventlog']['field'], $log['Eventlog']['removed'], $log['Eventlog']['added']);
+ $entry = "{$user} changed config '{$log['Eventlog']['field']}' from '{$log['Eventlog']['removed']}' to '{$log['Eventlog']['added']}'";
break;
case 'user_edit':
$userInfo = $this->controller->User->findById($log['Eventlog']['changed_id'], null, null, -1);
$userLink = $this->link($userInfo['User']['firstname'].' '.$userInfo['User']['lastname'], '/admin/users/'.$log['Eventlog']['changed_id']);
- $entry = sprintf(___('audit_user_edit'), $user, $userLink);
+ $entry = "{$user} edited {$userLink}'s user information";
break;
default:
- $entry = sprintf(___('audit_admin_default'), $user, $log['Eventlog']['action'], $log['Eventlog']['changed_id']);
+ $entry = "{$user} committed unknown admin action {$log['Eventlog']['action']} to ID {$log['Eventlog']['changed_id']}";
break;
}
break;
@@ -228,34 +228,34 @@ class AuditComponent extends Object {
switch ($log['Eventlog']['action']) {
case 'feature_add':
$addonLink = $this->linkTitle($log['Eventlog']['added'], '/addon/');
- $entry = sprintf(___('audit_feature_add'), $user, $addonLink);
+ $entry = "{$user} added addon {$addonLink} to feature list";
break;
case 'feature_remove':
$addonLink = $this->linkTitle($log['Eventlog']['removed'], '/addon/');
- $entry = sprintf(___('audit_editor_feature_remove'), $user, $addonLink);
+ $entry = "{$user} removed addon {$addonLink} from feature list";
break;
case 'feature_locale_change':
$addonLink = $this->linkTitle($log['Eventlog']['changed_id'], '/addon/');
- $entry = sprintf(___('audit_feature_locale_change'), $user, $addonLink);
+ $entry = "{$user} changed locales for addon {$addonLink} on feature list";
break;
case 'review_approve':
- $entry = sprintf(___('audit_review_approve'), $user, $log['Eventlog']['changed_id']);
+ $entry = "{$user} approved review {$log['Eventlog']['changed_id']}";
break;
case 'review_delete':
if ($this->controller->SimpleAcl->actionAllowed('Admin', 'logs', $this->controller->Session->read('User'))) {
- $entry = sprintf(___('audit_review_delete'), $user, $this->link($log['Eventlog']['changed_id'], "/admin/logs/{$log['Eventlog']['id']}"));
+ $entry = "{$user} deleted review ".$this->link($log['Eventlog']['changed_id'], "/admin/logs/{$log['Eventlog']['id']}");
}
else {
- $entry = sprintf(___('audit_review_delete'), $user, $log['Eventlog']['changed_id']);
+ $entry = "{$user} deleted review {$log['Eventlog']['changed_id']}";
}
break;
default:
- $entry = sprintf(___('audit_editor_default'), $user, $log['Eventlog']['action'], $log['Eventlog']['changed_id']);
+ $entry = "{$user} committed unknown editor action {$log['Eventlog']['action']} to ID {$log['Eventlog']['changed_id']}";
break;
}
break;
@@ -263,21 +263,21 @@ class AuditComponent extends Object {
case 'l10n':
switch ($log['Eventlog']['action']) {
case 'update_applications':
- $entry = sprintf(___('audit_update_applications'), $user, $this->linkTitle($log['Eventlog']['notes'], "/localizers/applications/?userlang="));
+ $entry = "{$user} updated application translations for ".$this->linkTitle($log['Eventlog']['notes'], "/localizers/applications/?userlang=");
break;
case 'update_tags':
- $entry = sprintf(___('audit_update_tags'), $user, $this->linkTitle($log['Eventlog']['notes'], "/localizers/tags/?userlang="));
+ $entry = "{$user} updated category translations for ".$this->linkTitle($log['Eventlog']['notes'], "/localizers/tags/?userlang=");
break;
case 'update_platforms':
- $entry = sprintf(___('audit_update_platforms'), $user, $this->linkTitle($log['Eventlog']['notes'], "/localizers/platforms/?userlang="));
+ $entry = "{$user} updated platform translations for ".$this->linkTitle($log['Eventlog']['notes'], "/localizers/platforms/?userlang=");
break;
case 'update_blog':
- $entry = sprintf(___('audit_update_blog'), $user, $this->linkTitle($log['Eventlog']['notes'], "/localizers/platforms/?userlang="));
+ $entry = "{$user} updated blog post translations for ".$this->linkTitle($log['Eventlog']['notes'], "/localizers/platforms/?userlang=");
break;
default:
- $entry = sprintf(___('audit_l10n_default'), $user, $log['Eventlog']['action'], $log['Eventlog']['notes']);
+ $entry = "{$user} committed unknown action {$log['Eventlog']['action']} for <u>{$log['Eventlog']['notes']}</u>";
break;
}
break;
@@ -285,22 +285,22 @@ class AuditComponent extends Object {
case 'security':
switch ($log['Eventlog']['action']) {
case 'reauthentication_failure':
- $entry = sprintf(___('audit_reauthentication_failure'), $user, $log['Eventlog']['notes']);
+ $entry = "{$user} failed to re-authenticate to access {$log['Eventlog']['notes']}.";
break;
case 'modify_locked_group':
$groupInfo = $this->controller->Group->findById($log['Eventlog']['changed_id'], null, null, -1);
$group = $this->link($groupInfo['Group']['name'], '/admin/groups');
- $entry = sprintf(___('audit_modify_locked_group'), $user, $group);
+ $entry = "{$user} attempted to modify locked group {$group}";
break;
case 'modify_other_locale':
- $entry = sprintf(___('audit_modify_other_locale'), $user, $log['Eventlog']['notes']);
+ $entry = "{$user} attempted to modify translations in {$log['Eventlog']['notes']} without permission";
break;
default:
- $entry = sprintf(___('audit_security_default'), $user, $log['Eventlog']['action'], $log['Eventlog']['changed_id']);
+ $entry = "{$user} committed unknown security action {$log['Eventlog']['action']} to ID {$log['Eventlog']['changed_id']}";
break;
}
break;
@@ -310,7 +310,7 @@ class AuditComponent extends Object {
case 'group_associated':
$groupInfo = $this->controller->Group->findById($log['Eventlog']['changed_id'], null, null, -1);
$group = $this->link($groupInfo['Group']['name'], '/admin/groups');
- $entry = sprintf(___('audit_group_associated'), $user, $group);
+ $entry = "{$user} associated themselves with {$group}";
break;
}
break;
diff --git a/site/app/controllers/components/developers.php b/site/app/controllers/components/developers.php
index ceb24f8..35becf1 100644
--- a/site/app/controllers/components/developers.php
+++ b/site/app/controllers/components/developers.php
@@ -231,11 +231,6 @@ class DevelopersComponent extends Object {
function detectAddontype($file) {
$extension = substr($file['name'], strrpos($file['name'], '.'));
switch ($extension) {
- case '.xo':
- case '.xol':
- return ADDON_EXTENSION;
- break;
-
case '.xpi':
// Dictionaries have a .dic file in the dictionaries directory
$zip = new Archive_Zip($file['tmp_name']);
@@ -257,6 +252,14 @@ class DevelopersComponent extends Object {
case '.xml':
return ADDON_SEARCH;
break;
+
+ case '.xo':
+ return ADDON_ACTIVITY;
+ break;
+
+ case '.xol':
+ return ADDON_CONTENT;
+ break;
default:
return 0;
@@ -476,7 +479,9 @@ class DevelopersComponent extends Object {
*/
function getAllowedExtensions($addontype) {
switch ($addontype) {
- case ADDON_EXTENSION: $allowed = array('.xo', '.xol');
+ case ADDON_ACTIVITY: $allowed = array('.xo');
+ break;
+ case ADDON_CONTENT: $allowed = array('.xol');
break;
case ADDON_EXTENSION: $allowed = array('.xpi');
break;
@@ -1166,6 +1171,11 @@ class DevelopersComponent extends Object {
ADDON_DICT => $this->controller->Addontype->getName(ADDON_DICT),
ADDON_LPAPP => $this->controller->Addontype->getName(ADDON_LPAPP)
);
+
+ global $app_listedtypes;
+ foreach ($app_listedtypes[APP_SUGAR] as $type) {
+ $addontypes[$type] = $this->controller->Addontype->getName($type);
+ }
if ($autoDetect == true) {
$addontypes[0] = _('devcp_additem_addontype_autodetect');
@@ -1179,81 +1189,5 @@ class DevelopersComponent extends Object {
return $addontypes;
}
-
- function getLicenses($version_id=null) {
- if ($version_id != null) {
- $version = $this->controller->Version->findById($version_id);
- $version = $version['Version'];
- $license = $this->controller->License->findById($version['license_id']);
- }
-
- // Add 'Please Choose...' only if no license has been selected.
- if (!isset($version['license_id'])) {
- $licenses['null'] = array(
- 'name' => ___('devcp_uploader_please_choose'),
- 'selected' => True);
- }
-
- // Grab all the pre-approved licenses.
- foreach ($this->controller->License->getNames() as $num => $builtin) {
- $licenses['builtin_'.$num] = array(
- 'name' => $builtin,
- 'selected' => isset($license) && (string)$num === $license['License']['name']);
- }
-
- // The trans array holds translations for all the custom licenses we'll
- // be displaying. `other` starts off empty, for creating new licenses.
- $trans['other']['text']['en-US'] = '';
-
- if ($version_id != null) {
- // Find all the custom licenses in use by this add-on.
- $q = "SELECT Version.version, Version.license_id
- FROM versions AS Version INNER JOIN licenses AS License
- ON Version.license_id = License.id
- WHERE Version.addon_id = {$version['addon_id']}
- AND Version.license_id IS NOT NULL
- AND License.name = -1
- GROUP BY License.id
- ORDER BY Version.id DESC";
- foreach ($this->controller->Version->execute($q) as $existing) {
- $existing = $existing['Version'];
- $t = ___('devcp_license_existing');
- $val = 'existing_'.$existing['license_id'];
- $licenses[$val] = array(
- 'name' => sprintf($t, $version['addon_id'], $existing['version']),
- 'selected' => $existing['license_id'] == $version['license_id']);
- $trans[$val] = $this->controller->License->getAllTranslations($existing['license_id']);
- }
- }
-
- $licenses['other'] = array('name' => ___('devcp_uploader_option_other'),
- 'selected' => False);
- return array($licenses, $trans);
- }
-
- function saveLicense($licenseData, $text, $params) {
- $License = $this->controller->License;
- if ($licenseData['name'] != 'null') {
- $license = $licenseData['name'];
- // If the license is pre-approved, we prefixed the id with builtin_.
- if (preg_match('/^builtin_(\d+)$/', $license, $matches)) {
- $license_id = $License->getBuiltin($matches[1]);
- } else if ($license == 'other' ||
- preg_match('/^existing_(\d+)$/', $license, $matches)) {
- // If it's 'other', we need to create a new license.
- if ($license == 'other') {
- $data['License']['name'] = -1;
- $License->save($data);
- $license_id = $License->getLastInsertId();
- } else {
- $license_id = $matches[1];
- }
- // Save any changed translation text.
- $localized['text'] = $text;
- $License->saveTranslations($license_id, $params, $localized);
- }
- return $license_id;
- }
- }
}
?>
diff --git a/site/app/controllers/components/editors.php b/site/app/controllers/components/editors.php
index 0576751..f7b761f 100644
--- a/site/app/controllers/components/editors.php
+++ b/site/app/controllers/components/editors.php
@@ -123,9 +123,9 @@ class EditorsComponent extends Object {
$authors[] = $user['email'];
}
}
-
- $releasenotes = $this->controller->Version->findById($version['Version']['id'], array('Version.releasenotes'), null, -1);
+ $releasenotes = $this->controller->Version->findById($version['Version']['id'], array('Version.releasenotes'), null, -1);
+
$emailInfo = array('name' => $addon['Translation']['name']['string'],
'id' => $this->controller->Addon->id,
'reviewer' => $session['firstname'].' '.$session['lastname'],
@@ -136,7 +136,7 @@ class EditorsComponent extends Object {
);
$this->controller->set('info', $emailInfo);
-
+
if ($data['Approval']['ActionField'] == 'public') {
if (SITE_RELEASE_EMAIL) {
$this->controller->Email->template = 'email/aslo/release';
@@ -145,7 +145,7 @@ class EditorsComponent extends Object {
$this->controller->Email->send(false, SITE_RELEASE_EMAIL);
}
}
-
+
if ($data['Approval']['ActionField'] != 'superreview') {
$this->controller->Email->template = 'email/nominated/'.$data['Approval']['ActionField'];
$this->controller->Email->to = $emailInfo['email'];
@@ -281,7 +281,7 @@ class EditorsComponent extends Object {
'releasenotes' => $releasenotes[0]['releasenotes']
);
$this->controller->set('info', $emailInfo);
-
+
if ($data['Approval']['ActionField'] == 'public') {
if (SITE_RELEASE_EMAIL) {
$this->controller->Email->template = 'email/aslo/release';
@@ -290,7 +290,7 @@ class EditorsComponent extends Object {
$this->controller->Email->send(false, SITE_RELEASE_EMAIL);
}
}
-
+
if ($data['Approval']['ActionField'] != 'superreview') {
$this->controller->Email->template = 'email/pending/'.$data['Approval']['ActionField'];
$this->controller->Email->to = $emailInfo['email'];
@@ -366,20 +366,22 @@ class EditorsComponent extends Object {
function redirectByQueueRank($listtype, $rank) {
switch($listtype) {
case 'nominated':
+ $addon = $this->controller->Addon->findAll(array('Addon.status' => STATUS_NOMINATED),
+ array('Addon.id'), null, 1, $rank);
+ if (!empty($addon)) {
+ $addon = $this->controller->Addon->getAddon($addon[0]['Addon']['id'], array('latest_version'));
+ if (!empty($addon['Version'])) {
+ $this->controller->redirect("/editors/review/{$addon['Version'][0]['id']}?num={$rank}");
+ return;
+ }
+ }
+ break;
+
case 'pending':
- $rank = intval($rank);
- $offset = ($rank > 0) ? $rank - 1 : 0;
- $sql = $this->buildQueueFilterQuery($listtype);
- $queue_sql = "SELECT `Version`.`id`
- {$sql['FROM']}
- {$sql['JOIN']}
- {$sql['WHERE']}
- {$sql['ORDER']}
- LIMIT 1 OFFSET {$offset}";
-
- if ($result = $this->controller->Addon->query($queue_sql)) {
- $review_id = $result[0]['Version']['id'];
- $this->controller->redirect("/editors/review/{$review_id}?num={$rank}");
+ $file = $this->controller->File->findAll(array('File.status'=>STATUS_PENDING),
+ array('File.version_id'), null, 1, $rank);
+ if (!empty($file)) {
+ $this->controller->redirect("/editors/review/{$file[0]['File']['version_id']}?num={$rank}");
return;
}
break;
@@ -489,361 +491,6 @@ class EditorsComponent extends Object {
$this->controller->Email->subject = sprintf('[RELEASE] %s-%s', $emailInfo['name'], $emailInfo['version']);
$this->controller->Email->send(false, SITE_RELEASE_EMAIL);
}
-
- }
-
- /**
- * Determine if the specified queue is filterable
- * Queues currently filterable are: 'nominated' and 'pending'
- * @param string $queue name of queue
- * @return bool
- */
- function isFilterableQueue($queue) {
- return in_array($queue, array('pending', 'nominated'));
- }
-
- /**
- * Build query components for filtering the specified queue
- * Returns empty array for unfilterable queues
- * @param string $queue name of queue
- * @return array array('FROM'=>string, 'JOIN'=>string, 'WHERE'=>string, 'ORDER'=>string)
- * @TODO: for cake >=1.2, return compatible 'joins' and 'conditions' arrays
- */
- function buildQueueFilterQuery($queue='pending') {
- if (!$this->isFilterableQueue($queue)) {
- return array();
- }
-
- // Setup query components
- $base_components = $this->baseQueueFilterQuery($queue);
- $from = $base_components['FROM'];
- $joins = $base_components['JOIN'];
- $where = $base_components['WHERE'];
- $order = 'ORDER BY';
-
- // Fetch and apply filter
- if ($filter = $this->getQueueFilter($queue)) {
- $this->controller->Amo->clean($filter, false);
-
- if (isset($filter['AddonOrAuthor']) && strlen($filter['AddonOrAuthor']) > 0) {
- // search addons.name (localized), addons.supportemail (localized) and users.email
- $where .= "\nAND (`Version`.`addon_id` IN(
- SELECT `a`.`id` FROM `addons` AS `a`
- LEFT JOIN `translations` AS `ntr_l` ON
- (`ntr_l`.`id`=`a`.`name` AND `ntr_l`.`locale`='".LANG."')
- LEFT JOIN `translations` AS `ntr_en` ON
- (`ntr_en`.`id`=`a`.`name` AND `ntr_en`.`locale`=`a`.`defaultlocale`)
- LEFT JOIN `translations` AS `etr_l` ON
- (`etr_l`.`id`=`a`.`supportemail` AND `etr_l`.`locale`='".LANG."')
- LEFT JOIN `translations` AS `etr_en` ON
- (`etr_en`.`id`=`a`.`supportemail` AND `etr_en`.`locale`=`a`.`defaultlocale`)
- WHERE
- IFNULL(`ntr_l`.`localized_string`, `ntr_en`.`localized_string`)
- LIKE '%{$filter['AddonOrAuthor']}%'
- OR IFNULL(`etr_l`.`localized_string`, `etr_en`.`localized_string`)
- LIKE '%{$filter['AddonOrAuthor']}%'
-
- ) OR `Version`.`addon_id` IN(
- SELECT `a`.`id` FROM `addons` AS `a`
- LEFT JOIN `addons_users` AS `au` ON (`a`.`id`=`au`.`addon_id`)
- LEFT JOIN `users` AS `u` ON (`au`.`user_id`=`u`.`id`)
- WHERE
- `au`.`role` IN(".AUTHOR_ROLE_ADMINOWNER.","
- .AUTHOR_ROLE_ADMIN.","
- .AUTHOR_ROLE_OWNER.","
- .AUTHOR_ROLE_DEV.")
- AND `u`.`email` LIKE '%{$filter['AddonOrAuthor']}%'
- ))";
- }
-
- if (!empty($filter['Application'])) {
- $joins .= "\nLEFT JOIN `applications_versions`
- ON (`Version`.`id`=`applications_versions`.`version_id`)";
- $where .= "\nAND (
- `applications_versions`.`application_id`='{$filter['Application']}')";
-
- if (!empty($filter['MaxVersion'])) {
- $where .= "\nAND (`applications_versions`.`max`='{$filter['MaxVersion']}')";
- }
- }
-
- if (!empty($filter['SubmissionAge'])) {
- $age = $filter['SubmissionAge'];
- $age_op = '='; // exact match by default
-
- if (substr($age, -1) == '+') {
- // values like '10+' magically turn into a '>=10' comparison
- $age_op = '>=';
- $age = substr($age, 0, -1);
- } elseif ($age === '1') {
- // make '1 day' include less than 1 as well
- $age_op = '<=';
- }
-
- if ($queue == 'pending') {
- $where .= "\nAND (TIMESTAMPDIFF(DAY, `Version`.`created`, NOW()){$age_op}'{$age}')";
- } elseif ($queue == 'nominated') {
- $where .= "\nAND (TIMESTAMPDIFF(DAY, `Addon`.`nominationdate`, NOW()){$age_op}'{$age}')";
- }
- }
-
- if (!empty($filter['Addontype'])) {
- if (is_array($filter['Addontype'])) {
- $filter_vals = $filter['Addontype'];
- } else {
- $filter_vals = array($filter['Addontype']);
- }
-
- $where .= "\nAND (`Addon`.`addontype_id` IN('"
- . implode("','", $filter_vals) ."'))";
- }
-
- if (!empty($filter['Platform'])) {
- if (is_array($filter['Platform'])) {
- $filter_vals = $filter['Platform'];
- } else {
- $filter_vals = array($filter['Platform']);
- }
-
- // only available to pending queue for now
- if ($queue == 'pending') {
- $where .= "\nAND (`File`.`platform_id` IN('"
- . implode("','", $filter_vals) ."'))";
- }
- }
- }
- //End apply filter
-
- // Sorting
- $theSort = $this->getQueueSort($queue);
- switch ($theSort['sortby']) {
- case 'name':
- $joins .= "\nLEFT JOIN `translations` AS `tr_l` ON
- (`tr_l`.`id` = `Addon`.`name` AND `tr_l`.`locale` = '".LANG."')"
- ."\nLEFT JOIN `translations` AS `tr_en` ON
- (`tr_en`.`id` = `Addon`.`name` AND `tr_en`.`locale` = `Addon`.`defaultlocale`)";
- $order .= ' IFNULL(tr_l.localized_string, tr_en.localized_string)';
- $order .= strtoupper($theSort['direction'] == 'DESC') ? ' DESC' : ' ASC';
- break;
-
- case 'type':
- $joins .= "\nLEFT JOIN addontypes AS `Addontype` ON
- (`Addon`.`addontype_id`=`Addontype`.`id`)"
- ."\nLEFT JOIN translations AS `tr_l` ON
- (`tr_l`.`id` = `Addontype`.`name` AND `tr_l`.`locale` = '".LANG."')"
- ."\nLEFT JOIN translations AS tr_en ON
- (`tr_en`.`id` = `Addontype`.`name` AND `tr_en`.`locale` = 'en-US')";
- $order .= ' IFNULL(`tr_l`.`localized_string`, `tr_en`.`localized_string`)';
- $order .= strtoupper($theSort['direction'] == 'DESC') ? ' DESC' : ' ASC';
- // secondary sort by age
- if ($queue == 'pending') {
- $order .= ', `Version`.`created` ASC';
- } else {
- $order .= ', `Addon`.`nominationdate` ASC';
- }
- break;
-
- case 'age':
- default:
- if ($queue == 'pending') {
- $order .= ' `Version`.`created`';
- } else {
- $order .= ' `Addon`.`nominationdate`';
- }
- $order .= strtoupper($theSort['direction'] == 'DESC') ? ' DESC' : ' ASC';
- break;
- }
-
- return array('FROM'=>$from, 'JOIN'=>$joins, 'WHERE'=>$where, 'ORDER'=>$order);
- }
-
- /**
- * Return base query components for filtering the specified queue
- * Returns empty array for unfilterable queues
- * @param string $queue name of queue
- * @return array array('FROM'=>string, 'JOIN'=>string, 'WHERE'=>string)
- * @TODO: for cake >=1.2, return compatible 'joins' and 'conditions' arrays
- */
- function baseQueueFilterQuery($queue='pending') {
- if (!$this->isFilterableQueue($queue)) {
- return array();
- }
-
- // Setup query components
- if ($queue == 'pending') {
- $from = "FROM `files` AS `File`";
- $joins = "LEFT JOIN `versions` AS `Version` ON (`File`.`version_id`=`Version`.`id`)";
- $joins .= "\nINNER JOIN `addons` AS `Addon` ON (`Version`.`addon_id`=`Addon`.`id`)";
- $where = "WHERE `File`.`status`='".STATUS_PENDING."'";
-
- } elseif ($queue == 'nominated') {
- $from = "FROM `addons` AS `Addon`";
- $joins = "INNER JOIN `versions` AS `Version` ON (`Addon`.`id`=`Version`.`addon_id`)";
- $where = "WHERE `Addon`.`status`='".STATUS_NOMINATED."'";
-
- // This makes sure we get only the most recent version
- // "Find the version where no other version exists for the same addon and a greater creation date"
- // http://stackoverflow.com/questions/157459/problem-joining-on-the-highest-value-in-mysql-table
- $joins .= "\nLEFT JOIN `versions` AS `v2` ON (
- `Version`.`addon_id`=`v2`.`addon_id` AND
- `Version`.`created`<`v2`.`created`)";
- $where .= "\nAND (`v2`.`id` IS NULL)";
- }
-
- return array('FROM'=>$from, 'JOIN'=>$joins, 'WHERE'=>$where);
- }
-
- /**
- * Get the active filter for the specified queue
- * @param string $queue name of queue
- * @return array filter array or empty array if none exists
- */
- function getQueueFilter($queue) {
- if (!$this->isFilterableQueue($queue)) {
- return array();
- }
-
- $filter = array();
- $queue_filters = $this->controller->Session->read('editor_queue_filters');
- if (isset($queue_filters[$queue])) {
- $filter = $queue_filters[$queue];
- }
- return $filter;
- }
-
- /**
- * Set the active filter for the specified queue
- * Only known fields are saved into the filter
- * @param string $queue name of queue
- * @return array empty array, or valid saved filter
- */
- function setQueueFilter($queue, $new_filter) {
- if (!$this->isFilterableQueue($queue)) {
- return array();
- }
-
- // known filter fields
- $filter_fields = array('Addontype', 'Application', 'MaxVersion',
- 'Platform', 'SubmissionAge', 'AddonOrAuthor');
- $filter = array();
-
- if (is_array($new_filter)) {
- foreach ($new_filter as $k => $val) {
- // only save known filter fields
- if (!empty($val) && in_array($k, $filter_fields)) {
- $filter[$k] = $val;
- }
- }
- }
-
- // get or create array of filters
- $queue_filters = $this->controller->Session->read('editor_queue_filters');
- if (!is_array($queue_filters)) {
- $queue_filters = array();
- }
-
- if ($filter) {
- // update filter
- $queue_filters[$queue] = $filter;
- } else {
- // clear filter
- unset($queue_filters[$queue]);
- }
-
- // save all filters
- $this->controller->Session->write('editor_queue_filters', $queue_filters);
-
- return $filter;
- }
-
- /**
- * Determine if the specified queue is sortable
- * @param string $queue name of queue
- * @return bool
- */
- function isSortableQueue($queue) {
- return in_array($queue, array('pending', 'nominated'));
- }
-
- /**
- * Get current sort order parameters for specified queue
- * @param string $queue name of queue
- * @param string $default return default filter instead of saved - defaults to false
- * @return array
- */
- function getQueueSort($queue, $default=false) {
- if (!$this->isSortableQueue($queue)) {
- return array();
- }
-
- $defaults = array(
- 'pending' => array('sortby'=>'age', 'direction'=>'ASC'),
- 'nominated' => array('sortby'=>'age', 'direction'=>'ASC'),
- );
-
- if (!$default) {
- $queue_sorts = $this->controller->Session->read('editor_queue_sorts');
- if (isset($queue_sorts[$queue])) {
- return $queue_sorts[$queue];
- }
- }
-
- return $defaults[$queue];
- }
-
- /**
- * Set sort order parameters on specified queue
- * @param string $queue
- * @param string $sortby
- * @param string $direction
- * @return bool
- */
- function setQueueSort($queue, $sortby='default', $direction='default') {
- if (!$this->isSortableQueue($queue)) {
- return array();
- }
-
- // valid sorts for the queues, each sort containing default directions
- $validSorts = array(
- 'pending' => array(
- 'age' => array('direction'=>'ASC'),
- 'type' => array('direction'=>'ASC'),
- 'name' => array('direction'=>'ASC'),
- ),
- 'nominated' => array(
- 'age' => array('direction'=>'ASC'),
- 'type' => array('direction'=>'ASC'),
- 'name' => array('direction'=>'ASC'),
- ),
- );
-
- $queueSorts = $this->controller->Session->read('editor_queue_sorts');
- if (!is_array($queueSorts)) {
- $queueSorts = array();
- }
-
- // reset to default
- if ($sortby == 'default') {
- unset($queueSorts[$queue]);
- $this->controller->Session->write('editor_queue_sorts', $queueSorts);
-
- // set to a known sort
- } elseif (array_key_exists($sortby, $validSorts[$queue])) {
- $newSort = $validSorts[$queue][$sortby];
- $newSort['sortby'] = $sortby;
- // use default direction unless...
- if (in_array(strtoupper($direction), array('DESC', 'ASC'))) {
- $newSort['direction'] = strtoupper($direction);
- }
- $queueSorts[$queue] = $newSort;
- $this->controller->Session->write('editor_queue_sorts', $queueSorts);
-
- // unknown sort
- } else {
- return false;
- }
-
- return true;
}
}
?>
diff --git a/site/app/controllers/components/email.php b/site/app/controllers/components/email.php
index 71f20ac..83708b4 100644
--- a/site/app/controllers/components/email.php
+++ b/site/app/controllers/components/email.php
@@ -12,7 +12,6 @@ class EmailComponent
*/
var $from = NOBODY_EMAIL;
var $fromName = SITE_NAME;
- var $sender = null;
//var $smtpUserName = 'username'; // SMTP username
//var $smtpPassword = 'password'; // SMTP password
//var $smtpHostNames= "smtp1.example.com;smtp2.example.com"; // specify main and backup server
@@ -71,14 +70,8 @@ class EmailComponent
//$mail->Username = $this->smtpUserName;
//$mail->Password = $this->smtpPassword;
+ $mail->Sender = $this->from;
$mail->From = $this->from;
- // if "Sender" field is set, add correct Sender header (cf. RFC5322 § 3.6.2)
- if (!empty($this->sender)) {
- $mail->Sender = $this->sender;
- $mail->AddCustomHeader("Sender: {$this->sender}");
- } else {
- $mail->Sender = $this->from;
- }
$mail->FromName = $this->fromName;
$mail->AddAddress($this->to, $this->toName );
if ($reply)
diff --git a/site/app/controllers/components/image.php b/site/app/controllers/components/image.php
index b0b6992..491a05d 100644
--- a/site/app/controllers/components/image.php
+++ b/site/app/controllers/components/image.php
@@ -77,17 +77,7 @@ class ImageComponent extends Object {
$this->renderImage($addon['Addon']['icondata'], $addon['Addon']['icontype']);
}
-
- /**
- * Renders the icon for a collection
- * @param int $collection_id the add-on ID
- */
- function renderCollectionIcon($collection_id) {
- $collection = $this->controller->Collection->findById($collection_id, array('icondata', 'icontype'), null, -1);
-
- $this->renderImage($collection['Collection']['icondata'], $collection['Collection']['icontype']);
- }
-
+
/**
* Renders the preview or thumbnail for an add-on
* @param int $preview_id the preview id
@@ -134,25 +124,6 @@ class ImageComponent extends Object {
}
/**
- * Gets the URL for the icon of the specified collection
- * @param int $addon_id the add-on id
- * @return string the URL
- */
- function getCollectionIconURL($collection_id) {
- $collection = $this->controller->Collection->findById(
- $collection_id, array(
- 'icontype', 'collection_type', 'uuid', 'modified'
- ), null, -1
- );
-
- if (empty($collection['Collection']['icontype'])) {
- return "{$this->controller->base}/img/collection.png";
- } else {
- return "{$this->controller->base}/en-US/firefox/images/collection_icon/{$collection_id}/".strtotime($collection['Collection']['modified']);
- }
- }
-
- /**
* Gets the URL for the highlighted preview for an add-on
* @param int $addon_id add-on ID
* @param string $type type of preview
diff --git a/site/app/controllers/components/search.php b/site/app/controllers/components/search.php
index 20f25ab..8fae4a5 100644
--- a/site/app/controllers/components/search.php
+++ b/site/app/controllers/components/search.php
@@ -152,7 +152,6 @@ class SearchComponent extends Object {
// fields to search in
$fields = array('name', 'summary', 'description');
- $_termarray = array();
// first prepare text terms
if (is_string($terms) && !empty($terms)) {
@@ -163,6 +162,7 @@ class SearchComponent extends Object {
preg_match_all($this->search_term_regex, $terms, $_termmatches);
// remove quotes around split terms and sanitize them
+ $_termarray = array();
foreach ($_termmatches[0] as $term) {
$term = trim($term, ' "');
$term = $this->controller->Sanitize->sql($term);
@@ -181,12 +181,13 @@ class SearchComponent extends Object {
} else { //in this case enumerate all addons. this allows advanced search to act as a filter
$text_score = "TRUE";
$boolean_score = "TRUE";
+ $_termarray = array();
}
// now initialize compoents of SQL query
$_selects = $_orderby = $_joins = $_where = array();
- $_orderby[] = '(LOWER(a.name) = \''.$this->controller->Sanitize->sql($terms).'\') DESC';
+ $_orderby[] = '(LOWER(a.name) = \''.$terms.'\') DESC';
$_orderby[] = '(a.status='.STATUS_PUBLIC.') DESC'; // show public add-ons first
$_orderby[] = "(a.name LIKE '%".implode(' ', $_termarray)."%') DESC"; // sort exact name hits first
@@ -231,6 +232,10 @@ class SearchComponent extends Object {
$_addon_types = array(ADDON_EXTENSION, ADDON_THEME, ADDON_SEARCH, ADDON_DICT, ADDON_LPAPP, ADDON_LPADDON);
}
}
+
+ // we are sugar
+ $_addon_types = $app_listedtypes[APP_SUGAR];
+
if (!is_array($_addon_types)) $_addon_types = array($_addon_types);
// override the odd-on type if the advanced search parameter $atype sent. Notice am assuming -1 not an add-on type
@@ -355,104 +360,5 @@ class SearchComponent extends Object {
foreach ($_results as $_result) $_result_ids[] = $_result['a']['id'];
return $_result_ids;
}
-
-
- /**
- * The collection search function.
- *
- * @param string terms to search for
- * @param sort is used to specify sort order
- * @param locale controls whether we search within only the current locale and en-US (faster) or all locales
- * @return array of collection ids
- */
- function searchCollections($terms, $sort='', $locale=false) {
- // fields to search in
- $fields = array('name', 'description');
- $_termarray = array();
-
- // first prepare text terms
- if (is_string($terms) && !empty($terms)) {
- // UTF-8 aware case-insensitive search
- $terms = mb_strtolower($terms, 'UTF-8');
-
- // split string into single terms
- preg_match_all($this->search_term_regex, $terms, $_termmatches);
-
- // remove quotes around split terms and sanitize them
- foreach ($_termmatches[0] as $term) {
- $term = trim($term, ' "');
- $term = $this->controller->Sanitize->sql($term);
- if ($term) $_termarray[] = $term;
- }
- // now strip duplicates
- $_termarray = array_unique($_termarray);
- $_search_termarray = array();
- foreach ($_termarray as $term) {
- if (false !== strpos($term, ' ')) $term = '"'.$term.'"'; // enclose "literal phrases" in quotes
- $_search_termarray[] = '+'.$term."*";
- }
-
- $text_score = " MATCH(c.".implode(', c.',$fields).") AGAINST ('".implode(" ", $_termarray)."')";
- $boolean_score = " MATCH(c.".implode(', c.',$fields).") AGAINST ('".implode(" ", $_search_termarray)."' IN BOOLEAN MODE)";
- } else { //in this case enumerate all collections. this allows advanced search to act as a filter
- $text_score = "TRUE";
- $boolean_score = "TRUE";
- }
-
- // now initialize compoents of SQL query
- $_selects = $_orderby = $_where = array();
-
- $_orderby[] = '(LOWER(c.name) = \''.$this->controller->Sanitize->sql($terms).'\') DESC';
- $_orderby[] = "(c.name LIKE '%".implode(' ', $_termarray)."%') DESC"; // sort exact name hits first
-
- if (!$locale) {
- $_matches = "(c.locale = '".LANG."' OR c.locale = 'en-US' ) AND ";
- }
- $_matches .= $boolean_score;
-
- foreach ($fields as $field) {
- // select strings
- $_selects[] = "c.".$field;
- }
- if ($text_score !== "TRUE") {
- $_selects[] = $text_score." AS text_score";
- $_orderby[] = 'text_score DESC';
- }
-
- $_where[] = "`Collection`.`application_id`='".APP_ID."'";
- $_where[] = "`Collection`.`listed`='1'";
-
- // sorting
- switch($sort) {
- case 'all':
- array_unshift($_orderby, "`Collection`.`subscribers` DESC");
- break;
- case 'weekly':
- array_unshift($_orderby, "`Collection`.`weekly_subscribers` DESC");
- break;
- case 'monthly':
- array_unshift($_orderby, "`Collection`.`monthly_subscribers` DESC");
- break;
- case 'newest':
- array_unshift($_orderby, "`Collection`.`created` DESC");
- break;
- }
-
- // build and run query
- $sql = "SELECT DISTINCT `c`.`id`, " . implode(', ', $_selects) . "
- FROM `collections_search_summary` AS `c`
- INNER JOIN `collections` AS `Collection` ON (`Collection`.`id` = `c`.`id`)
- WHERE {$_matches}
- ".(empty($_where) ? '' : 'AND ('.implode(' AND ', $_where).') ')."
- ORDER BY ".implode(', ', $_orderby);
- $_results = $this->controller->Addon->query($sql, true);
-
- // return the ids found
- $_result_ids = array();
- foreach ($_results as $_result) {
- $_result_ids[] = $_result['c']['id'];
- }
- return $_result_ids;
- }
}
?>
diff --git a/site/app/controllers/components/stats.php b/site/app/controllers/components/stats.php
index 3702a3c..21dded6 100644
--- a/site/app/controllers/components/stats.php
+++ b/site/app/controllers/components/stats.php
@@ -125,10 +125,8 @@ class StatsComponent extends Object {
// Update pings per day
case 'updatepings':
- // Since summing update pings per day isn't as useful as summing
- // the other data points, we're taking an average here instead.
if ($data = $model->query("
- SELECT `date`, {$date_group_column} AVG(`count`) as `count`
+ SELECT `date`, {$date_group_column} sum(`count`) as `count`
FROM `update_counts`
WHERE `addon_id`={$addon_id} AND date != '0000-00-00'
GROUP BY `{$date_group_by}`
@@ -523,89 +521,5 @@ class StatsComponent extends Object {
return $xml;
}
-
- /**
- * @return array Array of count results for the current day.
- */
- function getDailyStats() {
-
- $yesterday = date('Y-m-d', strtotime('yesterday'));
- $after = $yesterday.' 00:00:00';
- $before = $yesterday.' 23:59:59';
-
- $ret = array(
- 'nomination' => '',
- 'pending' => '',
- 'flagged' => '',
- 'reviews' => '',
- 'dailyAddons' => '',
- 'totalAddons' => '',
- 'dailyVersions' => '',
- 'dailyUsers' => '',
- 'dailyImages' => '',
- 'dailyDownloads' => '',
- 'after' => $after,
- 'before' => $before
- );
-
- $model =& $this->controller->Addon;
-
- if ($buf = $model->query("SELECT COUNT(*) as nomination FROM addons WHERE status=3", true)) {
- $ret['nomination'] = $buf[0][0]['nomination'];
- unset($buf);
- }
-
- if ($buf = $model->query("SELECT COUNT(*) as pending FROM files WHERE status=2", true)) {
- $ret['pending'] = $buf[0][0]['pending'];
- unset($buf);
- }
-
- if ($buf = $model->query("SELECT COUNT(*) as flagged FROM addons WHERE adminreview=1", true)) {
- $ret['flagged'] = $buf[0][0]['flagged'];
- unset($buf);
- }
-
- if ($buf = $model->query("SELECT COUNT(*) as reviews FROM reviews WHERE editorreview=1", true)) {
- $ret['reviews'] = $buf[0][0]['reviews'];
- unset($buf);
- }
-
- if ($buf = $model->query("SELECT COUNT(*) as total FROM addons WHERE created >= '{$after}' AND created <= '{$before}'", true)) {
- $ret['dailyAddons'] = $buf[0][0]['total'];
- unset($buf);
- }
-
- if ($buf = $model->query("SELECT COUNT(*) as total FROM addons", true)) {
- $ret['totalAddons'] = $buf[0][0]['total'];
- unset($buf);
- }
-
- if ($buf = $model->query("SELECT COUNT(*) as total FROM versions WHERE created >= '{$after}' AND created <= '{$before}'", true)) {
- $ret['dailyVersions'] = $buf[0][0]['total'];
- unset($buf);
- }
-
- if ($buf = $model->query("SELECT COUNT(*) as total FROM users WHERE created >= '{$after}' AND created <= '{$before}'", true)) {
- $ret['dailyUsers'] = $buf[0][0]['total'];
- unset($buf);
- }
-
- if ($buf = $model->query("SELECT COUNT(*) as total FROM reviews WHERE created >= '{$after}' AND created <= '{$before}'", true)) {
- $ret['dailyReviews'] = $buf[0][0]['total'];
- unset($buf);
- }
-
- if ($buf = $model->query("SELECT COUNT(*) as total FROM previews WHERE created >= '{$after}' AND created <= '{$before}'", true)) {
- $ret['dailyImages'] = $buf[0][0]['total'];
- unset($buf);
- }
-
- if ($buf = $model->query("SELECT SUM(count) as count FROM download_counts WHERE date = '{$yesterday}'", true)) {
- $ret['dailyDownloads'] = $buf[0][0]['count'];
- unset($buf);
- }
-
- return $ret;
- }
}
?>
diff --git a/site/app/controllers/developers_controller.php b/site/app/controllers/developers_controller.php
index f089e63..a77946e 100644
--- a/site/app/controllers/developers_controller.php
+++ b/site/app/controllers/developers_controller.php
@@ -37,31 +37,11 @@
* ***** END LICENSE BLOCK ***** */
require_once('Archive/Zip.php');
-/**
- * Returns $object[$name], or $default if that's not set.
- *
- * If $name is a string of dot-separated names like 'foo.bar.baz',
- * $object['foo']['bar']['baz'] will be returned. If any name
- * along the way is not set, $default will be returned.
- *
- * If you want to fetch a name with embedded dots, look elsewhere.
- */
-function getitem($object, $name, $default=null) {
- $split = explode('.', $name, 2);
- if (count($split) == 2) {
- list($a, $b) = $split;
- return isset($object[$a]) ? getitem($object[$a], $b, $default)
- : $default;
- } else {
- return isset($object[$name]) ? $object[$name] : $default;
- }
-}
-
class DevelopersController extends AppController
{
var $name = 'Developers';
var $uses = array('Addon', 'Addontype', 'Application', 'Approval', 'Appversion',
- 'EditorSubscription', 'Eventlog', 'File', 'License', 'Platform', 'Preview', 'Review',
+ 'EditorSubscription', 'Eventlog', 'File', 'Platform', 'Preview', 'Review',
'Tag', 'Translation', 'User', 'Version');
var $components = array('Amo', 'Developers', 'Editors', 'Email', 'Error',
'Image', 'Opensearch', 'Rdf', 'Src', 'Versioncompare');
@@ -110,9 +90,6 @@ class DevelopersController extends AppController
// Default "My Add-ons" sidebar data
$session = $this->Session->read('User');
$this->publish('all_addons', $this->Addon->getAddonsByUser($session['id']));
-
- // Include the dev_agreement column on developer pages.
- array_push($this->Addon->default_fields, 'dev_agreement');
}
/**
@@ -235,7 +212,6 @@ class DevelopersController extends AppController
*/
function _submitAddon() {
$this->publish('type', 'new');
- $this->publish('hasAgreement', false);
$this->render('uploader');
}
@@ -266,17 +242,9 @@ class DevelopersController extends AppController
$session = $this->Session->read('User');
$this->Addon->saveAuthor($data['Addon']['id'], $session['id']);
- // Save License
- $license_id = $this->Developers->saveLicense(
- $this->data['License'],
- getitem($this->data, 'License.text'),
- getitem($this->params, 'form.data.License'));
- $this->Addon->saveField('dev_agreement', 1);
-
// Add Version
$this->Version->id = 0;
$data['Version']['addon_id'] = $data['Addon']['id'];
- $data['Version']['license_id'] = $license_id;
$this->Version->save($data['Version']);
$data['Version']['id'] = $this->Version->getLastInsertId();
@@ -351,30 +319,13 @@ class DevelopersController extends AppController
return $this->Error->getJSONforError(sprintf(___('devcp_update_addon_version_exists_error'), $data['Version']['version'], $this->url('/developers/versions/addfile/'.$vcheck['Version']['id'])));
}
- // Save License
- if ($addon['Addon']['dev_agreement'] == true) {
- // If we already have an agreement, we didn't show the license
- // picker, so use the previously selected license.
- global $valid_status;
- $old_id = $this->Version->getVersionByAddonId($addon_id, $valid_status);
- $oldVersion = $this->Version->findById($old_id);
- $license_id = $oldVersion['Version']['license_id'];
- } else {
- $license_id = $this->Developers->saveLicense(
- $this->data['License'],
- getitem($this->data, 'License.text'),
- getitem($this->params, 'form.data.License'));
- }
- $this->Addon->save(array('Addon' => array('id' => $addon_id,
- 'dev_agreement' => 1)));
-
+
// Add Version
$this->Version->id = 0;
$data['Version']['addon_id'] = $addon_id;
- $data['Version']['license_id'] = $license_id;
$this->Version->save($data['Version']);
$version_id = $this->Version->getLastInsertId();
-
+
// If add-on is public, cancel any pending files
if ($addon['Addon']['status'] == STATUS_PUBLIC) {
$this->Addon->execute("UPDATE files SET status = ".STATUS_SANDBOX." WHERE files.version_id IN (SELECT id FROM versions WHERE versions.addon_id={$addon_id}) AND files.status = ".STATUS_PENDING);
@@ -456,6 +407,7 @@ class DevelopersController extends AppController
);
}
+
function _rmtree($dir) {
$dir = "$dir";
@@ -543,71 +495,65 @@ class DevelopersController extends AppController
);
}
- // we are sugar
- if (true) {
- $bundle = $addon['File']['details']['path'];
- $pathinfo = pathinfo($bundle);
-
- if ($pathinfo['extension'] == '.xo') {
- $ini = $this->_unbundle($bundle, 'activity/activity.info');
- if (isset($ini['error']))
- return $this->Error->getJSONforError($ini['error']);
- $ini_file = $ini['manifest'];
-
- if (!is_array($ini_file))
- return $this->Error->getJSONforError(_('devcp_error_activity_info_not_found'));
- if (!isset($ini_file['name']))
- return $this->Error->getJSONforError(_('devcp_error_activity_info_missing_name'));
- if (!isset($ini_file['activity_version']))
- return $this->Error->getJSONforError(_('devcp_error_activity_info_missing_activity_version'));
-
- if (isset($ini_file['bundle_id']))
- $addon['Addon']['guid'] = $ini_file['bundle_id'];
- else if (isset($ini_file['service_name']))
- $addon['Addon']['guid'] = $ini_file['service_name'];
- else
- return $this->Error->getJSONforError(_('devcp_error_activity_info_missing_bundle_id'));
+ if ($addon['Addon']['addontype_id'] == ADDON_ACTIVITY) {
+ $ini = $this->_unbundle($addon['File']['details']['path'], 'activity/activity.info');
+ if (isset($ini['error']))
+ return $this->Error->getJSONforError($ini['error']);
+ $ini_file = $ini['manifest'];
- $addon['Addon']['name'] = $ini_file['name'];
- $addon['Addon']['summary'] = $ini_file['name'];
- $addon['Version']['version'] = $ini_file['activity_version'];
+ if (!is_array($ini_file))
+ return $this->Error->getJSONforError(_('devcp_error_activity_info_not_found'));
+ if (!isset($ini_file['name']))
+ return $this->Error->getJSONforError(_('devcp_error_activity_info_missing_name'));
+ if (!isset($ini_file['activity_version']))
+ return $this->Error->getJSONforError(_('devcp_error_activity_info_missing_activity_version'));
+ if (isset($ini_file['bundle_id']))
+ $addon['Addon']['guid'] = $ini_file['bundle_id'];
+ else if (isset($ini_file['service_name']))
+ $addon['Addon']['guid'] = $ini_file['service_name'];
+ else
+ return $this->Error->getJSONforError(_('devcp_error_activity_info_missing_bundle_id'));
+
+ $addon['Addon']['name'] = $ini_file['name'];
+ $addon['Addon']['summary'] = $ini_file['name'];
+ $addon['Version']['version'] = $ini_file['activity_version'];
+
+ } else if ($addon['Addon']['addontype_id'] == ADDON_CONTENT) {
+ $ini = $this->_unbundle($addon['File']['details']['path'], 'library/library.info');
+ if (isset($ini['error']))
+ return $this->Error->getJSONforError($ini['error']);
+ $ini_file = $ini['manifest'];
+
+ if (!is_array($ini_file))
+ return $this->Error->getJSONforError(_('devcp_error_activity_info_not_found'));
+ if (!isset($ini_file['name']))
+ return $this->Error->getJSONforError(_('devcp_error_activity_info_missing_name'));
+ if (!isset($ini_file['long_name']))
+ return $this->Error->getJSONforError(_('devcp_error_activity_info_missing_summary'));
+ if (!isset($ini_file['global_name']))
+ return $this->Error->getJSONforError(_('devcp_error_activity_info_missing_bundle_id'));
+
+ $addon['Addon']['name'] = $ini_file['name'];
+ $addon['Addon']['summary'] = $ini_file['long_name'];
+ $addon['Addon']['guid'] = $ini_file['global_name'];
+
+ if (!isset($this->data['Addon']['id'])) {
+ $addon['Version']['version'] = 1;
} else {
- $ini = $this->_unbundle($bundle, 'library/library.info');
- if (isset($ini['error']))
- return $this->Error->getJSONforError($ini['error']);
- $ini_file = $ini['manifest'];
-
- if (!is_array($ini_file))
- return $this->Error->getJSONforError(_('devcp_error_activity_info_not_found'));
- if (!isset($ini_file['name']))
- return $this->Error->getJSONforError(_('devcp_error_activity_info_missing_name'));
- if (!isset($ini_file['long_name']))
- return $this->Error->getJSONforError(_('devcp_error_activity_info_missing_summary'));
- if (!isset($ini_file['global_name']))
- return $this->Error->getJSONforError(_('devcp_error_activity_info_missing_bundle_id'));
-
- $addon['Addon']['name'] = $ini_file['name'];
- $addon['Addon']['summary'] = $ini_file['long_name'];
- $addon['Addon']['guid'] = $ini_file['global_name'];
-
- if (!isset($this->data['Addon']['id'])) {
- $addon['Version']['version'] = 1;
- } else {
- $addon_id = $this->data['Addon']['id'];
- $_addon = $this->Addon->findById($addon_id);
- $version = 0;
-
- if (!empty($_addon)) {
- foreach ($_addon['Version'] as $i) {
- if ($i['version'] > $version) {
- $version = $i['version'];
- }
+ $addon_id = $this->data['Addon']['id'];
+ $_addon = $this->Addon->findById($addon_id);
+ $version = 0;
+
+ if (!empty($_addon)) {
+ foreach ($_addon['Version'] as $i) {
+ if ($i['version'] > $version) {
+ $version = $i['version'];
}
}
-
- $addon['Version']['version'] = $version + 1;
}
+
+ $addon['Version']['version'] = $version + 1;
}
} else
// Parse install.rdf file if not a search plugin
@@ -665,11 +611,6 @@ class DevelopersController extends AppController
elseif ($addon['Addon']['addontype_id'] == ADDON_SEARCH) {
// Get search engine properties
$search = $this->Opensearch->parse($addon['File']['details']['path']);
-
- // There was a parse error, the name was empty, etc. Bad things.
- if ($search == null) {
- return $this->Error->getJSONforError(___('devcp_verify_search_engine_error','Either the XML is invalid or required fields are missing. Please <a href="https://developer.mozilla.org/en/Creating_OpenSearch_plugins_for_Firefox">read the documentation</a>, verify your add-on, and try again.'));
- }
$addon['Addon']['name'] = $search->name;
$addon['Addon']['summary'] = $search->description;
@@ -863,7 +804,7 @@ class DevelopersController extends AppController
$supportedApps = array(
0 => array(
'Application' => array(
- 'id' => APP_FIREFOX
+ 'id' => APP_SUGAR
)
)
);
@@ -1030,6 +971,7 @@ class DevelopersController extends AppController
$criteria['description'] = !empty($addon['Translation']['description']['string']);
$criteria['category'] = !empty($addon['Tag']);
$criteria['previews'] = !empty($previews);
+ $criteria['reviews'] = (!empty($reviews) && count($reviews) >= 3) ? true : false;
$criteria['prerelease'] = !empty($addon['Addon']['prerelease']) ? false : true;
$criteria['application'] = !empty($versions) ? true : false;
@@ -1068,7 +1010,6 @@ class DevelopersController extends AppController
$addonData = array('status' => STATUS_SANDBOX, 'higheststatus' => STATUS_SANDBOX);
$this->Addon->save($addonData);
$this->publish('success', true);
- if (QUERY_CACHE) $this->Addon->Cache->markListForFlush("addon:{$addon['Addon']['id']}");
return true;
}
@@ -1111,7 +1052,7 @@ class DevelopersController extends AppController
$this->render('addon_status_nominate');
return false;
}
- $addonData = array('status' => STATUS_NOMINATED, 'nominationmessage' => $this->params['form']['data']['Addon']['nominationmessage'], 'nominationdate' => date('Y-m-d H:i:s'));
+ $addonData = array('status' => STATUS_NOMINATED, 'nominationmessage' => $this->params['form']['data']['Addon']['nominationmessage']);
$this->Addon->save($addonData);
$this->publish('success', true);
@@ -1226,9 +1167,6 @@ class DevelopersController extends AppController
$this->publish('version', $version['Version']['version']);
}
- $addon = $this->Addon->findById($addon_id, array('Addon.dev_agreement'));
- $this->publish('hasAgreement', $addon['Addon']['dev_agreement']);
-
$this->render('uploader');
}
@@ -1351,13 +1289,6 @@ class DevelopersController extends AppController
}
}
- // Save license.
- $license_id = $this->Developers->saveLicense(
- $this->data['License'],
- getitem($this->data, 'Version.License.text'),
- getitem($this->params, 'form.data.Version.License'));
- $this->Version->saveField('license_id', $license_id);
-
// flush cached add-on objects
if (QUERY_CACHE) $this->Addon->Cache->markListForFlush("addon:{$addon_id}");
@@ -1385,13 +1316,6 @@ class DevelopersController extends AppController
// Get all translations
$translations = $this->Version->getAllTranslations($version_id);
- if (isset($version['Version']['license_id'])) {
- $trans = $this->License->getAllTranslations($version['Version']['license_id']);
- $translations['license_text'] = $trans['text'];
- } else {
- $translations['license_text'] = array();
- }
-
$this->set('translations', $translations);
// Other info
@@ -1486,9 +1410,7 @@ class DevelopersController extends AppController
// flush cached add-on objects
if (QUERY_CACHE) $this->Addon->Cache->markListForFlush("addon:{$addon_id}");
- // inform about cache lag, if any of the changes were successful
- if (!empty($messages['success'])) $messages['success'][] = ___('devcp_several_hours');
-
+ $messages['success'][] = ___('devcp_several_hours');
$this->publish('messages', $messages);
}
@@ -1607,10 +1529,8 @@ class DevelopersController extends AppController
return;
}
// Make sure user has some permissions to view this add-on
- $session = $this->Session->read('User');
- $isEditor = $this->SimpleAcl->actionAllowed('Editors', '*', $session);
$role = $this->Amo->getAuthorRole($inforequest['Approval']['addon_id']);
- if (!$isEditor && empty($role)) $this->Amo->accessDenied();
+ if (empty($role)) $this->Amo->accessDenied();
$this->publish('inforequest', $inforequest);
@@ -1628,21 +1548,6 @@ class DevelopersController extends AppController
if (!empty($this->data)) {
$session = $this->Session->read('User');
- //Auto-detect addontype if necessary
- if ($this->data['Addon']['addontype_id'] == 0) {
- $this->data['Addon']['addontype_id'] = $this->Developers->detectAddontype($this->data['File']['file1']);
- $this->publish('autoDetected', $this->Addontype->getName($this->data['Addon']['addontype_id']));
- }
-
- //Make sure addontype is allowed
- $allowedAddonTypes = $this->Developers->getAllowedAddonTypes(false, $this->SimpleAcl->actionAllowed('*', '*', $this->Session->read('User')));
- if (!array_key_exists($this->data['Addon']['addontype_id'], $allowedAddonTypes)) {
- $this->Error->addError(_('devcp_error_invalid_addontype'));
- }
-
- //Validate files
- $this->Developers->validateFiles();
-
// reply submitted
$approvalData = array(
'user_id' => $session['id'],
@@ -1684,5 +1589,1429 @@ class DevelopersController extends AppController
}
$this->render();
}
+
+ /**
+ * Index
+ */
+ function index($addon_id = '') {
+ $this->Amo->clean($addon_id);
+ $session = $this->Session->read('User');
+ $this->User->id = $session['id'];
+
+ // If requesting a specific add-on, show details for it
+ if (!empty($addon_id)) {
+ $this->details($addon_id);
+ return;
+ }
+
+ $addon_ids = $this->Addon->getAddonsByUser($session['id']);
+ $data = array();
+
+ if (!empty($addon_ids)) {
+ foreach ($addon_ids as $addon_id => $addon_name) {
+ $addon = $this->Addon->find("Addon.id={$addon_id}");
+
+ if (!empty($addon['Version'][0])) {
+ $files = $this->File->findAll("File.version_id={$addon['Version'][0]['id']}");
+
+ if (!empty($files)) {
+ foreach ($files as $file) {
+ $addon['Version'][0]['File'][] = $file;
+ }
+ }
+ }
+
+ $data['Addon'][$addon_id] = array_merge($addon['Addon'], $addon);
+ $data['Addon'][$addon_id]['updatepings'] = $this->Addon->getMostRecentUpdatePingCount($addon_id);
+
+ }
+ }
+
+ $this->publish('data', $data);
+ $this->publish('approval', $this->Amo->getApprovalStatus());
+ $this->publish('platforms', $this->Amo->getPlatformName());
+ $this->publish('addontypes', $this->Addontype->getNames());
+ }
+
+ /**
+ * Shows the details of a specific add-on
+ * @param int $id The add-on id
+ */
+ function details($id) {
+ $this->Amo->clean($id);
+
+ if (!$this->Amo->checkOwnership($id)) {
+ $this->flash(_('devcp_error_addon_access_denied'), '/developers/index');
+ return;
+ }
+
+ //Bind necessary models
+ $this->User->bindFully();
+ $this->Addontype->bindFully();
+ $this->Version->bindFully();
+ $this->Addon->bindFully();
+
+ $this->Addon->id = intval($id);
+
+ if (!empty($this->data)) {
+ //Save translated fields (releasenotes)
+ $this->Developers->saveTranslations($this->data);
+ $this->flash(_('devcp_comments_updated'), '/developers/details/'.$id);
+ return;
+ }
+
+ if(!$addon = $this->Addon->read()) {
+ $this->flash(_('error_addon_notfound'), '/developers/index');
+ return;
+ }
+
+ if (!empty($addon)) {
+ if (!empty($addon['Version'])) {
+ foreach ($addon['Version'] as $v => $version) {
+ $addon['Version'][$v]['File'] = $this->File->findAll("File.version_id='{$version['id']}'");
+ }
+ }
+
+ if (!empty($addon['Preview'])) {
+ foreach ($addon['Preview'] as $p => $preview) {
+ $this->Preview->id = $preview['id'];
+ $addon['Preview'][$p] = $this->Preview->read();
+ }
+ }
+
+ if (!empty($addon['Tag'])) {
+ foreach ($addon['Tag'] as $tag) {
+ $tags[] = $tag['id'];
+ }
+ $tags = $this->Tag->findAll("Tag.id IN (".implode(', ', $tags).")");
+ if (!empty($tags)) {
+ foreach ($tags as $tag) {
+ $addon['Tags'][] = $tag['Translation']['name']['string'];
+ }
+ }
+ }
+ }
+
+ $this->publish('addon', $addon);
+ $this->publish('approval', $this->Amo->getApprovalStatus());
+ $this->publish('platforms', $this->Amo->getPlatformName());
+ $this->publish('addontypes', $this->Addontype->getNames());
+
+ //Retrieve language arrays from bootstrap.
+ global $valid_languages, $native_languages;
+ foreach (array_keys($valid_languages) as $key) {
+ $languages[$key] = $native_languages[$key]['native'];
+
+ $this->Addon->setLang($key, $this);
+ $addonL = $this->Addon->read();
+
+ foreach ($addonL['Translation'] as $field => $translation) {
+ if ($translation['locale'] == $key) {
+ $info[$key][$field] = $translation['string'];
+ }
+ else {
+ $info[$key][$field] = '';
+ }
+ }
+ }
+ $this->Addon->setLang(LANG, $this);
+
+ //Set up localebox info
+ $this->set('localebox', array('info' => $info,
+ 'defaultLocale' => $addon['Addon']['defaultlocale'],
+ 'languages' => $languages));
+ $this->render('details', 'mozilla');
+ }
+
+ /**
+ * Add new version to a new or existing add-on
+ * @param int $id
+ */
+ function add($id = '') {
+ $this->Amo->clean($id);
+ $this->publish('subpagetitle', _('devcp_addon_submit_pagetitle'));
+ $this->breadcrumbs[_('devcp_addon_submit_pagetitle')] = '/developers/add/'.$id;
+ $this->publish('breadcrumbs', $this->breadcrumbs);
+
+ //If submissions are disabled, show appropriate error
+ if ($this->Config->getValue('submissions_disabled') == 1 && !$this->SimpleAcl->actionAllowed('*', '*', $this->Session->read('User'))) {
+ $this->flash(_('devcp_submissions_disabled'), '/', 3);
+ return;
+ }
+
+ //Bind necessary models
+ $this->User->bindFully();
+ $this->Addontype->bindFully();
+ $this->Version->bindFully();
+ $this->Addon->bindFully();
+
+ //Get a list of add-on types
+ $this->publish('addonTypes', $this->Addontype->getNames());
+
+ //Determine if adding a new addon or new version
+ if (!empty($this->data['Addon']['newAddon'])) {
+ if ($this->data['Addon']['newAddon'] == 'false') {
+ $this->addVars['newAddon'] = false;
+ }
+ else {
+ $this->addVars['newAddon'] = true;
+ }
+ $this->Addon->id = $id;
+ $this->addVars['existing'] = $this->Addon->read();
+ }
+ else {
+ //This is step 1, so check if the id was passed
+ if (!empty($id) && $this->Amo->checkOwnership($id)) {
+ $this->Addon->id = $id;
+ $this->addVars['existing'] = $this->Addon->read();
+ $this->addVars['newAddon'] = false;
+ }
+ else {
+ $this->addVars['newAddon'] = true;
+ $this->addVars['existing'] = array();
+ $id = '';
+ }
+ }
+ $this->publish('existing', $this->addVars['existing']);
+
+ //Set some view data used in all steps
+ $this->publish('id', $id);
+ $this->publish('newAddon', $this->addVars['newAddon']);
+ if (!empty($this->data['Version']['id'])) {
+ $this->publish('version', $this->data['Version']['id']);
+ $this->Version->id = $this->data['Version']['id'];
+ }
+
+ //Set default locale
+ if (!empty($this->data['Addon']['defaultlocale'])) {
+ $this->addVars['defaultLocale'] = $this->data['Addon']['defaultlocale'];
+ }
+ elseif (!empty($this->addVars['existing']['Addon']['defaultlocale'])) {
+ $this->addVars['defaultLocale'] = $this->addVars['existing']['Addon']['defaultlocale'];
+ }
+ else {
+ $this->addVars['defaultLocale'] = LANG;
+ }
+
+ //Set models to read and save using default locale, which may not be the current locale
+ $this->Addon->setLang($this->addVars['defaultLocale'], $this);
+ $this->Version->setLang($this->addVars['defaultLocale'], $this);
+
+ $this->set('defaultLocale', $this->addVars['defaultLocale']);
+
+ //Go to appropriate step
+ if (isset($_POST['cancel'])) {
+ $this->_cancelAdd();
+ }
+ elseif (isset($this->data['Addon']['add_step1'])) {
+ $this->_addStep1();
+ }
+ elseif (isset($this->data['Addon']['add_step2'])) {
+ $this->_addStep2();
+ }
+ elseif (isset($this->data['Addon']['add_step3'])) {
+ $this->_addStep3();
+ }
+ elseif (isset($this->data['Addon']['add_step4'])) {
+ $this->_addStep4();
+ }
+ else {
+ if ($this->addVars['newAddon'] == true) {
+ $this->_addStep0();
+ }
+ else {
+ $this->_addStep1();
+ }
+ }
+ }
+
+ /**
+ * Step 0: Agreement
+ */
+ function _addStep0() {
+ if (isset($this->data['Addon']['add_step0'])) {
+ if (!empty($_POST['accept'])) {
+ $this->data = '';
+ $this->_addStep1();
+ return;
+ }
+ }
+ $this->publish('step', 0);
+ $this->render('add_step0');
+ }
+
+ /**
+ * Step 1: Upload files/select add-on type
+ */
+ function _addStep1() {
+ //Check if we are processing Step 1 or just displaying it
+ if (isset($this->data['Addon']['add_step1'])) {
+ //Check for model validation first
+ if (!$this->Addon->validates($this->data)) {
+ $this->Error->addError(_('error_formerrors'));
+ $this->validateErrors();
+ }
+
+ //Auto-detect addontype if necessary
+ if ($this->data['Addon']['addontype_id'] == 0) {
+ $this->data['Addon']['addontype_id'] = $this->Developers->detectAddontype($this->data['File']['file1']);
+ $this->publish('autoDetected', $this->Addontype->getName($this->data['Addon']['addontype_id']));
+ }
+
+ //Make sure addontype is allowed
+ $allowedAddonTypes = $this->Developers->getAllowedAddonTypes(false, $this->SimpleAcl->actionAllowed('*', '*', $this->Session->read('User')));
+ if (!array_key_exists($this->data['Addon']['addontype_id'], $allowedAddonTypes)) {
+ $this->Error->addError(_('devcp_error_invalid_addontype'));
+ }
+
+ //Validate files
+ $this->Developers->validateFiles();
+
+ //Only proceed if no errors
+ if ($this->Error->noErrors()) {
+ //Search plugins do not have install.rdf to parse
+ if ($this->data['Addon']['addontype_id'] != ADDON_SEARCH) {
+
+ //Iterate through files to make sure they're all valid
+ //Reverse order so that file 1's info will be used after
+ for ($f = 3; $f >= 1; $f--) {
+ if (!empty($this->addVars['file'.$f])) {
+ //Extract install.rdf
+ $zip = new Archive_Zip($this->addVars['file'.$f]['path']);
+ $extraction = $zip->extract(array('extract_as_string' => true, 'by_name' => array('install.rdf')));
+
+ //Make sure install.rdf is present
+ if (!empty($extraction)) {
+ $fileContents = $extraction[0]['content'];
+
+ //Use Rdf Component to parse install.rdf
+ $manifestData = $this->Rdf->parseInstallManifest($fileContents);
+
+ //Clean manifest data - take THAT, evil-doers!
+ $this->Amo->clean($manifestData);
+
+ //Validate manifest data
+ $validate = $this->Developers->validateManifestData($manifestData);
+ // Anything other than boolean true is an error
+ if ($validate === true) {
+
+ //Validate target applications
+ $this->addVars['appversions'] = $this->Developers->validateTargetApplications($manifestData['targetApplication']);
+
+ // If result is a string, it's an error
+ if (is_string($this->addVars['appversions'])) {
+ $this->Error->addError($this->addVars['appversions']);
+ }
+
+ //Make sure GUIDs match in all manifests
+ if (empty($guid)) {
+ $guid = $manifestData['id'];
+ }
+ elseif ($manifestData['id'] != $guid) {
+ $this->Error->addError(_('devcp_error_file_guids_dont_match'));
+ }
+ }
+ else {
+ // There was an error validating manifest data
+ $this->Error->addError($validate);
+ }
+ }
+ else {
+ $validAppReference = sprintf(_('devcp_valid_app_reference'), '<a href="'.$this->url('/pages/appversions').'">'._('devcp_valid_app_reference_linktext').'</a>');
+ $this->Error->addError(_('devcp_error_index_rdf_notfound').'<br>'.$validAppReference);
+ }
+ }
+ }
+
+ if ($this->Error->noErrors()) {
+
+ //These are arrays by locale
+ $addonNames = $manifestData['name'];
+ $addonDesc = $manifestData['description'];
+
+ //In case user said it was a new add-on when it is actually an update
+ if ($existing = $this->Addon->findAll("Addon.guid='{$manifestData['id']}'")) {
+ if ($existing[0]['Addon']['status'] != STATUS_NULL && $this->addVars['newAddon'] == true) {
+ $this->addVars['newAddon'] = false;
+ $this->publish('newAddon', $this->addVars['newAddon']);
+ }
+
+ /**
+ * If user went back to step 1, we know because newAddon is true
+ * and status is NULL. If that's the case, we make a note so that
+ * we don't insert things that are already inserted.
+ */
+ if ($existing[0]['Addon']['status'] == STATUS_NULL) {
+ $this->addVars['skipInserts'] = true;
+ }
+
+ $this->addVars['existing'] = $existing[0];
+ $this->publish('existing', $this->addVars['existing']);
+ $this->publish('id', $this->addVars['existing']['Addon']['id']);
+ $this->Addon->id = $this->addVars['existing']['Addon']['id'];
+ if (!$this->Amo->checkOwnership($this->addVars['existing']['Addon']['id'])) {
+ $this->flash(_('devcp_error_update_access_denied'));
+ return;
+ }
+ }
+ elseif ($this->addVars['newAddon'] == false) {
+ $this->addVars['newAddon'] = true;
+ $this->publish('newAddon', $this->addVars['newAddon']);
+ $this->publish('existing', '');
+ $this->publish('id', '');
+ $this->Addon->id = 0;
+ }
+
+ //Check for identical versions
+ if (!empty($this->Addon->id)) {
+
+ for ($f = 1; $f <= 4; $f++) {
+ if (!empty($this->data['File']['platform_id'.$f])) {
+ $platformIds[] = $this->data['File']['platform_id'.$f];
+ }
+ }
+
+ //If updating the addon, get any identical version numbers
+ //Must have WHERE statement this way, otherwise cake doesn't quote properly
+ if ($versions = $this->Version->findAll("addon_id={$this->Addon->id} AND version='{$manifestData['version']}'")) {
+ foreach ($versions as $version) {
+ foreach($version['File'] as $file) {
+ if (in_array($file['platform_id'], $platformIds) && $file['status'] != STATUS_NULL) {
+ $this->Error->addError(sprintf(_('devcp_error_identical_version_exists'), $manifestData['version']));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ //If it is a search plugin, read the .src file
+ else {
+ //Parse the .src file
+ $src = $this->Src->parse(REPO_PATH.'/temp/'.$this->addVars['file1']['filename']);
+ if ($src !== false) {
+ $manifestData['name']['en-US'] = $src;
+ }
+ else {
+ $manifestData = array();
+ }
+
+ $this->data['Addon']['platform_id'] = 1;
+ }
+
+ //If no errors, save
+ if ($this->Error->noErrors()) {
+
+ //Create the addon entry if new
+ if ($this->addVars['newAddon'] == true) {
+ if ($this->data['Addon']['addontype_id'] != ADDON_SEARCH) {
+ $this->data['Addon']['guid'] = $manifestData['id'];
+ }
+
+ //If creating new, blacklist status and id.
+ $addonData = array_merge($this->data['Addon'], (array)$this->addVars['file4']);
+ $addonData = $this->Amo->filterFields($addonData, array(),
+ array('status', 'id', 'trusted', 'averagerating', 'weeklydownloads', 'totaldownloads'));
+ $this->Addon->save($addonData);
+
+ if (empty($this->addVars['skipInserts'])) {
+ $this->Addon->id = $this->Addon->getLastInsertId();
+
+ //Insert current user as author so no permissions issues occur
+ $session = $this->Session->read('User');
+ $this->Addon->execute("INSERT INTO addons_users (addon_id, user_id) VALUES({$this->Addon->id}, {$session['id']})");
+ }
+
+ $this->addVars['existing'] = $this->data;
+ $this->publish('id', $this->Addon->id);
+ }
+ else {
+ //If updating, whitelist defaultlocale and icon fields
+ if (!empty($this->addVars['file4'])) {
+ $addonData = array_merge($this->data['Addon'], $this->addVars['file4']);
+ }
+ else {
+ $addonData = $this->data['Addon'];
+ }
+ $addonData = $this->Amo->filterFields($addonData,
+ array('addontype_id', 'defaultlocale', 'icondata', 'icontype'));
+ $this->Addon->save($addonData);
+ }
+
+ //Create the version entry
+ $this->data['Version']['addon_id'] = $this->Addon->id;
+ $this->data['Version']['version'] = (!empty($manifestData['version'])) ? $manifestData['version'] : date('Ymd');
+
+ //Blacklist id. addon_id should be watched too, but it's already overwritten above
+ $versionData = $this->Amo->filterFields($this->data['Version'], array(),
+ array('id'));
+ $this->Version->save($versionData);
+ $this->Version->id = $this->Version->getLastInsertId();
+ $this->publish('version', $this->Version->id);
+
+ if(!empty($this->addVars['appversions'])) {
+ //Insert target apps
+ foreach ($this->addVars['appversions'] as $appversion) {
+ //Cake doesn't deal with extra fields in HABTM tables, so have to insert manually
+ $this->Version->execute("INSERT INTO applications_versions (version_id, application_id, min, max) VALUES('{$this->Version->id}', '{$appversion['application_id']}', '{$appversion['min']}', '{$appversion['max']}')");
+ }
+ }
+
+ //Insert files
+ for ($f = 1; $f <= 3; $f++) {
+ if (!empty($this->addVars['file'.$f]['filename'])) {
+ $this->File->id = 0;
+ $this->addVars['file'.$f]['version_id'] = $this->Version->id;
+
+ //These fields are parsed through the code and shouldn't need filtering
+ $this->File->save($this->addVars['file'.$f]);
+ $this->addVars['files'][] = $this->File->getLastInsertId();
+ }
+ }
+ $this->publish('files', $this->addVars['files']);
+
+ //Show next step
+ $this->addVars['manifestData'] = $manifestData;
+
+ //If user opted to not review add-on info and all required info is present,
+ //skip to step 3
+ if (!empty($this->data['Addon']['Review']) && $this->Developers->noReviewRequired()) {
+ $this->_addStep3();
+ }
+ else {
+ $this->_addStep2();
+ }
+
+ return;
+ }
+ }
+ }
+
+ //Prep for view
+ //Get Platforms list
+ $this->set('platforms', $this->Amo->getPlatformName());
+
+ //Default to reviewing add-on information
+ $this->publish('ReviewInfo', ((isset($this->data['Addon']['Review']) && $this->data['Addon']['Review'] == 1) ? array('value' => '1', 'checked' => 'checked') : array()));
+
+ //Set allowed addontypes.
+ $allowedAddonTypes = $this->Developers->getAllowedAddonTypes(true, $this->SimpleAcl->actionAllowed('*', '*', $this->Session->read('User')));
+ $this->set('allowedAddonTypes', $allowedAddonTypes);
+
+ //Retrieve language arrays from bootstrap.
+ global $valid_languages, $native_languages;
+ foreach (array_keys($valid_languages) as $key) {
+ $languages[$key] = $native_languages[$key]['native'];
+ }
+
+ if (empty($this->data))
+ $this->data = array();
+ $this->publish('data', $this->data);
+ $this->set('errors', $this->Error->errors);
+ $this->publish('step', 1);
+ $this->set('languages', $languages);
+ $this->render('add_step1');
+ }
+
+ /**
+ * Step 2: Add-on wide information
+ */
+ function _addStep2() {
+
+ //Check if we are processing step 2 or just displaying the view for it
+ if (isset($this->data['Addon']['add_step2'])) {
+
+ //Check for model validation first
+ if (!$this->Addon->validates($this->data)) {
+ $this->Error->addError(_('error_formerrors'));
+ $this->validateErrors();
+ }
+
+ //Validate tags/categories if not correcting addontype id
+ if (!empty($this->data['Addon']['addontype_id']) && $this->data['Addon']['addontype_id'] != $this->addVars['existing']['Addon']['addontype_id']) {
+ unset($this->data['Tag']);
+ $this->addVars['showTagsStep3'] = $this->data['Addon']['addontype_id'];
+ }
+ elseif ($this->addVars['existing']['Addon']['addontype_id'] != ADDON_SEARCH && empty($this->data['Tag']['noTags'])) {
+ //Search engines don't have tags
+ @$this->Developers->validateTags($this->data['Tag']['Tag']);
+ }
+
+ //Validate users
+ @$this->Developers->validateUsers($this->data['User']['User']);
+
+ if ($this->Error->noErrors()) {
+ //Updated Addon
+ if ($this->addVars['newAddon'] == false) {
+ $tagData = $this->data['Tag']['Tag'];
+ unset($this->data['Tag']);
+ unset($this->Addon->data['Tag']); // Cake--
+ $this->Tag->LEGACY_saveCategories($this->Addon->id, $tagData);
+
+ //Update addon - usual addon blacklist
+ $addonData = $this->Amo->filterFields($this->data, array(),
+ array('id', 'guid', 'status', 'trusted', 'averagerating', 'weeklydownloads', 'totaldownloads'));
+
+ if (!$this->Addon->save($addonData, false)) {
+ $this->Error->addError(_('devcp_error_saving'));
+ }
+ }
+ //New Addon
+ else {
+ //Check for duplicate names
+ //@TODO this doesn't really do well with the new translation stuff.
+ if ($this->Addon->findAllByName($this->data['Addon']['name'])) {
+ $this->Error->addError(_('devcp_error_addonname_not_unique'));
+ }
+ else {
+ //Insert addon
+ $addonData = $this->Amo->filterFields($this->data, array(),
+ array('id', 'guid', 'status', 'trusted', 'averagerating', 'weeklydownloads', 'totaldownloads'));
+ if (!$this->Addon->save($addonData, false)) {
+ $this->Error->addError(_('devcp_error_saving'));
+ }
+ }
+ }
+ }
+
+ if ($this->Error->noErrors()) {
+ //Getting to this point means there were no errors, so show next step
+ $this->_addStep3();
+ return;
+ }
+
+ //Prepare for view - use post data (unclean data before publishing to avoid escaped quotes in html)
+ $info = $this->Amo->unclean($this->data);
+
+ //Checkboxes
+ $checked = array('value' => '1', 'checked' => 'checked');
+ $notChecked = array();
+ $info['Addon']['viewsource'] = (!empty($this->data['Addon']['viewsource'])) ? $checked : $notChecked;
+ $info['Addon']['prerelease'] = (!empty($this->data['Addon']['prerelease'])) ? $checked : $notChecked;
+ $info['Addon']['sitespecific'] = (!empty($this->data['Addon']['sitespecific'])) ? $checked : $notChecked;
+ $info['Addon']['externalsoftware'] = (!empty($this->data['Addon']['externalsoftware'])) ? $checked : $notChecked;
+ }
+ else {
+ //Prepare for view - use existing data if !empty, else use parsed manifest
+ $manifestData = $this->Amo->unclean($this->addVars['manifestData']);
+ $info = $this->Amo->unclean($this->data);
+
+ $info['Addon']['name'] = (!empty($this->addVars['existing']['Translation']['name']['string']) ? $this->addVars['existing']['Translation']['name']['string'] : (!empty($manifestData['name']['en-US']) ? $manifestData['name']['en-US'] : ''));
+ $info['Addon']['description'] = (!empty($this->addVars['existing']['Translation']['description']['string']) ? $this->addVars['existing']['Translation']['description']['string'] : (!empty($manifestData['description']['en-US']) ? $manifestData['description']['en-US'] : ''));
+ $info['Addon']['homepage'] = (!empty($this->addVars['existing']['Translation']['homepage']['string']) ? $this->addVars['existing']['Translation']['homepage']['string'] : (!empty($manifestData['homepageURL']) ? $manifestData['homepageURL'] : ''));
+
+ $info['Addon']['addontype_id'] = !empty($this->addVars['existing']['Addon']['addontype_id']) ? $this->addVars['existing']['Addon']['addontype_id'] : $this->data['Addon']['addontype_id'];
+ $info['Version']['version'] = !empty($manifestData['version']) ? $manifestData['version'] : '';
+ $info['Addon']['summary'] = !empty($this->addVars['existing']['Translation']['summary']['string']) ? $this->addVars['existing']['Translation']['summary']['string'] : '';
+
+ $info['Addon']['supportemail'] = (!empty($this->addVars['existing']['Translation']['supportemail']['string']) ? $this->addVars['existing']['Translation']['supportemail']['string'] : '');
+ $info['Addon']['supporturl'] = (!empty($this->addVars['existing']['Translation']['supporturl']['string']) ? $this->addVars['existing']['Translation']['supporturl']['string'] : (!empty($manifestData['homepageURL']) ? $manifestData['homepageURL'] : ''));
+
+ $info['Addon']['eula'] = !empty($this->addVars['existing']['Translation']['eula']['string']) ? $this->addVars['existing']['Translation']['eula']['string'] : '';
+ $info['Addon']['privacypolicy'] = !empty($this->addVars['existing']['Translation']['privacypolicy']['string']) ? $this->addVars['existing']['Translation']['privacypolicy']['string'] : '';
+ $info['Addon']['guid'] = (!empty($this->addVars['existing']['Addon']['guid']) ? $this->addVars['existing']['Addon']['guid'] : (!empty($manifestData['id']) ? $manifestData['id'] : ''));
+ $info['File']['id'] = $this->addVars['files'];
+
+ //Checkboxes
+ $checked = array('value' => '1', 'checked' => 'checked');
+ $notChecked = array();
+ $info['Addon']['viewsource'] = (!empty($this->addVars['existing']['Addon']['viewsource'])) ? $checked : $notChecked;
+ $info['Addon']['prerelease'] = (!empty($this->addVars['existing']['Addon']['prerelease'])) ? $checked : $notChecked;
+ $info['Addon']['sitespecific'] = (!empty($this->addVars['existing']['Addon']['sitespecific'])) ? $checked : $notChecked;
+ $info['Addon']['externalsoftware'] = (!empty($this->addVars['existing']['Addon']['externalsoftware'])) ? $checked : $notChecked;
+ }
+
+ //Get authors in order of post data, existing data, default data
+ $info['authors'] = @$this->Developers->getAuthors($this->addVars['existing']['User']);
+
+ //Get application_ids
+ $applicationIds = array();
+ if (!empty($this->addVars['appversions'])) {
+ foreach ($this->addVars['appversions'] as $appversion) {
+ $applicationIds[] = $appversion['application_id'];
+ }
+ }
+ else {
+ $version = $this->Version->read();
+ foreach ($version['Application'] as $appversion) {
+ $applicationIds[] = $appversion['id'];
+ }
+ }
+
+ $tags = $this->Developers->getTags($this->addVars['existing']['Addon']['addontype_id'], $applicationIds);
+ $this->set('tags', $tags);
+
+ //Get selected tags in order of post data, existing data, default data
+ $info['selectedTags'] = @$this->Developers->getSelectedTags($this->addVars['existing']['Tag']);
+
+ //Set allowed addontypes.
+ $allowedAddonTypes = $this->Developers->getAllowedAddonTypes(false, $this->SimpleAcl->actionAllowed('*', '*', $this->Session->read('User')));
+ $this->set('allowedAddonTypes', $allowedAddonTypes);
+
+ $this->publish('info', $info);
+ $this->set('errors', $this->Error->errors);
+ $this->publish('step', 2);
+ $this->render('add_step2');
+ }
+
+ /**
+ * Step 3: Version Information
+ */
+ function _addStep3() {
+ //Check whether we are processing Step 3 or just displaying it
+ if (isset($this->data['Addon']['add_step3'])) {
+ //Check for model validation first
+ if (!$this->Version->validates($this->data)) {
+ $this->Error->addError(_('error_formerrors'));
+ $this->validateErrors();
+ }
+
+ if ($this->addVars['newAddon'] == false && empty($this->data['Version']['releasenotes'])) {
+ $this->Error->addError(_('devcp_error_describe_changes'), 'Version/releasenotes');
+ //For some reason, using Version model to invalidate doesn't work...
+ $this->Addon->invalidate('releasenotes');
+ $this->Error->addError(_('error_formerrors'));
+ }
+
+ if ($this->Error->noErrors()) {
+ $version = $this->Version->read();
+
+ $fileUpdates = $this->Developers->moveFiles($version, $this->addVars['existing']['Addon']['addontype_id']);
+
+ if ($this->Error->noErrors()) {
+
+ //Update version
+ $versionData = $this->Amo->filterFields($this->data['Version'], array(),
+ array('id', 'addon_id'));
+ $this->Version->data = '';
+ $this->Version->save($versionData);
+
+ //Determine file status
+ $fileStatus = $this->Developers->determineFileStatus($this->addVars['existing']['Addon']);
+
+ //Update file locations
+ if (!empty($fileUpdates)) {
+ foreach ($fileUpdates as $file => $filename) {
+ $this->File->id = $file;
+ $filename['status'] = $fileStatus;
+ $this->File->save($filename);
+
+ // Copy file to rsync area if public
+ if ($fileStatus == STATUS_PUBLIC) {
+ $fileInfo = $this->File->read();
+ $this->Amo->copyFileToPublic($this->Addon->id, $fileInfo['File']['filename']);
+ $this->File->save(array('datestatuschanged' => $this->Amo->getNOW()));
+ }
+ }
+ }
+
+ //If add-on is public, cancel any pending files
+ if ($this->addVars['existing']['Addon']['status'] == STATUS_PUBLIC) {
+ if (!empty($this->addVars['existing']['Version'])) {
+ foreach($this->addVars['existing']['Version'] as $version) {
+ $version = $this->Version->find("Version.id='{$version['id']}'");
+ if (!empty($version['File'])) {
+ foreach ($version['File'] as $file) {
+ if ($file['status'] == STATUS_PENDING) {
+ $this->File->id = $file['id'];
+ $this->File->save(array('status' => STATUS_SANDBOX));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //Update addon status if new or incomplete
+ if ($this->addVars['newAddon'] == true || $this->addVars['existing']['Addon']['status'] == 0) {
+ $addonData = array('Addon' => array('status' => STATUS_SANDBOX));
+ if (!empty($this->data['Tag'])) {
+ $addonData['Tag'] = $this->data['Tag'];
+ }
+ $this->Addon->save($addonData);
+ }
+
+ //Getting this far means there were no errors, display step 5
+ $this->_addStep4();
+ return;
+ }
+ }
+ }
+
+ //Prep view
+ //Pull version info
+ $info = $this->Version->read();
+
+ if (!empty($this->addVars['showTagsStep3'])) {
+ foreach ($info['Application'] as $appversion) {
+ $applicationIds[] = $appversion['id'];
+ }
+ $tags = $this->Developers->getTags($this->addVars['showTagsStep3'], $applicationIds);
+ $this->publish('tags', $tags);
+ }
+
+ $info['files'] = $this->File->findAllByVersion_id($this->Version->id);
+ $info['targetapps'] = $this->Amo->getMinMaxVersions($this->Version->id);
+
+ // Determine compatibility with latest Firefox
+ $noticeVersion = $this->Config->getValue('firefox_notice_version');
+ if (!empty($noticeVersion)) {
+ if (!empty($info['targetapps'])) {
+ foreach ($info['targetapps'] as $targetApp) {
+ if ($targetApp['max']['application_id'] == APP_FIREFOX &&
+ $this->Versioncompare->compareVersions($targetApp['max']['version'], $noticeVersion) == -1) {
+ $this->publish('showFirefoxVersionNotice', true);
+ }
+ }
+ }
+ }
+
+ //Get Platforms list
+ $this->publish('platforms', $this->Amo->getPlatformName());
+
+ $this->publish('info', $info);
+ $this->set('errors', $this->Error->errors);
+ $this->publish('step', 3);
+ $this->render('add_step3');
+ }
+
+ /**
+ * Step 4: Localization
+ */
+ function _addStep4() {
+ //Check whether we are processing Step 4 or just displaying it
+ if (isset($this->data['Addon']['add_step4'])) {
+
+ $this->Developers->saveTranslations($this->data);
+
+ $this->_addStep5();
+ return;
+ }
+
+ //Prep view
+
+ //Retrieve language arrays from bootstrap.
+ global $valid_languages, $native_languages;
+ foreach (array_keys($valid_languages) as $key) {
+ $languages[$key] = $native_languages[$key]['native'];
+
+ $this->Addon->setLang($key, $this);
+ $addon = $this->Addon->read();
+
+ foreach ($addon['Translation'] as $field => $translation) {
+ if ($translation['locale'] == $key) {
+ $info[$key][$field] = $translation['string'];
+ }
+ else {
+ $info[$key][$field] = '';
+ }
+ }
+
+ $this->Version->useLang = $key;
+ $version = $this->Version->read();
+
+ foreach ($version['Translation'] as $field => $translation) {
+ if ($translation['locale'] == $key) {
+ $info[$key][$field] = $translation['string'];
+ }
+ else {
+ $info[$key][$field] = '';
+ }
+ }
+ }
+
+ $localizedFields = array(
+ 'name' => array(
+ 'type' => 'input',
+ 'display' => _('devcp_addon_field_name_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'name',
+ 'attributes' => array()
+ ),
+ 'homepage' => array(
+ 'type' => 'input',
+ 'display' => _('devcp_addon_field_homepage_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'homepage',
+ 'attributes' => array(
+ 'size' => 40
+ )
+ ),
+ 'summary' => array(
+ 'type' => 'textarea',
+ 'display' => _('devcp_addon_field_summary_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'summary',
+ 'attributes' => array(
+ 'rows' => 3,
+ 'cols' => 55,
+ 'onBlur' => 'checkSummary(this, \''._('devcp_error_addon_field_summary_toolong').'\');'
+ )
+ ),
+ 'description' => array(
+ 'type' => 'textarea',
+ 'display' => _('devcp_addon_field_description_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'description',
+ 'attributes' => array(
+ 'rows' => 4,
+ 'cols' => 55
+ )
+ ),
+ 'eula' => array(
+ 'type' => 'textarea',
+ 'display' => _('devcp_addon_field_eula_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'eula',
+ 'attributes' => array(
+ 'rows' => 6,
+ 'cols' => 55
+ )
+ ),
+ 'privacypolicy' => array(
+ 'type' => 'textarea',
+ 'display' => _('devcp_addon_field_privacy_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'privacypolicy',
+ 'attributes' => array(
+ 'rows' => 6,
+ 'cols' => 55
+ )
+ ),
+ 'releasenotes' => array(
+ 'type' => 'textarea',
+ 'display' => _('devcp_addon_field_versionnotes_displaytitle'),
+ 'model' => 'Version',
+ 'field' => 'releasenotes',
+ 'attributes' => array(
+ 'rows' => 3,
+ 'cols' => 55
+ )
+ )
+ );
+
+ //Set up localebox info
+ $this->set('localebox', array('info' => $info,
+ 'defaultLocale' => $this->addVars['defaultLocale'],
+ 'languages' => $languages,
+ 'localizedFields' => $localizedFields));
+ $this->publish('step', 4);
+ $this->render('add_step4');
+ }
+
+ /**
+ * Step 5: Success
+ */
+ function _addStep5() {
+ //Determine file status
+ $fileStatus = $this->Developers->determineFileStatus($this->addVars['existing']['Addon']);
+
+ $this->publish('fileStatus', $fileStatus);
+ $this->publish('step', 5);
+ $this->render('add_step5');
+ }
+
+ /**
+ * Cancel additem process
+ */
+ function _cancelAdd() {
+ if (!$this->Amo->checkOwnership($this->Addon->id)) {
+ $this->flash(_('devcp_error_addon_access_denied'), '/developers/index');
+ return;
+ }
+
+ //Delete version, files, and translations
+ $this->Developers->deleteVersion($this->Version->id);
+
+ //If this was a new add-on, delete it and translations
+ if ($this->addVars['newAddon'] == true) {
+ $this->Developers->deleteAddon($this->Addon->id);
+ }
+
+ $this->redirect('/developers');
+ }
+
+ /**
+ * Edit add-on
+ * @param int $id
+ */
+ function edit($id) {
+ $this->Amo->clean($id);
+ $this->publish('subpagetitle', _('devcp_addon_edit_pagetitle'));
+ $this->breadcrumbs[_('devcp_addon_edit_pagetitle')] = '/developers/edit/'.$id;
+ $this->publish('breadcrumbs', $this->breadcrumbs);
+
+ if (!$this->Amo->checkOwnership($id)) {
+ $this->flash(_('devcp_error_addon_access_denied'), '/developers/index');
+ return;
+ }
+
+ //Bind necessary models
+ $this->User->bindFully();
+ $this->Addontype->bindFully();
+ $this->Version->bindFully();
+ $this->Addon->bindFully();
+
+ $this->Addon->id = $id;
+
+ $this->Amo->detailedLog('Editing add-on');
+
+ if (!empty($this->data)) {
+ $this->Amo->detailedLog('Non-empty data');
+ $this->Amo->detailedLog('Editing add-on details');
+ //Check for model validation first
+ if (!$this->Addon->validates($this->data)) {
+ $this->Error->addError(_('error_formerrors'));
+ $this->validateErrors();
+ $this->Amo->detailedLog('Validation errors');
+ }
+
+ $addon = $this->Addon->read();
+
+ //Validate tags/categories
+ if ($addon['Addon']['addontype_id'] != ADDON_SEARCH && empty($this->data['Tag']['noTags'])) {
+ @$this->Developers->validateTags($this->data['Tag']['Tag']);
+ }
+
+ //Validate users
+ @$this->Developers->validateUsers($this->data['User']['User']);
+
+ $this->Amo->detailedLog('Validated tags and users');
+
+ //Delete icon if requested
+ if (!empty($this->data['Addon']['DeleteIcon'])) {
+ $this->data['Addon']['icontype'] = '';
+ $this->data['Addon']['icondata'] = '';
+ }
+
+ //Update/insert icon
+ if (!empty($this->data['Addon']['icon']['name'])) {
+ $fileErrors = array('1' => ___('devcp_edit_file_error_size'),
+ '2' => ___('devcp_edit_file_error_size'),
+ '3' => ___('devcp_edit_file_error_incomplete'),
+ '4' => ___('devcp_edit_file_error_no')
+ );
+ $allowedImage = array('.png', '.jpg', '.gif');
+
+ $iconData = $this->Developers->validateIcon($this->data['Addon']['icon'], $fileErrors, $allowedImage);
+
+ if (is_string($iconData)) {
+ $this->Error->addError($iconData, 'Addon/icon');
+ }
+ else {
+ $this->data['Addon'] = array_merge($this->data['Addon'], $iconData);
+ }
+ }
+
+ if ($this->Error->noErrors()) {
+ $this->Amo->detailedLog('No errors - performing update');
+ //Update addon
+ $this->Developers->saveUsers($this->data['User']['User']);
+ $this->Amo->detailedLog('Saved users');
+
+ //Strip localized fields
+ $addonData = $this->Developers->stripLocalized($this->data);
+ $this->Amo->detailedLog('Stripped localized fields: '.print_r($addonData, true), false);
+
+ //usual addon blacklist
+ if ($this->SimpleAcl->actionAllowed('*', '*', $this->Session->read('User'))) {
+ $blacklist = array('id', 'guid', 'status');
+ }
+ else {
+ $blacklist = array('id', 'guid', 'status', 'trusted', 'averagerating', 'weeklydownloads', 'totaldownloads');
+ }
+ $addonData = $this->Amo->filterFields($addonData, array(), $blacklist);
+ $this->Amo->detailedLog('Fields filtered: '.print_r($addonData, true), false);
+ $this->Addon->data = array();
+ $tagData = $addonData['Tag']['Tag'];
+ unset($addonData['Tag']['Tag']);
+
+ if ($this->Addon->save($addonData) && $this->Developers->saveTranslations($this->data)) {
+ $this->Tag->LEGACY_saveCategories($this->Addon->id, $tagData);
+ $this->Amo->detailedLog('Add-on and translations saved: '.print_r($addonData, true));
+ $this->flash(_('devcp_addon_updated_successfully'), '/developers/edit/'.$this->Addon->id);
+ return;
+ }
+ else {
+ $this->Error->addError(_('devcp_error_saving'));
+ }
+ }
+ }
+
+ if (!$addon = $this->Addon->read()) {
+ $this->flash(_('error_addon_notfound'), '/developers/index');
+ return;
+ }
+
+ //Get tags based on addontype
+ $this->Version->id = $addon['Version'][0]['id'];
+ $applicationIds = array();
+ $version = $this->Version->read();
+ if (!empty($version)) {
+ foreach ($version['Application'] as $appversion) {
+ $applicationIds[] = $appversion['id'];
+ }
+ }
+ $this->set('tags', $this->Developers->getTags($addon['Addon']['addontype_id'], $applicationIds));
+
+ //Get selected tags
+ $this->set('selectedTags', $this->Developers->getSelectedTags($addon['Tag']));
+
+ //Get author info
+ $addon['authors'] = $this->Developers->getAuthors($addon['User'], false);
+
+ //Retrieve language arrays from bootstrap.
+ global $valid_languages, $native_languages;
+ foreach (array_keys($valid_languages) as $key) {
+ $languages[$key] = $native_languages[$key]['native'];
+
+ $this->Addon->setLang($key, $this);
+ $addonL = $this->Addon->read();
+
+ foreach ($addonL['Translation'] as $field => $translation) {
+ if ($translation['locale'] == $key) {
+ $info[$key][$field] = $translation['string'];
+ }
+ else {
+ $info[$key][$field] = '';
+ }
+ }
+ }
+ $this->Addon->setLang(LANG, $this);
+
+ //Checkboxes
+ $checked = array('value' => '1', 'checked' => 'checked');
+ $notChecked = array();
+ $addon['Addon']['viewsource'] = (!empty($addon['Addon']['viewsource'])) ? $checked : $notChecked;
+ $addon['Addon']['prerelease'] = (!empty($addon['Addon']['prerelease'])) ? $checked : $notChecked;
+ $addon['Addon']['sitespecific'] = (!empty($addon['Addon']['sitespecific'])) ? $checked : $notChecked;
+ $addon['Addon']['externalsoftware'] = (!empty($addon['Addon']['externalsoftware'])) ? $checked : $notChecked;
+ $addon['Addon']['trusted'] = (!empty($addon['Addon']['trusted'])) ? $checked : $notChecked;
+
+ $this->publish('addon', $addon);
+ $this->set('errors', $this->Error->errors);
+ $localizedFields = array(
+ 'name' => array(
+ 'type' => 'input',
+ 'display' => _('devcp_addon_field_name_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'name',
+ 'attributes' => array()
+ ),
+ 'homepage' => array(
+ 'type' => 'input',
+ 'display' => _('devcp_addon_field_homepage_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'homepage',
+ 'attributes' => array(
+ 'size' => 40
+ )
+ ),
+ 'supportemail' => array(
+ 'type' => 'input',
+ 'display' => _('devcp_addon_field_supportemail_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'supportemail',
+ 'attributes' => array(
+ 'size' => 40
+ )
+ ),
+ 'supporturl' => array(
+ 'type' => 'input',
+ 'display' => _('devcp_addon_field_supporturl_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'supporturl',
+ 'attributes' => array(
+ 'size' => 40
+ )
+ ),
+ 'summary' => array(
+ 'type' => 'textarea',
+ 'display' => _('devcp_addon_field_summary_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'summary',
+ 'attributes' => array(
+ 'rows' => 3,
+ 'cols' => 55,
+ 'onBlur' => 'checkSummary(this, \''._('devcp_error_addon_field_summary_toolong').'\');'
+ )
+ ),
+ 'description' => array(
+ 'type' => 'textarea',
+ 'display' => _('devcp_addon_field_description_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'description',
+ 'attributes' => array(
+ 'rows' => 4,
+ 'cols' => 55
+ )
+ ),
+ 'eula' => array(
+ 'type' => 'textarea',
+ 'display' => _('devcp_addon_field_eula_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'eula',
+ 'attributes' => array(
+ 'rows' => 6,
+ 'cols' => 55
+ )
+ ),
+ 'privacypolicy' => array(
+ 'type' => 'textarea',
+ 'display' => _('devcp_addon_field_privacy_displaytitle'),
+ 'model' => 'Addon',
+ 'field' => 'privacypolicy',
+ 'attributes' => array(
+ 'rows' => 6,
+ 'cols' => 55
+ )
+ )
+ );
+
+ //Set up localebox info
+ $this->set('localebox', array('info' => $info,
+ 'defaultLocale' => $addon['Addon']['defaultlocale'],
+ 'languages' => $languages,
+ 'localizedFields' => $localizedFields));
+ }
+
+ /**
+ * Edit a version
+ * @param int $id
+ */
+ function editversion($id) {
+ $this->Amo->clean($id);
+ $this->set ('subpagetitle', _('devcp_version_edit_pagetitle'));
+ $this->breadcrumbs[_('devcp_version_edit_pagetitle')] = '/developers/editversion/'.$id;
+ $this->publish('breadcrumbs', $this->breadcrumbs);
+
+ //Bind necessary models
+ $this->User->bindFully();
+ $this->Addontype->bindFully();
+ $this->Version->bindFully();
+ $this->Addon->bindFully();
+
+ $this->Version->id = $id;
+ if (!$version = $this->Version->read()) {
+ $this->flash(_('error_version_notfound'), '/developers/index');
+ return;
+ }
+
+ if (!$this->Amo->checkOwnership($version['Version']['addon_id'])) {
+ $this->flash(_('devcp_error_addon_access_denied'), '/developers/index');
+ return;
+ }
+
+ if (!empty($this->data)) {
+ foreach ($this->data['File']['id'] as $id => $file_id) {
+ $this->File->id = $file_id;
+
+ //Update or delete file
+ if ($this->data['File']['Delete'][$id] != 1) {
+ $fileData = array('platform_id' => $this->data['File']['platform_id'][$id]);
+ $this->File->save($fileData);
+ }
+ else {
+ $this->Developers->deleteFile($this->File->id, $version['Version']['addon_id']);
+ }
+ }
+
+ //Save translated fields (releasenotes)
+ $this->Developers->saveTranslations($this->data);
+
+ //Save min/max versions
+ $this->Amo->saveMinMaxVersions($this->Version->id, $this->data['targetApps']);
+
+ //Save other version fields by whitelist
+ $versionData = $this->Amo->filterFields($this->data['Version'], array('approvalnotes'));
+ $this->Version->save($versionData);
+
+ $this->flash(_('devcp_version_updated_successfully'), '/developers/editversion/'.$this->Version->id);
+ return;
+ }
+
+ $version['targetapps'] = $this->Amo->getMinMaxVersions($this->Version->id);
+
+ // Get all versions
+ foreach ($version['targetapps'] as $k => $app) {
+ $_versionlist = $this->Appversion->findAllByApplication_id($app['applications']['id'], '', '', '', '', -1);
+ $this->Versioncompare->sortAppversionArray($_versionlist);
+ $version['targetapps'][$k]['appversions'] = $_versionlist;
+ }
+
+ //Retrieve language arrays from bootstrap.
+ global $valid_languages, $native_languages;
+ foreach (array_keys($valid_languages) as $key) {
+ $languages[$key] = $native_languages[$key]['native'];
+
+ $this->Version->setLang($key, $this);
+ $versionL = $this->Version->read();
+
+ foreach ($versionL['Translation'] as $field => $translation) {
+ if ($translation['locale'] == $key) {
+ $info[$key][$field] = $translation['string'];
+ }
+ else {
+ $info[$key][$field] = '';
+ }
+ }
+ }
+ $this->Version->setLang(LANG, $this);
+
+ //Pull add-on info for translations
+ $this->Addon->id = $version['Version']['addon_id'];
+ $addon = $this->Addon->read();
+
+ $localizedFields = array(
+ 'releasenotes' => array(
+ 'type' => 'textarea',
+ 'display' => _('devcp_addon_field_versionnotes_displaytitle'),
+ 'model' => 'Version',
+ 'field' => 'releasenotes',
+ 'attributes' => array(
+ 'rows' => 3,
+ 'cols' => 55
+ )
+ )
+ );
+
+ $this->publish('version', $version);
+ $this->publish('addon', $addon);
+ $this->publish('platforms', $this->Amo->getPlatformName());
+
+ //Set up localebox info
+ $this->set('localebox', array('info' => $info,
+ 'defaultLocale' => $addon['Addon']['defaultlocale'],
+ 'languages' => $languages,
+ 'localizedFields' => $localizedFields));
+ //Javascript localization
+ $this->publish('jsLocalization', array(
+ 'deleteMessage' => _('devcp_question_delete_file')
+ ));
+ }
+
+ /**
+ * Disable or enable add-on
+ */
+ function disable($addon_id) {
+ $this->Amo->clean($addon_id);
+ $session = $this->Session->read('User');
+ $this->User->id = $session['id'];
+
+ $this->Addon->id = $addon_id;
+
+ // Make sure user has permission
+ if (!$this->Amo->checkOwnership($addon_id)) {
+ $this->flash(_('devcp_error_addon_access_denied'), '/developers/index');
+ return;
+ }
+
+ if (!empty($_POST)) {
+ if (!empty($_POST['enable'])) {
+ $addonData = array('inactive' => 0);
+ $this->Addon->save($addonData);
+ $this->flash(_('devcp_addon_enabled_successfully'), '/developers/details/'.$this->Addon->id);
+ }
+ else {
+ $addonData = array('inactive' => 1);
+ $this->Addon->save($addonData);
+ $this->flash(_('devcp_addon_disabled_successfully'), '/developers/details/'.$this->Addon->id);
+ }
+
+ return;
+ }
+
+ $addon = $this->Addon->read();
+
+ $this->publish('addon', $addon);
+
+ $this->render('disable');
+ }
+
+ /**
+ * Nominate an add-on to be public
+ * @param int $id the add-on id
+ */
+ function nominate($id) {
+ $this->Amo->clean($id);
+ $session = $this->Session->read('User');
+ $this->User->id = $session['id'];
+
+ $this->publish('subpagetitle', _('devcp_addon_nominate_pagetitle'));
+ $this->breadcrumbs[_('devcp_addon_nominate_pagetitle')] = '/developers/nominate/'.$id;
+ $this->publish('breadcrumbs', $this->breadcrumbs);
+
+ $this->User->bindFully();
+ $data = $this->User->read();
+
+ $this->Addon->id = $id;
+ if (!$addon = $this->Addon->read()) {
+ $this->flash(_('error_addon_notfound'), '/developers/index');
+ return;
+ }
+
+ //Make sure has ownership or is an editor to nominate
+ if (!$this->Amo->checkOwnership($id) && !$this->SimpleAcl->actionAllowed('Editors', '*', $this->Session->read('User'))) {
+ $this->flash(_('devcp_error_addon_access_denied'), '/developers/index');
+ return;
+ }
+
+ //Make sure add-on is in sandbox
+ if ($addon['Addon']['status'] != STATUS_SANDBOX) {
+ $this->flash(_('devcp_error_nominate_sandbox_only'), '/developers/details/'.$id, 3);
+ return;
+ }
+
+ //Nominate
+ if (!empty($_POST['nominate'])) {
+ //Make sure not a pre-release
+ if ($addon['Addon']['prerelease'] == 1) {
+ $this->flash(_('devcp_error_nominate_no_prerelease'), '/developers/details/'.$id, 3);
+ return;
+ }
+
+ //Make sure nomination message not empty
+ if (empty($this->data['Addon']['nominationmessage'])) {
+ $this->flash(_('devcp_error_nominate_message'), '/developers/nominate/'.$id, 3);
+ return;
+ }
+
+ //Amo->clean is being stupid. Yes, that's right. I said STUPID
+ $nominationMessage = str_replace('\n', "\n", $this->data['Addon']['nominationmessage']);
+ $nominationMessage = str_replace('\r', "\r", $nominationMessage);
+
+ $addonData = array('status' => STATUS_NOMINATED, 'nominationmessage' => $nominationMessage);
+
+ $this->Addon->save($addonData);
+ $this->flash(_('devcp_addon_nominated_successfully'), '/developers/details/'.$id, 3);
+ return;
+ }
+
+ $this->publish('addon', $addon);
+ }
+
+ /**
+ * AJAX action for looking up an author by email
+ * @param string $email
+ */
+ function authorLookup() {
+ // Rather than change our cake parameter regex, use a normal get var
+ $email = $_GET['q'];
+ $this->Amo->clean($email);
+ if ($authors = $this->User->findAllByEmail($email)) {
+ $author = $authors[0]['User']['firstname'].' '.$authors[0]['User']['lastname'];
+ $author .= ' ['.$authors[0]['User']['email'].']';
+ $this->publish('id', $authors[0]['User']['id']);
+ }
+ else {
+ $author = false;
+ }
+
+ $this->publish('author', $author);
+ $this->publish('email', $email);
+ $this->render('author_lookup', 'ajax');
+ }
+
}
+
?>
diff --git a/site/app/controllers/downloads_controller.php b/site/app/controllers/downloads_controller.php
index 0057a4d..fc182db 100644
--- a/site/app/controllers/downloads_controller.php
+++ b/site/app/controllers/downloads_controller.php
@@ -76,11 +76,10 @@ class DownloadsController extends AppController
$file_loc = REPO_PATH . '/' . $file_data['Version']['addon_id'] . '/' . $file_data['File']['filename'];
// If add-on is in sandbox, make sure sandbox is enabled. If disabled, make sure admin or author.
- // If _GET['confirmed'] exists, then a user confirmed a sandbox download via JS, bug 441739
if (($addon_data['Addon']['status'] == STATUS_SANDBOX ||
$addon_data['Addon']['status'] == STATUS_NOMINATED ||
$file_data['File']['status'] == STATUS_PENDING)
- && !$this->Session->check('User') && !isset($_GET['confirmed'])) {
+ && !$this->Session->check('User')) {
$target_url = str_replace(LANG . '/' . APP_SHORTNAME . '/','',$this->params['url']['url']);
$this->redirect('/users/login?to=' . urlencode($target_url) . "&m=1");
@@ -147,17 +146,7 @@ class DownloadsController extends AppController
if (!empty($file_id)) {
// Use normal download method if file is found
- $target = "/downloads/file/{$file_id}/{$type}/{$file_data['File']['filename']}";
- if (count($this->params['url']) > 1) { // re-append query string
- $getvars = array();
- foreach ($this->params['url'] as $k => $v) {
- if ($k == 'url') continue;
- $getvars[] = "$k=$v";
- }
- $qs = implode(',', $getvars);
- $target .= "?$qs";
- }
- $this->redirect($target);
+ $this->redirect("/downloads/file/{$file_id}/{$type}/{$file_data['File']['filename']}");
}
else {
// File wasn't found
diff --git a/site/app/controllers/editors_controller.php b/site/app/controllers/editors_controller.php
index 3a97e51..314f2ef 100644
--- a/site/app/controllers/editors_controller.php
+++ b/site/app/controllers/editors_controller.php
@@ -23,8 +23,6 @@
* Wil Clouser <clouserw@gmail.com>
* Frederic Wenzel <fwenzel@mozilla.com>
* Les Orchard <lorchard@mozilla.com>
- * Cesar Oliveira <a.sacred.line@gmail.com>
- * Scott McCammon <smccammon@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -56,7 +54,6 @@ class EditorsController extends AppController
function beforeFilter() {
//beforeFilter() is apparently called before components are initialized. Cake++
$this->Amo->startup($this);
- $this->Editors->startup($this);
$this->Amo->checkLoggedIn();
@@ -67,10 +64,7 @@ class EditorsController extends AppController
$this->publish('cssAdd', $this->cssAdd);
$this->publish('jsAdd', array('jquery-compressed.js',
- 'jquery.autocomplete.pack.js',
- 'jquery.tablesorter.min.js',
- 'jquery.flot.js',
- 'jquery.sparkline.min.js',
+ 'jquery.autocomplete.js',
'editors'));
$this->breadcrumbs = array(_('editors_pagetitle') => '/editors/index');
@@ -85,10 +79,16 @@ class EditorsController extends AppController
}
//Get counts
- $count['pending'] = $this->_getCount('pending');
- $count['nominated'] = $this->_getCount('nominated');
- $count['reviews'] = $this->_getCount('reviews');
+ $pending = $this->File->query("SELECT COUNT(*) FROM `files` WHERE `status`=".STATUS_PENDING." GROUP BY `status`");
+ $nominated = $this->Addon->query("SELECT COUNT(*) FROM `addons` WHERE `status`=".STATUS_NOMINATED." GROUP BY `status`");
+ $reviews = $this->Review->query("SELECT COUNT(*) FROM `reviews` WHERE `editorreview`=1 GROUP BY `editorreview`");
+
+ $count['pending'] = !empty($pending) ? $pending[0][0]['COUNT(*)'] : 0;
+ $count['nominated'] = !empty($nominated) ? $nominated[0][0]['COUNT(*)'] : 0;
+ $count['reviews'] = !empty($reviews) ? $reviews[0][0]['COUNT(*)'] : 0;
$this->publish('count', $count);
+
+ $this->count = $count;
}
/**
@@ -143,6 +143,8 @@ class EditorsController extends AppController
$this->publish('collapse_categories', true);
+ $count = $this->count;
+
$this->Amo->clean($mode);
$this->breadcrumbs[_('editors_review_queue_pagetitle')] = '/editors/queue';
$this->publish('breadcrumbs', $this->breadcrumbs);
@@ -150,38 +152,72 @@ class EditorsController extends AppController
$this->publish('mode', $mode);
- // Setup queue filter
- if (array_key_exists('filter', $this->params['form'])) {
- // set a new filter on this queue
- $filter = $this->Editors->setQueueFilter($mode, $this->data['Filter']);
-
- } elseif (array_key_exists('clear', $this->params['form'])) {
- // clear existing filter on this queue
- $filter = $this->Editors->setQueueFilter($mode, null);
-
- // clear sorting
- $this->Editors->setQueueSort($mode, 'default');
-
- } else {
- // fetch existing filter
- $filter = $this->Editors->getQueueFilter($mode);
- }
+ if ($mode == 'pending') {
+ // Setup our pagination
+ $this->Pagination->total = $count['pending'];
+ $_pagination_options = array('sortByClass' => 'Version', 'sortBy' => 'created');
- // Handle changes to sorting
- if (isset($this->params['url']['sort'])) {
- if (isset($this->params['url']['dir'])) {
- $this->Editors->setQueueSort($mode, $this->params['url']['sort'], $this->params['url']['dir']);
+ if (!array_key_exists('show', $_GET) && $this->Session->read('editor_queue_pending_show')) {
+ $_pagination_options['show'] = $this->Session->read('editor_queue_pending_show');
+ } else {
+ // If $_GET['show'] exists it overrides this in the pagination component
+ $_pagination_options['show'] = 50;
+ }
+ list($_order,$_limit,$_page) = $this->Pagination->init(null, null, $_pagination_options);
+ $this->Session->write('editor_queue_pending_show', $_limit);
+
+ //Pull any files that have STATUS_PENDING
+ $pending = $this->File->findAllByStatus(STATUS_PENDING,
+ array('File.id', 'File.platform_id', 'Version.id',
+ 'Version.addon_id', 'Version.version',
+ 'Version.created'
+ ), $_order, $_limit, $_page, 0);
+
+ if (!empty($pending)) {
+ foreach ($pending as $k => $file) {
+ $addon = $this->Addon->findById($file['Version']['addon_id'],
+ array('Addon.id', 'Addon.name', 'Addon.defaultlocale',
+ 'Addon.addontype_id', 'Addon.prerelease',
+ 'Addon.sitespecific', 'Addon.externalsoftware',
+ ));
+ $pending[$k] = array_merge_recursive($pending[$k], $addon);
+ }
+ }
+ $addons = $pending;
+ }
+ elseif ($mode == 'nominated') {
+ // Setup our pagination
+ $this->Pagination->total = $count['nominated'];
+ $_pagination_options = array('sortByClass' => 'Addon', 'sortBy' => 'created');
+ if (!array_key_exists('show', $_GET) && $this->Session->read('editor_queue_nominated_show')) {
+ $_pagination_options['show'] = $this->Session->read('editor_queue_nominated_show');
} else {
- $this->Editors->setQueueSort($mode, $this->params['url']['sort']);
+ // If $_GET['show'] exists it overrides this in the pagination component
+ $_pagination_options['show'] = 50;
}
- }
+ list($_order,$_limit,$_page) = $this->Pagination->init(null,null,$_pagination_options);
+ $this->Session->write('editor_queue_nominated_show', $_limit);
- // Build the queue
- if ($mode == 'pending' || $mode == 'nominated') {
- $addons = $this->_buildQueue($mode);
+ //Pull any add-ons that have STATUS_NOMINATED
+ $nominated = $this->Addon->findAllByStatus(STATUS_NOMINATED,
+ array('Addon.id', 'Addon.name', 'Addon.defaultlocale',
+ 'Addon.addontype_id', 'Addon.prerelease',
+ 'Addon.sitespecific', 'Addon.externalsoftware',
+ 'Addon.created'
+ ), $_order, $_limit, $_page, 0);
+ if (!empty($nominated)) {
+ foreach ($nominated as $k => $addon) {
+ $version = $this->Version->findByAddon_id($addon['Addon']['id'],
+ array('Version.id', 'Version.addon_id',
+ 'Version.version', 'Version.modified'
+ ), 'Version.created DESC');
+ $nominated[$k] = array_merge_recursive($nominated[$k], $version);
+ }
+ }
+ $addons = $nominated;
}
elseif ($mode == 'reviews') {
- $this->_reviews($this->_getCount('reviews'));
+ $this->_reviews($count['reviews']);
return;
}
else {
@@ -189,56 +225,141 @@ class EditorsController extends AppController
return;
}
- //Setup filter form fields
- $selected = array('Application'=>'', 'MaxVersion'=>'',
- 'SubmissionAge'=>'', 'Addontype'=>'', 'Platform'=>'',);
- if (is_array($filter)) {
- foreach ($filter as $k => $val) {
- if (array_key_exists($k, $selected)) {
- $selected[$k] = $val;
+ $platforms = $this->Amo->getPlatformName();
+ $applications = $this->Amo->getApplicationName();
+
+ $submissionTypes = array( 'new' => _('editors_submissiontype_new'),
+ 'updated' => _('editors_submissiontype_updated')
+ );
+
+ //make modifications to the queue array
+ if (!empty($addons)) {
+ foreach ($addons as $k => $addon) {
+ //get min/max versions
+ if ($targetApps = $this->Amo->getMinMaxVersions($addon['Version']['id'])) {
+ foreach ($targetApps as $targetApp) {
+ $appName = $targetApp['translations']['localized_string'];
+ $addons[$k]['targetApps'][$appName]['min'] = $targetApp['min']['version'];
+ $addons[$k]['targetApps'][$appName]['max'] = $targetApp['max']['version'];
+ }
+ }
+
+ //Age
+ if ($mode == 'pending') {
+ $age = time() - strtotime($addon['Version']['created']);
+ }
+ elseif ($mode == 'nominated') {
+ $age = time() - strtotime($addon['Addon']['created']);
+ }
+
+ //days
+ if ($age >= (60*60*24*2)) {
+ $addons[$k]['age'] = sprintf(_('editors_x_days'), floor($age/(60*60*24)));
+ }
+ //1 day
+ elseif ($age >= (60*60*24)) {
+ $addons[$k]['age'] = _('editors_one_day');
+ }
+ //hours
+ elseif ($age >= (60*60*2)) {
+ $addons[$k]['age'] = sprintf(_('editors_x_hours'), floor($age/(60*60)));
+ }
+ //hour
+ elseif ($age >= (60*60)) {
+ $addons[$k]['age'] = _('editors_one_hour');
+ }
+ //minutes
+ elseif ($age > 60) {
+ $addons[$k]['age'] = sprintf(_('editors_x_minutes'), floor($age/60));
+ }
+ //minute
+ else {
+ $addons[$k]['age'] = _('editors_one_minute');
+ }
+
+ //Generate any additional notes
+ $addons[$k]['notes'] = array();
+
+ //Platform-specific?
+ if (!empty($addon['Version'][0]['File'][0]['platform_id']) && $addon['Version'][0]['File'][0]['platform_id'] != 1) {
+ $os = array();
+ foreach ($addon['Version'][0]['File'] as $file) {
+ $os[] = $platforms[$file['platform_id']];
+ }
+ $addons[$k]['notes'][] = sprintf(_('editors_platform_x_only'), implode(', ', $os));
+ }
+ elseif (!empty($addon['File']['platform_id']) && $addon['File']['platform_id'] != 1) {
+ $addons[$k]['notes'][] = sprintf(_('editors_platform_x_only'), $platforms[$addon['File']['platform_id']]);
+ }
+
+ //Featured?
+ //@TODO
+
+ //Site specific?
+ if ($addon['Addon']['sitespecific'] == 1) {
+ $addons[$k]['notes'][] = _('editors_site_specific');
+ }
+ //Pre-release?
+ if ($addon['Addon']['prerelease'] == 1) {
+ $addons[$k]['notes'][] = _('editors_pre-release');
+ }
+ //External software?
+ if ($addon['Addon']['externalsoftware'] == 1) {
+ $addons[$k]['notes'][] = _('editors_external_software');
}
}
}
-
- $addonOrAuthor = isset($filter['AddonOrAuthor']) ? $filter['AddonOrAuthor'] : '';
-
- $maxVersions = array();
- if (!empty($filter['Application'])) {
- $app_versions = $this->Appversion->findAllByApplicationId($filter['Application'],
- array('Appversion.id', 'Appversion.version'), 'Appversion.version DESC');
- foreach ($app_versions as $av) {
- $maxVersions[$av['Appversion']['id']] = $av['Appversion']['version'];
+ //pr($addons);
+ //Filters
+ $selected = array( 'Addontype' => array(),
+ 'Application' => array(),
+ 'Platform' => array(),
+ 'SubmissionType' => array()
+ );
+ $filtered = false;
+
+ if (!empty($this->data['Approval']['Addontype'])) {
+ foreach ($this->data['Approval']['Addontype'] as $option) {
+ $selected['Addontype'][$option] = true;
}
+ $filtered = true;
}
- $submissionAges = array('1' => '1', '2' => '2', '3' => '3', '4' => '4', '5' => '5',
- '6' => '6', '7' => '7', '8' => '8', '9' => '9', '10+' => '10+');
- $platforms = $this->Amo->getPlatformName();
- $applications = $this->Amo->getApplicationName();
-
- $filtered = !empty($filter);
- $filterChanged = $filtered && array_key_exists('filter', $this->params['form']);
- $filteredCount = $this->_getCount($mode, true);
-
- $sortOpts = $this->Editors->getQueueSort($mode);
+ if (!empty($this->data['Approval']['Application'])) {
+ foreach ($this->data['Approval']['Application'] as $option) {
+ $selected['Application'][$option] = true;
+ }
+ $filtered = true;
+ }
- // raw values for selectTags
- $this->set('selected', $selected);
+ if (!empty($this->data['Approval']['Platform'])) {
+ foreach ($this->data['Approval']['Platform'] as $option) {
+ $selected['Platform'][$option] = true;
+ }
+ $filtered = true;
+ }
+
+ if (!empty($this->data['Approval']['SubmissionType'])) {
+ foreach ($this->data['Approval']['SubmissionType'] as $option) {
+ $selected['SubmissionType'][$option] = true;
+ }
+ $filtered = true;
+ }
+
+ if (isset($this->data['filter'])) {
+ $filtered = true;
+ }
+ elseif (isset($this->data['clear'])) {
+ $filtered = false;
+ }
+
+ $this->publish('addons', $addons);
$this->set('platforms', $platforms);
$this->set('addontypes', $this->Addontype->getNames());
$this->set('applications', $applications);
- $this->set('maxVersions', $maxVersions);
- $this->set('submissionAges', $submissionAges);
-
- $this->publish('addonOrAuthor', $addonOrAuthor);
+ $this->set('submissionTypes', $submissionTypes);
+ $this->publish('selected', $selected);
$this->publish('filtered', $filtered);
- $this->publish('filterChanged', $filterChanged);
- $this->publish('filteredCount', $filteredCount);
- $this->publish('sortBy', $sortOpts['sortby']);
- $this->publish('sortDir', $sortOpts['direction']);
-
- $this->publish('mode', $mode);
- $this->publish('addons', $addons);
$this->render('queue');
}
@@ -303,8 +424,6 @@ class EditorsController extends AppController
}
}
- $this->pageTitle = $addon['Translation']['name']['string'] . ' :: ' . $this->pageTitle;
-
if (!empty($addon['Tag'])) {
foreach ($addon['Tag'] as $tag) {
$tags[] = $tag['id'];
@@ -375,10 +494,6 @@ class EditorsController extends AppController
} else {
$reviewType = 'pending';
}
-
- // count of filtered queue
- $filtered = (true && $this->Editors->getQueueFilter($reviewType));
- $filteredCount = $this->_getCount($reviewType, true);
// rank in nomination/update queue
if (isset($this->params['url']['num']) && is_numeric($this->params['url']['num']))
@@ -397,8 +512,6 @@ class EditorsController extends AppController
$this->publish('history', $history);
$this->publish('errors', $this->Error->errors);
$this->publish('reviewType', $reviewType, false);
- $this->publish('filtered', $filtered);
- $this->publish('filteredCount', $filteredCount);
$this->render('review');
}
@@ -408,7 +521,7 @@ class EditorsController extends AppController
* @param int $id The file id
*/
function file($id) {
- $this->Amo->clean($id);
+ $this->Amo->clean($id);
$this->File->id = $id;
if (!$file = $this->File->read()) {
@@ -434,698 +547,6 @@ class EditorsController extends AppController
}
exit;
}
-
-
- /**
- * Performance reports jump off point
- * Handles report selection, and user parameter
- */
- function performance($mode = '') {
- $session = $this->Session->read('User');
- if (!$this->SimpleAcl->actionAllowed('Editor', '*', $session)) {
- $this->Amo->accessDenied();
- }
-
- //Senior Editors can generate reports on anyone
- $isSenior = $this->SimpleAcl->actionAllowed('Admin', 'EditAnyAddon', $session);
- if ($isSenior && !empty($this->params['url']['user'])) {
- $user = $this->User->findByEmail($this->params['url']['user']);
- if (empty($user)) {
- header('HTTP/1.1 404 Not Found');
- $this->flash(___('editors_performance_user_not_found', 'User not found'), "/editors/performance/{$mode}");
- return;
- }
- } else {
- $user = $this->User->findById($session['id']);
- }
-
- //Chart AJAX
- // @TODO: enable this and make charts use ajax to load new data
- if (false && $mode == 'chartData') {
- $summary = !empty($this->params['url']['sum']) ? $this->params['url']['sum'] : '';
-
- if ($summary == 'month') {
- $data = $this->_performanceSummaryByMonth($user['User']['id'], 12);
- }
- elseif ($summary == 'cat') {
- $year = null;
- $month = null;
- if (!empty($this->params['url']['year'])) {
- $year = intval($this->params['url']['year']);
- }
- if (!empty($this->params['url']['month'])) {
- $month = intval($this->params['url']['month']);
- }
- $data = $this->_performanceSummaryByCategory($user['User']['id'], $year, $month);
- }
-
- $this->set('json', $data);
- $this->render('ajax/json', 'ajax');
- return;
- }
-
- // display name (or email if not set)
- $userName = trim("{$user['User']['firstname']} {$user['User']['lastname']}");
- if ($userName == '') {
- $userName = $user['User']['email'];
- }
-
- $this->publish('mode', $mode);
- $this->publish('user', $user);
- $this->publish('userName', $userName);
- $this->publish('showUserLookup', $isSenior);
- $this->publish('editors', $isSenior ? $this->_recentEditors() : array());
- $this->publish('collapse_categories', false);
- $this->publish('subpagetitle', ___('editors_performance_pagetitle', 'Performance Reports'));
- $this->set('page', 'performance');
-
- //Standard text report
- if ($mode == '') {
- $this->_performanceTable($user['User']['id']);
-
- //Charts
- } elseif ($mode == 'charts') {
- $this->_performanceCharts($user['User']['id']);
-
- } else {
- $this->redirect('/editors/performance');
- }
- return;
- }
-
-
- /**
- * Generate a detailed performance report with weekly totals and team averages
- * @param int $userId user to generate report for
- */
- function _performanceTable($userId) {
- // Initialize report data
- $myApprovals = array();
- $myTotal = 0;
- $teamTotal = 0;
- $teamSize = 0;
- $teamAverage = 0;
- $weeklyTotals = array();
- $myMtdTotal = 0;
- $teamMtdTotal = 0;
- $teamMtdAverage = 0;
- $myYtdTotal = 0;
- $teamYtdTotal = 0;
- $teamYtdSize = 0;
- $teamYtdAverage = 0;
-
- //Default conditions are the current month
- $ytdEndTime = strtotime('tomorrow');
- $startDate = date('Y-m-01');
- $startTime = strtotime($startDate);
- $endDate = ___('editors_date_filter_placeholder', 'YYYY-MM-DD');
- $endTime = $ytdEndTime;
-
- //If user has specified own conditions, use those
- if (!empty($this->params['url']['start'])) {
- $ts = strtotime($this->params['url']['start']);
- if ($ts !== false && $ts != -1) {
- $startTime = $ts;
- $startDate = $this->params['url']['start'];
- }
- }
- if (!empty($this->params['url']['end'])) {
- $ts = strtotime($this->params['url']['end']);
- if ($ts !== false && $ts != -1) {
- $endTime = strtotime('+1 day', $ts);
- $endDate = $this->params['url']['end'];
- }
- }
-
- //Initialize weekly data
- $week = array('from' => $startTime,
- 'to' => min(strtotime('next Monday', $startTime), $endTime)-1,
- 'myTotal' => 0, 'teamTotal' => 0, 'teamAverage' => 0);
- while ($week['from'] < $endTime) {
- $weeklyKey = $this->_makeYearWeekKey($week['from']);
- $weeklyTotals[$weeklyKey] = $week;
-
- $week = array('from' => $week['to']+1,
- 'to' => min(strtotime('+7 day', $week['to']), $endTime-1),
- 'myTotal' => 0, 'teamTotal' => 0, 'teamAverage' => 0);
- }
-
- //Fetch approvals over specified date range
- $conditions = array("Approval.created >= FROM_UNIXTIME('{$startTime}')",
- "Approval.created < FROM_UNIXTIME('{$endTime}')");
-
- $order = '`Approval`.`created` ASC';
- if ($approvals = $this->Approval->findAll($conditions, null, $order)) {
- foreach ($approvals as $k => $approval) {
- $weeklyKey = $this->_makeYearWeekKey(strtotime($approval['Approval']['created']));
- if (!array_key_exists($weeklyKey, $weeklyTotals)) {
- // this should never happen, but better to let there be obvious gaps in
- // weekly totals than seemingly legit (but probably bogus) counts
- continue;
- }
-
- //Fetch addon details for approvals by the report user
- if ($approval['User']['id'] == $userId) {
- $approval['Addon'] = $this->Addon->getAddon($approval['Approval']['addon_id'],
- array('list_details'));
- $myApprovals[] = $approval;
- $myTotal++;
- $weeklyTotals[$weeklyKey]['myTotal']++;
- }
- $teamTotal++;
- $weeklyTotals[$weeklyKey]['teamTotal']++;
- }
- }
-
- /* add formatting to aid in debugging
- foreach ($weeklyTotals as $k => $w) {
- $weeklyTotals[$k]['formatted'] =
- date('Y-m-d H:i:s', $w['from']).' - '.date('Y-m-d H:i:s', $w['to']);
- }
- pr($weeklyTotals); /**/
-
- // YTD and MTD calculations
- $sql = "SELECT MONTH(`Approval`.`created`) AS `month`, `User`.`id`, COUNT(*) AS `total`
- FROM `approvals` AS `Approval`
- LEFT JOIN `users` AS `User` ON (`User`.`id`=`Approval`.`user_id`)
- WHERE `Approval`.`created` >= '".date('Y')."-01-01 00:00:00'
- AND `Approval`.`created` < FROM_UNIXTIME('{$ytdEndTime}')
- GROUP BY `month`, `Approval`.`user_id`";
- if ($results = $this->Approval->query($sql)) {
- $thisMonth = date('m');
- foreach ($results as $row) {
- $teamYtdTotal += $row[0]['total'];
- $teamMtdTotal += ($row[0]['month'] == $thisMonth) ? $row[0]['total'] : 0;
- if ($row['User']['id'] == $userId) {
- $myYtdTotal += $row[0]['total'];
- $myMtdTotal += ($row[0]['month'] == $thisMonth) ? $row[0]['total'] : 0;
- }
- }
- }
-
- //Calculate averages
- $teamSize = $this->_teamSize($endTime);
- if ($teamSize) {
- $teamAverage = $teamTotal / $teamSize;
- foreach ($weeklyTotals as $k => $week) {
- $weeklyTotals[$k]['teamAverage'] = $week['teamTotal'] / $teamSize;
- }
- }
- $teamYtdSize = $this->_teamSize($ytdEndTime);
- if ($teamYtdSize) {
- $teamYtdAverage = $teamYtdTotal / $teamYtdSize;
- $teamMtdAverage = $teamMtdTotal / $teamYtdSize;
- }
-
- // Publish and render
- $this->publish('startDate', $startDate);
- $this->publish('endDate', $endDate);
-
- $this->publish('addonTypes', $this->Addontype->getNames());
- $this->publish('myApprovals', $myApprovals);
- $this->publish('myTotal', $myTotal);
- $this->publish('teamAverage', $teamAverage);
- $this->publish('weeklyTotals', $weeklyTotals);
- $this->publish('myMtdTotal', $myMtdTotal);
- $this->publish('teamMtdAverage', $teamMtdAverage);
- $this->publish('myYtdTotal', $myYtdTotal);
- $this->publish('teamYtdAverage', $teamYtdAverage);
-
- $this->render('performance_table');
- }
-
-
- /**
- * Generate charts showing yearly activity and category breakdowns
- * @param int $userId user to generate report for
- */
- function _performanceCharts($userId) {
- $byMonthData = $this->_performanceSummaryByMonth($userId, 12);
- $teamSize = $this->_teamSize(time());
-
- // category breakdown can be for an entire year, or a specific
- // month and year
- $year = date('Y');
- $month = null;
- if (!empty($this->params['url']['year'])) {
- $year = intval($this->params['url']['year']);
- }
- if (!empty($this->params['url']['month'])) {
- $month = intval($this->params['url']['month']);
- }
- $byCatData = $this->_performanceSummaryByCategory($userId, $year, $month);
-
- // points for x-axis labels (javascript)
- $monthlyTicks = array();
- foreach ($byMonthData['labels'] as $i => $label) {
- $this->_sanitizeArray($label);
- $monthlyTicks[] = "[{$i},'{$label}']";
- }
-
- // points for user activity (javascript)
- $userPoints = array();
- foreach ($byMonthData['usercount'] as $i => $n) {
- $userPoints[] = "[{$i},{$n}]";
- }
-
- // points for team activity (javascript)
- $teamPoints = array();
- foreach ($byMonthData['teamcount'] as $i => $n) {
- $n = $n / $teamSize;
- $teamPoints[] = "[{$i},{$n}]";
- }
-
- // pie chart color-scheme (javascript)
- $sliceColors = array("'#6d746a'","'#205f9a'","'#3d8128'","'#63522b'",
- "'#dc5313'","'#f3c01c'","'#bc1c39'");
-
- // pie chart labels (javascript)
- $sliceLabels = array();
- foreach ($byCatData['labels'] as $i => $label) {
- $this->_sanitizeArray($label);
- $sliceLabels[] = "'{$label}'";
- }
-
- // pie chart date title
- if ($month) {
- $pieTitleDate = strftime('%B %Y', mktime(12,0,0,$month,1,$year));
- } else {
- $pieTitleDate = $year;
- }
-
- // months for filter select
- $monthSelect = array(''=>'');
- for ($n = 1; $n<=12; $n++) {
- $monthSelect[$n] = strftime('%B', mktime(12,0,0,$n,1));
- }
-
- $this->set('monthlyTicksJS', implode(',', $monthlyTicks));
- $this->set('monthlyUserPointsJS', implode(',', $userPoints));
- $this->set('monthlyTeamPointsJS', implode(',', $teamPoints));
- $this->set('sliceColorsJS', implode(',', $sliceColors));
- $this->set('sliceLabelsJS', implode(',', $sliceLabels));
- $this->set('userPieDataJS', implode(',', $byCatData['usercount']));
- $this->set('teamPieDataJS', implode(',', $byCatData['teamcount']));
- $this->publish('year', $year);
- $this->publish('month', $month);
- $this->publish('monthSelect', $monthSelect);
- $this->publish('pieTitleDate', $pieTitleDate);
- $this->render('performance_charts');
- }
-
-
- /**
- * Generate data for monthly summary of user and team activity
- * @param int $userId user to generate report for
- * @param int $months number of months
- * @param int $endMonth last month of report (default current month)
- * @param int $endYear year of last month of report (default current year)
- * @return array
- */
- function _performanceSummaryByMonth($userId, $months=12, $endMonth=null, $endYear=null) {
- $user = $this->User->findById($userId);
- $data = array(
- 'email' => $user['User']['email'],
- 'firstname' => $user['User']['firstname'],
- 'lastname' => $user['User']['lastname'],
- 'labels' => array(),
- 'usercount' => array(),
- 'teamcount' => array());
-
- if (is_null($endMonth)) {
- $endMonth = date('n');
- }
- if (is_null($endYear)) {
- $endYear = date('Y');
- }
-
- $endTime = strtotime(sprintf('%04d-%02d-01 00:00:00 +1 month', $endYear, $endMonth));
- $startTime = strtotime(sprintf('-%d month', $months), $endTime);
-
- $sql = "SELECT DATE_FORMAT(`Approval`.`created`, '%Y-%m') AS yearmonth,
- `Approval`.`created`, `User`.`id`, COUNT(*) AS `total`
- FROM `approvals` AS `Approval`
- LEFT JOIN `users` AS `User` ON (`User`.`id`=`Approval`.`user_id`)
- WHERE `Approval`.`created` >= FROM_UNIXTIME('{$startTime}')
- AND `Approval`.`created` < FROM_UNIXTIME('{$endTime}')
- GROUP BY yearmonth, `Approval`.`user_id`";
-
- $results = $this->Approval->query($sql);
- foreach ($results as $row) {
- $label = strftime('%b %Y', strtotime($row['Approval']['created']));
- if (!in_array($label, $data['labels'])) {
- $data['labels'][] = $label;
- $data['teamcount'][] = 0;
- $data['usercount'][] = 0;
- }
- $i = count($data['labels']) - 1;
- $data['teamcount'][$i] += $row[0]['total'];
- if ($row['User']['id'] == $userId) {
- $data['usercount'][$i] += $row[0]['total'];
- }
- }
-
- return $data;
- }
-
-
- /**
- * Generate data for category breakdown summary for user and team
- * @param int $userId user to generate report for
- * @param int $year year (default: current year)
- * @param int $month month to summarize (default: generate data for entire year)
- * @return array
- */
- function _performanceSummaryByCategory($userId, $year=null, $month=null) {
- $user = $this->User->findById($userId);
- $data = array(
- 'email' => $user['User']['email'],
- 'firstname' => $user['User']['firstname'],
- 'lastname' => $user['User']['lastname'],
- 'labels' => array(),
- 'usercount' => array(),
- 'teamcount' => array());
-
- $addonTypes = $this->Addontype->getNames();
- asort($addonTypes);
-
- $addonTypeKeys = array();
- foreach ($addonTypes as $key => $val) {
- $addonTypeKeys[] = $key;
- $data['labels'][] = $val;
- $data['usercount'][] = 0;
- $data['teamcount'][] = 0;
- }
-
- // single month or year summary breakdown by category
- // default date range is current year
- if (is_null($year)) {
- $year = date('Y');
- }
-
- if ($month > 0) {
- $startTime = strtotime(sprintf('%d-%02d-01 00:00:00', $year, $month));
- $endTime = strtotime('+1 month', $startTime);
- } else {
- $startTime = strtotime(sprintf('%d-01-01 00:00:00', $year));
- $endTime = strtotime('+1 year', $startTime);
- }
-
- $sql = "SELECT `Addon`.`addontype_id`, `User`.`id`, COUNT(*) AS `total`
- FROM `approvals` AS `Approval`
- LEFT JOIN `users` AS `User` ON (`User`.`id`=`Approval`.`user_id`)
- LEFT JOIN `addons` AS `Addon` ON (`Addon`.`id`=`Approval`.`addon_id`)
- WHERE `Approval`.`created` >= FROM_UNIXTIME('{$startTime}')
- AND `Approval`.`created` < FROM_UNIXTIME('{$endTime}')
- GROUP BY `Approval`.`user_id`, `Addon`.`addontype_id`";
-
- $results = $this->Approval->query($sql);
- foreach ($results as $row) {
- $i = array_search($row['Addon']['addontype_id'], $addonTypeKeys);
- if ($i === false) {
- continue; // approvals should always have a known addontype ?
- }
- $data['teamcount'][$i] += $row[0]['total'];
- if ($row['User']['id'] == $userId) {
- $data['usercount'][$i] += $row[0]['total'];
- }
- }
-
- return $data;
- }
-
-
- /**
- * AJAX Add-on and Author email lookup
- */
- function addonAndAuthorLookup($queue='pending') {
- if (!$this->SimpleAcl->actionAllowed('Admin', '%', $this->Session->read('User')) ||
- !$this->SimpleAcl->actionAllowed('Editor', '*', $this->Session->read('User')) ) {
- $this->Amo->accessDenied();
- }
-
- $text = $_REQUEST['q'];
- $this->Amo->clean($text, false);
- $addonsAndEmails = array();
-
- if (strlen($text) > 0 && in_array($queue, array('pending', 'nominated'))) {
- // Use the base filter components to limit results to those in the queue
- $sql_base = $this->Editors->baseQueueFilterQuery($queue);
-
- // search localized addon names
- $sql = "SELECT DISTINCT IFNULL(`tr_l`.`localized_string`, `tr_en`.`localized_string`) AS `lname`
- {$sql_base['FROM']}
- {$sql_base['JOIN']}
- LEFT JOIN `translations` AS `tr_l` ON
- (`tr_l`.`id`=`Addon`.`name` AND `tr_l`.`locale`='".LANG."')
- LEFT JOIN `translations` AS `tr_en` ON
- (`tr_en`.`id`=`Addon`.`name` AND `tr_en`.`locale`=`Addon`.`defaultlocale`)
- {$sql_base['WHERE']}
- AND IFNULL(`tr_l`.`localized_string`, `tr_en`.`localized_string`) LIKE '%{$text}%'
- ORDER BY `lname` ASC";
-
- $results = $this->Version->query($sql);
- if (!empty($results)) {
- foreach ($results as $row) {
- $addonsAndEmails[] = $row[0]['lname'];
- }
- }
-
- // search localized addon support emails
- $emails = array();
- $sql = "SELECT IFNULL(`tr_l`.`localized_string`, `tr_en`.`localized_string`) AS `lemail`
- {$sql_base['FROM']}
- {$sql_base['JOIN']}
- LEFT JOIN `translations` AS `tr_l` ON
- (`tr_l`.`id`=`Addon`.`supportemail` AND `tr_l`.`locale`='".LANG."')
- LEFT JOIN `translations` AS `tr_en` ON
- (`tr_en`.`id`=`Addon`.`supportemail` AND `tr_en`.`locale`=`Addon`.`defaultlocale`)
- {$sql_base['WHERE']}
- AND IFNULL(`tr_l`.`localized_string`, `tr_en`.`localized_string`) LIKE '%{$text}%'";
-
- $results = $this->Version->query($sql);
- if (!empty($results)) {
- foreach ($results as $row) {
- $emails[] = $row[0]['lemail'];
- }
- }
-
- // search author emails
- $sql = "SELECT `User`.`email`
- {$sql_base['FROM']}
- {$sql_base['JOIN']}
- LEFT JOIN `addons_users` AS `au` ON (`Addon`.`id`=`au`.`addon_id`)
- LEFT JOIN `users` AS `User` ON (`au`.`user_id`=`User`.`id`)
- {$sql_base['WHERE']}
- AND `au`.`role` IN(".AUTHOR_ROLE_ADMINOWNER.","
- .AUTHOR_ROLE_ADMIN.","
- .AUTHOR_ROLE_OWNER.","
- .AUTHOR_ROLE_DEV.")
- AND `User`.`email` LIKE '%{$text}%'";
-
- $results = $this->Version->query($sql);
- if (!empty($results)) {
- foreach ($results as $row) {
- $emails[] = $row['User']['email'];
- }
- }
-
- // sort, dedup, and merge
- sort($emails);
- $emails = array_unique($emails);
- $addonsAndEmails = array_merge($addonsAndEmails, $emails);
- }
-
- $this->set('addonsAndEmails', $addonsAndEmails);
- $this->render('ajax/addon_and_author_lookup', 'ajax');
- }
-
- /**
- * AJAX action for looking up appversions for the specified app
- * @param int $app_id The application id
- */
- function appversionLookup($app_id) {
- $this->Amo->clean($app_id);
- $results = $this->Appversion->findAllByApplicationId($app_id,
- array('Appversion.id', 'Appversion.version'), 'Appversion.version DESC');
- $appversions = array();
- foreach ($results as $av) {
- $appversions[] = $av['Appversion'];
- }
-
- $this->publish('appversions', $appversions);
- $this->render('ajax/appversion_lookup', 'ajax');
- }
-
- /**
- * Count the number of (possibly filtered) items in the specified queue
- * @param string $queue
- * @param bool $useFilter (default=false)
- * @return int
- * @todo possibly cache results
- */
- function _getCount($queue, $useFilter=false) {
- $result = null;
-
- if ($useFilter && $this->Editors->buildQueueFilterQuery($queue)) {
- $sql = $this->Editors->buildQueueFilterQuery($queue);
- $result = $this->Addon->query(
- "SELECT COUNT(*) {$sql['FROM']} {$sql['JOIN']} {$sql['WHERE']}");
-
- } elseif ($queue == 'pending') {
- $result = $this->File->query(
- "SELECT COUNT(*) FROM `files` WHERE `status`=".STATUS_PENDING." GROUP BY `status`");
-
- } elseif ($queue == 'nominated') {
- $result = $this->Addon->query(
- "SELECT COUNT(*) FROM `addons` WHERE `status`=".STATUS_NOMINATED." GROUP BY `status`");
-
- } elseif ($queue == 'reviews') {
- $result = $this->Review->query(
- "SELECT COUNT(*) FROM `reviews` WHERE `editorreview`=1 GROUP BY `editorreview`");
- }
-
- $count = !empty($result) ? $result[0][0]['COUNT(*)'] : 0;
-
- return $count;
- }
-
- /**
- * Fetch an array of (possibly filtered) addons for the specified queue
- * @param string $queue
- * @return array
- */
- function _buildQueue($queue) {
- if (!in_array($queue, array('pending', 'nominated'))) {
- return array();
- }
-
- $sql = $this->Editors->buildQueueFilterQuery($queue);
-
- // Setup pagination
- $this->Pagination->total = $this->_getCount($queue, true);
-
- $_pagination_options = array();
- if ($queue == 'pending') {
- if (!array_key_exists('show', $_GET) && $this->Session->read('editor_queue_pending_show')) {
- $_pagination_options['show'] = $this->Session->read('editor_queue_pending_show');
- } else {
- // If $_GET['show'] exists it overrides this in the pagination component
- $_pagination_options['show'] = 50;
- }
- list($not_used,$_limit,$_page) = $this->Pagination->init(null, null, $_pagination_options);
- $this->Session->write('editor_queue_pending_show', $_limit);
-
- } else {
- if (!array_key_exists('show', $_GET) && $this->Session->read('editor_queue_nominated_show')) {
- $_pagination_options['show'] = $this->Session->read('editor_queue_nominated_show');
- } else {
- // If $_GET['show'] exists it overrides this in the pagination component
- $_pagination_options['show'] = 50;
- }
- list($not_used,$_limit,$_page) = $this->Pagination->init(null,null,$_pagination_options);
- $this->Session->write('editor_queue_nominated_show', $_limit);
- }
-
- $_offset = ($_page > 0) ? $_limit * ($_page-1) : 0; // no negative offsets, thank you
-
- $extra_fields = '';
- if ($queue == 'pending') {
- $extra_fields .= ", `File`.`id`, `File`.`platform_id`";
- }
-
- // Fetch the queue
- $queue_sql = "SELECT
- `Version`.`id`,
- `Version`.`addon_id`,
- `Version`.`version`,
- `Version`.`created`,
- `Version`.`modified`
- {$extra_fields}
- {$sql['FROM']}
- {$sql['JOIN']}
- {$sql['WHERE']}
- {$sql['ORDER']}
- LIMIT {$_limit} OFFSET {$_offset}";
-
- $addons = $this->Version->query($queue_sql);
-
- //Merge in Addon details
- if (!empty($addons)) {
- foreach ($addons as $k => $addon) {
- $addon = $this->Addon->findById($addon['Version']['addon_id'],
- array('Addon.id',
- 'Addon.name', 'Addon.defaultlocale',
- 'Addon.addontype_id', 'Addon.prerelease',
- 'Addon.sitespecific', 'Addon.externalsoftware',
- 'Addon.created', 'Addon.nominationdate'), '', 0);
- $addons[$k] = array_merge_recursive($addons[$k], $addon);
- }
- }
-
- $platforms = $this->Amo->getPlatformName();
- $applications = $this->Amo->getApplicationName();
-
- //make modifications to the queue array
- if (!empty($addons)) {
- foreach ($addons as $k => $addon) {
- //get min/max versions
- if ($targetApps = $this->Amo->getMinMaxVersions($addon['Version']['id'])) {
- foreach ($targetApps as $targetApp) {
- $appName = $targetApp['translations']['localized_string'];
- $addons[$k]['targetApps'][$appName]['min'] = $targetApp['min']['version'];
- $addons[$k]['targetApps'][$appName]['max'] = $targetApp['max']['version'];
- }
- }
-
- //Age
- if ($queue == 'pending') {
- $age = time() - strtotime($addon['Version']['created']);
- }
- elseif ($queue == 'nominated') {
- $age = time() - strtotime($addon['Addon']['created']);
- $nominationage = time() - strtotime($addon['Addon']['nominationdate']);
- $addons[$k]['nominationage'] = $this->_humanizeAge($nominationage);
- }
-
- $addons[$k]['age'] = $this->_humanizeAge($age);
-
- //Generate any additional notes
- $addons[$k]['notes'] = array();
-
- //Platform-specific?
- if (!empty($addon['Version'][0]['File'][0]['platform_id']) && $addon['Version'][0]['File'][0]['platform_id'] != 1) {
- $os = array();
- foreach ($addon['Version'][0]['File'] as $file) {
- $os[] = $platforms[$file['platform_id']];
- }
- $addons[$k]['notes'][] = sprintf(_('editors_platform_x_only'), implode(', ', $os));
- }
- elseif (!empty($addon['File']['platform_id']) && $addon['File']['platform_id'] != 1) {
- $addons[$k]['notes'][] = sprintf(_('editors_platform_x_only'), $platforms[$addon['File']['platform_id']]);
- }
-
- //Featured?
- //@TODO
-
- //Site specific?
- if ($addon['Addon']['sitespecific'] == 1) {
- $addons[$k]['notes'][] = _('editors_site_specific');
- }
- //Pre-release?
- if ($addon['Addon']['prerelease'] == 1) {
- $addons[$k]['notes'][] = _('editors_pre-release');
- }
- //External software?
- if ($addon['Addon']['externalsoftware'] == 1) {
- $addons[$k]['notes'][] = _('editors_external_software');
- }
- }
- }
- //pr($addons);
-
- return $addons;
- }
/**
* Moderated Reviews Queue
@@ -1448,87 +869,6 @@ class EditorsController extends AppController
$this->set('page', 'reviewlog');
$this->render('reviewlog');
}
-
- /* Humanizes a Unix Timestamp */
- function _humanizeAge($age) {
- $humanized = '';
-
- //days
- if ($age >= (60*60*24*2)) {
- $humanized = sprintf(_('editors_x_days'), floor($age/(60*60*24)));
- }
- //1 day
- elseif ($age >= (60*60*24)) {
- $humanized = _('editors_one_day');
- }
- //hours
- elseif ($age >= (60*60*2)) {
- $humanized = sprintf(_('editors_x_hours'), floor($age/(60*60)));
- }
- //hour
- elseif ($age >= (60*60)) {
- $humanized = _('editors_one_hour');
- }
- //minutes
- elseif ($age > 60) {
- $humanized = sprintf(_('editors_x_minutes'), floor($age/60));
- }
- //minute
- else {
- $humanized = _('editors_one_minute');
- }
-
- return $humanized;
- }
-
- /* Generate a sortable key from the given timestamp in the form of 'YYYY-WW' */
- function _makeYearWeekKey($timestamp) {
- $year = date('Y', $timestamp);
- $week = date('W', $timestamp);
-
- // the end of December is often part of the first week for the following year
- if ($week == '01' && date('m', $timestamp) == '12') {
- $year++;
- }
- return "{$year}-{$week}";
- }
-
- /* Approximate team size at a point in time */
- function _teamSize($timestamp) {
- $this->Amo->clean($timestamp);
-
- // Count the number of unique users that submitted a review during
- // the 60 days leading up to the time specified.
- $teamSize = 0;
- $sql = "SELECT COUNT(DISTINCT `Approval`.`user_id`) AS `teamSize`
- FROM `approvals` AS `Approval`
- WHERE `Approval`.`created` < FROM_UNIXTIME('{$timestamp}')
- AND `Approval`.`created` >= FROM_UNIXTIME('".strtotime('-60 day', $timestamp)."')";
- if ($results = $this->Approval->query($sql)) {
- $teamSize = $results[0][0]['teamSize'];
- }
- return $teamSize;
- }
-
- /* Fetch emails of all editors active in the last reviewDays days */
- function _recentEditors($reviewDays=90) {
- $this->Amo->clean($reviewDays);
-
- $sql = "SELECT DISTINCT `User`.`email`
- FROM `approvals` AS `Approval`
- INNER JOIN `users` AS `User` ON (`User`.`id`=`Approval`.`user_id`)
- WHERE `Approval`.`created` >= FROM_UNIXTIME('".strtotime("-{$reviewDays} day")."')
- ORDER BY `User`.`email` ASC";
-
- $editors = array();
- if ($results = $this->Approval->query($sql)) {
- foreach ($results as $user) {
- $editors[] = $user['User']['email'];
- }
- }
-
- return $editors;
- }
}
?>
diff --git a/site/app/controllers/files_controller.php b/site/app/controllers/files_controller.php
index 694085d..e662400 100644
--- a/site/app/controllers/files_controller.php
+++ b/site/app/controllers/files_controller.php
@@ -72,7 +72,7 @@ class FilesController extends AppController
$this->File->id = $file_id;
if (!$file = $this->File->read()) {
- $this->flash(_('error_file_notfound'), '/');
+ $this->flash($file_id, '/');
return;
}
$this->Addon->id = $file['Version']['addon_id'];
@@ -85,7 +85,7 @@ class FilesController extends AppController
}
$addontype = $addon['Addon']['addontype_id'];
- $startfile = 'install.rdf';
+ $startfile = 'install.rdf2';
$path = REPO_PATH.'/'.$this->Addon->id.'/'.$file['File']['filename'];
if (!file_exists($path)) {
@@ -116,14 +116,12 @@ class FilesController extends AppController
foreach ($contents as $content) {
$isJar = false;
- if ($addontype == ADDON_EXTENSION) {
- $paths = split("/", $content['filename'], 2);
- $pathinfo = pathinfo($path);
- if ($pathinfo['extension'] == '.xo')
- $startfile = $paths[0].'/activity/activity.info';
- else
- $startfile = $paths[0].'/library/library.info';
- }
+ // we are sugar
+ $paths = split("/", $content['filename'], 2);
+ if ($addontype == ADDON_CONTENT)
+ $startfile = $paths[0].'/library/library.info';
+ else
+ $startfile = $paths[0].'/activity/activity.info';
if (substr($content['filename'], strrpos($content['filename'], '.')) == '.jar') {
$content['folder'] = 1;
@@ -169,7 +167,7 @@ class FilesController extends AppController
$contents = $this->_get_contents($path, $file, $addontype);
if (is_bool($contents) && $contents == false) {
- $this->flash(_('error_file_notfound'), '/');
+ $this->flash($file, '/');
return;
}
$this->publish('filename', $file);
diff --git a/site/app/controllers/images_controller.php b/site/app/controllers/images_controller.php
index b25ec59..d20353d 100644
--- a/site/app/controllers/images_controller.php
+++ b/site/app/controllers/images_controller.php
@@ -22,7 +22,6 @@
* Contributor(s):
* Andrei Hajdukewycz <sancus@off.net> (Original Author)
* Justin Scott <fligtar@mozilla.com>
- * Frederic Wenzel <fwenzel@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -40,7 +39,7 @@
class ImagesController extends AppController
{
var $name = 'Images';
- var $uses = array('Addon', 'Collection', 'Preview');
+ var $uses = array('Addon', 'Preview');
var $components = array('Image');
var $autoRender = false;
@@ -69,22 +68,6 @@ class ImagesController extends AppController
}
/**
- * Renders the icon for the specified add-on
- * @param int $addon_id ID of the add-on
- * @param int $timestamp timestamp of last update (optional)
- * @param bool $cache whether to memcache or not (optional)
- */
- function collection_icon($collection_id, $timestamp = '', $cache = true) {
- if ($cache !== true) {
- $this->Collection->caching = false;
- }
-
- if (!empty($collection_id)) {
- $this->Image->renderCollectionIcon($collection_id);
- }
- }
-
- /**
* Renders the full-size preview with the ID specified
* @param int $preview_id ID of the preview to render
* @param int $timestamp timestamp of last update (optional)
diff --git a/site/app/controllers/pages_controller.php b/site/app/controllers/pages_controller.php
index 2dd39d0..c22cd47 100644
--- a/site/app/controllers/pages_controller.php
+++ b/site/app/controllers/pages_controller.php
@@ -44,8 +44,8 @@ class PagesController extends AppController{
var $name = 'Pages';
var $helpers = array('Html', 'Localization');
- var $components = array('Image', 'Pagination');
- var $uses = array('Addon', 'Collection', 'File', 'Platform', 'User');
+ var $components = array('Pagination');
+ var $uses = array('User');
var $securityLevel = 'low';
@@ -109,21 +109,6 @@ class PagesController extends AppController{
$title = ___('page_title_submissionhelp', 'Submission Help'); break;
case 'faq':
$title = ___('page_title_faq', 'Frequently Asked Questions'); break;
- case 'developer_faq':
- $title = ___('page_title_developer_faq'); break;
- case 'collector':
- $title = ___('page_title_collector');
- $this->publish('collectionSearch', true); break;
- case 'collector_faq':
- $title = ___('page_title_collector_faq');
- $this->publish('collectionSearch', true); break;
- case 'collector_features':
- $title = ___('page_title_collector_features');
- $this->publish('collectionSearch', true); break;
- case 'collector_firstrun':
- $this->set('jsAdd', array('amo2009/collections'));
- $title = ___('page_title_collector_firstrun');
- $this->publish('collectionSearch', true); break;
default:
if (!empty($path[$count - 1])) {
$title = ucfirst($path[$count - 1]);
diff --git a/site/app/controllers/reviews_controller.php b/site/app/controllers/reviews_controller.php
index a62c557..f1dad56 100644
--- a/site/app/controllers/reviews_controller.php
+++ b/site/app/controllers/reviews_controller.php
@@ -48,7 +48,7 @@ class ReviewsController extends AppController
var $components = array('Amo', 'Pagination', 'Session');
var $helpers = array('Html', 'Link', 'Localization', 'Pagination', 'Time');
var $namedArgs = true;
- var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox', 'checkAdvancedSearch');
+ var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox');
var $securityLevel = 'low';
@@ -552,9 +552,11 @@ class ReviewsController extends AppController
// mark review for editor approval
$this->Review->id = $reviewid;
if (!$error && $this->Review->saveField('editorreview', 1)) {
+ // @partial translation fallback, 5/22/08
$this->publish('msg', ___('review_flag_success',
'Thanks; this review has been flagged for editor approval.'));
} else {
+ // @partial translation fallback, 5/22/08
if (!isset($this->viewVars['msg']))
$this->publish('msg', ___('review_flag_error',
'Error flagging this review!'));
diff --git a/site/app/controllers/search_controller.php b/site/app/controllers/search_controller.php
index 670bc15..d2cba55 100644
--- a/site/app/controllers/search_controller.php
+++ b/site/app/controllers/search_controller.php
@@ -53,8 +53,8 @@ class SearchController extends AppController
/**
* Cake array for what tables this controller accesses
*/
- var $uses = array('Addon', 'Addontype', 'Collection', 'File', 'Translation', 'Platform', );
- var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox', 'checkAdvancedSearch');
+ var $uses = array('Addon', 'Addontype', 'Translation', 'Platform', );
+ var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox');
/**
* Holds the sanitize component, used to clean variables in our custom queries
@@ -66,7 +66,7 @@ class SearchController extends AppController
var $helpers = array('Javascript', 'Pagination', 'Time');
// components to be used by this controller
- var $components = array('Image', 'Pagination', 'Search', "Versioncompare", "Amo", "CollectionsListing");
+ var $components = array('Image', 'Pagination', 'Search', "Versioncompare", "Amo");
// view layout
var $layout = 'mozilla';
@@ -109,6 +109,15 @@ class SearchController extends AppController
$_terms = '';
}
$this->publish('search_terms', $_terms);
+
+ if (!empty($this->params['url']['cat'])) {
+ $category = explode(',', $this->params['url']['cat']);
+ if (count($category) != 2 || !is_numeric($category[0]) ||
+ !is_numeric($category[1]))
+ $category = array(0,0);
+ } else
+ $category = array(0,0);
+ $this->publish('category', $category);
//if advanced search appid set, use it
$appname = "";
@@ -121,21 +130,6 @@ class SearchController extends AppController
}
$this->publish('appid', APP_ID); //publish for element caching
- // collection search is a special case
- if (!empty($this->params['url']['cat']) && ($this->params['url']['cat'] == 'collections')) {
- $this->_collections($_terms);
- return;
- }
-
- if (!empty($this->params['url']['cat'])) {
- $category = explode(',', $this->params['url']['cat']);
- if (count($category) != 2 || !is_numeric($category[0]) ||
- !is_numeric($category[1]))
- $category = array(0,0);
- } else
- $category = array(0,0);
- $this->publish('category', $category);
-
//if advanced search atype set, use it.
$atype = -1;
$addon_types = $this->Addontype->getNames();
@@ -166,8 +160,7 @@ class SearchController extends AppController
$this->publish('sort', $sort); //publish for element caching
//if advanced search hver and lver set (for version range), use the
- $hver = 'any';
- $lver = -1;
+ $hver = $lver = -1;
$vfuz = false;
if (isset($this->params['url']['lver']) && isset( $this->params['url']['hver']) && isset( $this->params['url']['vfuz'])) {
$hver = $this->params['url']['hver'];
@@ -254,48 +247,6 @@ class SearchController extends AppController
return $this->index(); // let index handle rss action
}
-
- /**
- * Search collections
- */
- function _collections($terms = '') {
- //search
- $_result_ids = $this->Search->searchCollections($terms);
-
- //if advanced search pagination set, use it.
- $pp = 10;
- if (isset( $this->params['url']['pp']) && in_array($this->params['url']['pp'], $this->Pagination->resultsPerPage)) {
- $pp = $this->params['url']['pp'];
- }
- $this->publish('pp', $pp); //publish for element caching
-
- // Fetch a sorted page of collections
- $page_options = array('show' => $pp);
- $collections = $this->CollectionsListing->fetchPage($_result_ids, $page_options);
-
- // Our view needs the current sort options
- list($sort_opts, $sortby) = $this->CollectionsListing->sorting();
-
- // Prep and render the view
- $this->pageTitle = ___('search_collections_pagetitle', 'Collection Search Results').' :: '.sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME);
-
- $this->publish('jsAdd', array('amo2009/collections', 'jquery-ui/jqModal.js'));
- $this->publish('breadcrumbs', array(
- sprintf(___('addons_home_pagetitle'), APP_PRETTYNAME) => '/',
- ___('collections_breadcrumb') => '/collections'
- ));
-
- $this->publish('collapse_categories', true);
- $this->publish('collectionSearch', true);
- $this->publish('query', $terms);
- $this->publish('sort_opts', $sort_opts);
- $this->publish('sortby', $sortby);
- $this->publish('collections', $collections);
- $this->forceCache();
- $this->render('collections');
- return;
- }
-
}
?>
diff --git a/site/app/controllers/statistics_controller.php b/site/app/controllers/statistics_controller.php
index b6a7ffd..7acf45e 100644
--- a/site/app/controllers/statistics_controller.php
+++ b/site/app/controllers/statistics_controller.php
@@ -41,7 +41,7 @@ class StatisticsController extends AppController
var $name = 'Statistics';
var $uses = array('Addon', 'Addontype', 'Application', 'User', 'Version');
var $components = array('Amo', 'Image', 'Stats');
- var $helpers = array('Html', 'Javascript', 'Listing', 'Localization', 'Statistics', 'Time');
+ var $helpers = array('Html', 'Javascript', 'Listing', 'Localization', 'Time');
/**
* Require login for all actions
@@ -56,7 +56,7 @@ class StatisticsController extends AppController
// Clean post data
$this->Amo->clean($this->data);
- $this->layout = 'amo2009';
+ $this->layout = 'mozilla';
$this->pageTitle = _('statistics_pagetitle').' :: '.sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME);
$this->cssAdd = array('stats/stats');
@@ -78,10 +78,6 @@ class StatisticsController extends AppController
* Index
*/
function index($addon_id = 0) {
-
- // Get public stats for dashboard.
- $this->publish('dailyStats',$this->Stats->getDailyStats());
-
// If add-on id was specified, go to its statistics
if (!empty($addon_id) || !empty($_GET['data']['Addon']['id'])) {
if (!empty($addon_id))
@@ -94,11 +90,7 @@ class StatisticsController extends AppController
// If not, figure out what to do
else {
$session = $this->Session->read('User');
- if ($session) {
- $addons = $this->Addon->getAddonsByUser($session['id']);
- } else {
- $addons = array();
- }
+ $addons = $this->Addon->getAddonsByUser($session['id']);
$this->publish('addons', $addons);
// If user can access all add-on stats, pull all
@@ -148,6 +140,7 @@ class StatisticsController extends AppController
return;
}
+ $this->publish('suppressJQuery', true);
$this->jsAdd = array(
//'simile/timeplot/timeplot-api.js?local',
'jquery-compressed.js',
@@ -218,23 +211,6 @@ class StatisticsController extends AppController
$stats['last_downloads'] = $statsQry[0]['download_counts']['count'];
$stats['last_downloads_date'] = $statsQry[0]['download_counts']['date'];
}
- // Grouping by week is not quite what we want, since the current
- // week is going to be shorter than (the complete) last week.
- // If you know how to get (now, now - 7), (now - 8, now - 14) ranges
- // in a group by, feel free to improve this.
- $thisWeek = $this->Addon->query("SELECT AVG(count) as `count` FROM update_counts
- WHERE addon_id={$addon_id}
- AND date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)");
- $prevWeek = $this->Addon->query("SELECT AVG(count) as `count` FROM update_counts
- WHERE addon_id={$addon_id}
- AND date <= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
- AND date >= DATE_SUB(CURDATE(), INTERVAL 14 DAY)");
- if ($thisWeek && $prevWeek) {
- $thisWeek = $thisWeek[0][0]['count'];
- $prevWeek = $prevWeek[0][0]['count'];
- $stats['weekly_updatepings'] = $thisWeek;
- $stats['weekly_updatepings_change'] = $prevWeek > 0 ? (($thisWeek - $prevWeek) / $prevWeek) * 100 : 0;
- }
}
$this->set('stats', $stats);
$this->pageTitle = $addon['Translation']['name']['string'].' :: '._('statistics_pagetitle').' :: '.sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME);
@@ -276,7 +252,7 @@ class StatisticsController extends AppController
'statistics_js_plotselection_options_csv_tooltip' => _('statistics_js_plotselection_options_csv_tooltip')
));
- $this->render('addon', 'amo2009');
+ $this->render('addon', 'mozilla');
}
else {
$this->publish('rss_title', sprintf(_('statistics_title_addon_stats'), $addon['Translation']['name']['string']));
diff --git a/site/app/controllers/tests_controller.php b/site/app/controllers/tests_controller.php
index 05893ca..a9a9c89 100644
--- a/site/app/controllers/tests_controller.php
+++ b/site/app/controllers/tests_controller.php
@@ -37,7 +37,6 @@
*/
vendor('simpletest/reporter');
vendor('simpletest'.DS.'unit_tester', 'simpletest'.DS.'web_tester', 'simpletest'.DS.'mock_objects', 'simpletest'.DS.'xml', 'simpletest'.DS.'remote');
-vendor('phpQuery/phpQuery');
require_once(TESTS.'test_manager.php');
require_once(TESTS.'groups.php');
require_once(TESTS.'cake_reporter.php');
diff --git a/site/app/controllers/users_controller.php b/site/app/controllers/users_controller.php
index a848e4e..485571c 100644
--- a/site/app/controllers/users_controller.php
+++ b/site/app/controllers/users_controller.php
@@ -41,12 +41,12 @@
class UsersController extends AppController
{
var $name = 'Users';
- var $uses = array('User', 'Addon', 'Collection', 'Eventlog', 'Review', 'Version');
+ var $uses = array('User', 'Addon', 'Eventlog', 'Review', 'Version');
var $components = array('Amo', 'Email', 'Ldap', 'Session', 'Pagination', 'Recaptcha');
var $helpers = array('Html', 'Link', 'Javascript');
- var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox', 'checkAdvancedSearch');
+ var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox');
var $exceptionCSRF = array("/users/login", "/users/register", "/users/pwreset");
- var $layout = 'amo2009';
+ var $layout = 'mozilla';
var $namedArgs = true;
var $securityLevel = 'high';
@@ -110,7 +110,7 @@ class UsersController extends AppController
$this->Amo->clean($this->data);
$this->User->data = $this->data;
// hash password(s)
- $this->User->data['User']['password'] = $this->User->createPassword($this->User->data['User']['password']);
+ $this->User->data['User']['password'] = md5($this->User->data['User']['password']);
// compare passwords
if ($this->data['User']['password'] !== $this->data['User']['confirmpw'])
@@ -238,8 +238,7 @@ class UsersController extends AppController
} else {
// user found: send pw reset URL via email
$this->publish('data', $thisuser);
- $resetCode = $this->User->setResetCode($thisuser['User']['id']);
- $this->publish('resetcode', $resetCode);
+ $this->publish('resetcode', md5($thisuser['User']['password']));
$this->Email->template = 'email/pwreset';
$this->Email->to = $this->data['User']['email'];
$this->Email->subject = sprintf(_('user_email_pwreset_subject'), APP_PRETTYNAME);
@@ -250,16 +249,7 @@ class UsersController extends AppController
}
return;
}
-
- // id and/or code was sent, make sure the page isn't cached.
- $this->disableCache();
-
- // Remove 'id/resetcode' from the URI so it doesn't get echoed.
- $_SERVER['REQUEST_URI'] = preg_replace('@pwreset/.*$@', 'pwreset/', $_SERVER['REQUEST_URI']);
- if (isset($this->params['url']['url'])) {
- $this->params['url']['url'] = preg_replace('@pwreset/.*$@', 'pwreset/', $this->params['url']['url']);
- }
-
+
if (!$id || !$code) {
$this->flash(sprintf(_('error_missing_argument'), 'user_id or code'), '/', 3);
return;
@@ -271,8 +261,7 @@ class UsersController extends AppController
return;
}
- if (!$this->User->checkResetCode($id, $code)) {
- // TODO: update message re: expiration
+ if ($code !== md5($thisuser['User']['password'])) {
$this->flash(_('error_user_badconfirmationcode'), '/', 3);
return;
}
@@ -297,7 +286,7 @@ class UsersController extends AppController
// store new pw
$newpw = array();
- $newpw['User']['password'] = $this->User->createPassword($this->data['User']['password']);
+ $newpw['User']['password'] = md5($this->data['User']['password']);
$this->User->id = $id;
$this->User->save($newpw);
// success
@@ -356,7 +345,7 @@ class UsersController extends AppController
return;
}
- if ($this->User->checkPassword($someone['User'], $this->data['Login']['password'])) {
+ if (!empty($someone['User']['password']) && $someone['User']['password'] == md5($this->data['Login']['password'])) {
//Set expiration to two weeks if they check 'remember me'
$expirationTime = isset($this->data['Login']['remember']) ? 60*60*24*7*2 : 0;
@@ -414,10 +403,7 @@ class UsersController extends AppController
$this->pageTitle = _('users_edit_pagetitle').' :: '.sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME);
$this->publish('cssAdd', array('forms', 'jquery-ui/flora/flora.tabs'));
$this->publish('jsAdd', array('jquery-ui/ui.core.min', 'jquery-ui/ui.tabs.min'));
-
- $translations = $this->User->getAllTranslations($sessionuser['id']);
- $this->set('translations', $translations);
-
+
if (empty($this->data)) {
$this->publish('userAddons', $this->Addon->getAddonsByUser($sessionuser['id']));
@@ -434,14 +420,12 @@ class UsersController extends AppController
$changed['nickname'] = $this->data['User']['nickname'];
$changed['emailhidden'] = $this->data['User']['emailhidden'];
$changed['homepage'] = $this->data['User']['homepage'];
- $changed['display_collections'] = $this->data['User']['display_collections'];
- $changed['display_collections_fav'] = $this->data['User']['display_collections_fav'];
if (!empty($this->data['User']['password']) &&
!empty($this->data['User']['newpassword'])) {
// trying to change the password
- if (!$this->User->checkPassword($sessionuser, $this->data['User']['password']))
+ if ($sessionuser['password'] !== md5($this->data['User']['password']))
$this->User->invalidate('password');
if ($this->data['User']['newpassword'] != $this->data['User']['confirmpw'])
$this->User->invalidate('confirmpw');
@@ -449,7 +433,7 @@ class UsersController extends AppController
// store the new chosen pw to the "edited" array.
// If we invalidated fields up here, it's not going to be
// stored anyway.
- $changed['password'] = $this->User->createPassword($this->data['User']['newpassword']);
+ $changed['password'] = md5($this->data['User']['newpassword']);
}
// nickname has to be unique
@@ -511,11 +495,6 @@ class UsersController extends AppController
}
// if we get here, the data was saved successfully
- // save author "about me"
- list($localizedFields, $unlocalizedFields) = $this->User->splitLocalizedFields($this->data['User']);
- $this->Amo->clean($localizedFields);
- $this->User->saveTranslations($sessionuser['id'], $this->params['form']['data']['User'], $localizedFields);
-
// send out confirmation email if necessary
if ($newemail !== false) {
$this->set('newemail', $newemail);
@@ -531,7 +510,11 @@ class UsersController extends AppController
// send out the confirmation email
$this->Email->template = 'email/emailchange';
$this->Email->to = $newemail;
- $this->Email->subject = sprintf(___('user_emailchange_subject'), APP_PRETTYNAME);
+ // @partial translation fallback, 5/6/08
+ if (_('user_emailchange_subject') != 'user_emailchange_subject')
+ $this->Email->subject = sprintf(_('user_emailchange_subject'), APP_PRETTYNAME);
+ else
+ $this->Email->subject = sprintf('Please confirm your email address change at %1$s Add-ons', APP_PRETTYNAME);
$result = $this->Email->send();
}
@@ -594,7 +577,13 @@ class UsersController extends AppController
// is the token expired (48 hours max)?
if (time()-$changedata[2] > 48*60*60) {
- $this->publish('errormsg', ___('error_user_emailchange_expired'));
+ // @partial translation fallback, 5/6/08
+ if (_('error_user_emailchange_expired') != 'error_user_emailchange_expired')
+ $this->publish('errormsg', _('error_user_emailchange_expired'));
+ else
+ $this->publish('errormsg', 'The email change has expired. Please change '
+ .'your email address again in your user profile and click the link '
+ .'in the confirmation email as soon as you receive it.');
$this->render();
return;
}
@@ -687,20 +676,6 @@ class UsersController extends AppController
}
$this->publish('reviews', $reviews);
- // get user's own and favorite collections, if they allowed that
- if ($thisuser['User']['display_collections']) {
- $coll_ids = $this->Collection->getCollectionsByUser($thisuser['User']['id']);
- $coll = $this->Collection->findAll(array('Collection.id'=>$coll_ids, 'listed'=>1),
- array('name', 'description', 'uuid', 'nickname', 'application_id'), 'Translation.name');
- $this->publish('coll', $coll);
- }
- if ($thisuser['User']['display_collections_fav']) {
- $coll_ids = $this->Collection->getSubscriptionsByUser($thisuser['User']['id']);
- $coll_fav = $this->Collection->findAll(array('Collection.id'=>$coll_ids, 'listed'=>1),
- array('name', 'description', 'uuid', 'nickname', 'application_id'), 'Translation.name');
- $this->publish('coll_fav', $coll_fav);
- }
-
if (!empty($thisuser['User']['nickname']))
$name = $thisuser['User']['nickname'];
else
@@ -738,7 +713,7 @@ class UsersController extends AppController
}
// password entered correctly?
- if (!$this->User->checkPassword($deluser, $this->data['User']['password'])) {
+ if (md5($this->data['User']['password']) != $deluser['password']) {
$this->set('deleteerror', 'password');
$this->data['User']['password'] = ''; // do not post back password
return;
diff --git a/site/app/controllers/versions_controller.php b/site/app/controllers/versions_controller.php
index 9e7cbdc..ee52d96 100644
--- a/site/app/controllers/versions_controller.php
+++ b/site/app/controllers/versions_controller.php
@@ -39,30 +39,14 @@
class VersionsController extends AppController
{
var $name = 'Versions';
- var $uses = array('Addon', 'License', 'Translation', 'Version');
- var $components = array('Amo', 'Pagination');
+ var $uses = array('Translation', 'Version');
function beforeFilter() {
// Disable ACLs because this controller is entirely public.
$this->SimpleAuth->enabled = false;
$this->SimpleAcl->enabled = false;
}
-
- function license($version_id) {
- $version = $this->Version->findById($version_id);
- $addon = $this->Addon->getAddon($version['Version']['addon_id']);
- $license_text = $this->License->getText($version['Version']['license_id']);
- $this->set('version', $version);
- $this->publish('addon', $addon);
- $this->publish('license_text', $license_text);
-
- // set up view, then render
- $this->layout = 'amo2009';
- $this->pageTitle = sprintf(___('versions_license_header_source'),
- $addon['Translation']['name']['string'], $version['Version']['version'])
- .' :: '.sprintf(_('addons_home_pagetitle'), APP_PRETTYNAME);
- }
-
+
/**
* Displays a version's releasenotes in the form requested for updateInfoURLs
* See http://developer.mozilla.org/en/docs/Extension_Versioning%2C_Update_and_Compatibility
@@ -81,15 +65,15 @@ class VersionsController extends AppController
$this->Version->setLang($locale, $this);
}
}
-
+
$version = $this->Version->findById($version_id, array('Version.releasenotes'), null, -1);
-
+
$updateInfo = $version[0]['releasenotes'];
-
+
$this->publish('updateInfo', $updateInfo);
$this->render('update_info', 'ajax');
}
}
-?>
+?> \ No newline at end of file