Mozilla/mozilla/webtools/remora/app/controllers/addons_controller.php
fligtar%gmail.com b6f4031c64 Updated addon MCV
git-svn-id: svn://10.0.0.236/trunk@208694 18797224-902f-48f8-a5cc-f745e15eee43
2006-08-29 04:33:16 +00:00

390 lines
15 KiB
PHP

<?php
require_once('Archive/Zip.php');
class AddonsController extends AppController
{
var $name = 'Addons';
var $uses = array('Addon', 'Platform', 'Application', 'Appversion', 'Tag', 'User');
var $components = array('Amo', 'Rdf', 'Versioncompare');
var $helpers = array('Html', 'Javascript', 'Ajax');
var $scaffold;
/**
*
*
function index() {
$this->set('addons', $this->Amo->addonTypes);
}*/
/**
* Add new or new version of an add-on
* @param int $id
*/
function add($id = '') {
$this->layout = 'developers';
$this->set('addonTypes', $this->Amo->addonTypes);
//Determine if an adding a new addon or new version
if ($id != '' && $this->Amo->checkOwnership($id)) {
$this->Addon->id = $id;
$existing = $this->Addon->read();
$this->set('existing', $existing);
$newAddon = false;
}
else {
$newAddon = true;
}
$this->set('id', $id);
$this->set('newAddon', $newAddon);
//Step 2: Parse uploaded file and if correct, display addon-wide information form
if (isset($this->data['Addon']['add_step1'])) {
//Check for model validation first (in step 1, this is just addon type)
if (!$this->Addon->validates($this->data)) {
$this->validateErrors();
$this->set('fileError', '');
$this->render('add_step1');
die();
}
//Check for file upload errors
if ($this->data['Addon']['file']['error'] !== 0) {
$this->Addon->invalidate('file');
$fileErrors = array('1' => _('Exceeds maximum upload size'),
'2' => _('Exceeds maximum upload size'),
'3' => _('Incomplete transfer'),
'4' => _('No file uploaded')
);
$fileError = $fileErrors[$this->data['Addon']['file']['error']];
$this->set('fileError', $fileError);
$this->render('add_step1');
die();
}
$fileName = $this->data['Addon']['file']['name'];
$fileSize = round($this->data['Addon']['file']['size']/1024, 1); //in KB
$fileExtension = substr($fileName, strrpos($fileName, '.'));
$allowedExtensions = array('.xpi', '.jar', '.src');
//Check for file extenion match
if (!in_array($fileExtension, $allowedExtensions)) {
$this->Addon->invalidate('file');
$this->set('fileError', sprintf(_('Disallowed file extension (%s)'), $fileExtension));
$this->render('add_step1');
die();
}
//Move temporary file to repository
$uploadedFile = $this->data['Addon']['file']['tmp_name'];
$tempLocation = REPO_PATH.'/temp/'.$fileName;
if (move_uploaded_file($uploadedFile, $tempLocation)) {
$uploadedFile = $tempLocation;
chmod($uploadedFile, 0644);
}
else {
$this->Addon->invalidate('file');
$this->set('fileError', _('Could not move file'));
$this->render('add_step1');
die();
}
//Search plugins do not have install.rdf to parse
if ($this->Amo->addonTypes[$this->data['Addon']['addontype_id']] != 'Search Plugin') {
//Extract install.rdf from the package
$zip = new Archive_Zip($uploadedFile);
$extraction = $zip->extract(array('extract_as_string' => true, 'by_name' => array('install.rdf')));
//Make sure install.rdf is present
if ($extraction !== 0) {
$fileContents = $extraction[0]['content'];
}
else {
$this->Addon->invalidate('file');
$this->set('fileError', _('No install.rdf present'));
$this->render('add_step1');
die();
}
//Use Rdf Component to parse install.rdf
$manifestData = $this->Rdf->parseInstallManifest($fileContents);
//If the result is a string, it is an error message
if (!is_array($manifestData)) {
$this->Addon->invalidate('file');
$this->set('fileError', sprintf(_('The following error occurred while parsing install.rdf: %s'), $manifestData));
$this->render('add_step1');
die();
}
//Check if install.rdf has an updateURL
if (isset($manifestData['updateURL'])) {
$this->Addon->invalidate('file');
$this->set('fileError', _('Add-ons cannot use an external updateURL. Please remove this from install.rdf and try again.'));
$this->render('add_step1');
die();
}
//Check the GUID
if (!isset($manifestData['id']) || !preg_match('/^(\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}|[a-z0-9-\._]*\@[a-z0-9-\._]+)$/i', $manifestData['id'])) {
$this->Addon->invalidate('file');
$this->set('fileError', _('The ID of this add-on is invalid or not set.'));
$this->render('add_step1');
die();
}
//Make sure version has no spaces
if (!isset($manifestData['version']) || preg_match('/.*\s.*/', $manifestData['version'])) {
$this->Addon->invalidate('file');
$this->set('fileError', _('The version of this add-on is invalid or not set. Versions cannot contain spaces.'));
$this->render('add_step1');
die();
}
//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->findAllByGuid($manifestData['id'])) {
if ($newAddon === true) {
$newAddon = false;
$this->set('newAddon', $newAddon);
}
$existing = $existing[0];
}
else {
if ($newAddon === false) {
$newAddon = true;
$this->set('newAddon', $newAddon);
}
}
//Initialize targetApp checking
$noMozApps = true;
$versionErrors = array();
if (count($manifestData['targetApplication']) > 0) {
//Iterate through each target app and find it in the DB
foreach ($manifestData['targetApplication'] as $appKey => $appVal) {
if ($matchingApp = $this->Application->find(array('guid' => $appKey), null, null, -1)) {
$noMozApps = false;
//Check if the minVersion is valid
if (!$matchingMinVers = $this->Appversion->find(array(
'application_id' => $matchingApp['Application']['id'],
'version' => $appVal['minVersion'],
'public' => 1
), null, null, -1)) {
$versionErrors[] = sprintf(_('%s is not a valid version for %s'), $appVal['minVersion'], $matchingApp['Application']['name']);
}
//Check if the maxVersion is valid
if (!$matchingMaxVers = $this->Appversion->find(array(
'application_id' => $matchingApp['Application']['id'],
'version' => $appVal['maxVersion'],
'public' => 1
), null, null, -1)) {
$versionErrors[] = sprintf(_('%s is not a valid version for %s'), $appVal['maxVersion'], $matchingApp['Application']['name']);
}
}
}
}
//Must have at least one mozilla app
if ($noMozApps === true) {
$this->Addon->invalidate('file');
$this->set('fileError', _('You must have at least one valid Mozilla Target Application.'));
$this->render('add_step1');
die();
}
//Max/min version errors
if (count($versionErrors) > 0) {
$this->Addon->invalidate('file');
$errorStr = implode($versionErrors, '<br />');
$this->set('fileError', _('The following errors were found in install.rdf:').'<br />'.$errorStr);
$this->render('add_step1');
die();
}
}
//If it is a search plugin, read the .src file
else {
}
$info['name'] = (!empty($existing['Addon']['name'])) ? $existing['Addon']['name'] : $manifestData['name']['en-US'];
$info['description'] = (!empty($existing['Addon']['description'])) ? $existing['Addon']['description'] : $manifestData['description']['en-US'];
$info['homepage'] = (!empty($existing['Addon']['homepage'])) ? $existing['Addon']['homepage'] : $manifestData['homepageURL'];
$info['addontype_id'] = (!empty($existing['Addon']['addontype_id'])) ? $existing['Addon']['addontype_id'] : $this->data['Addon']['addontype_id'];
$info['version'] = $manifestData['version'];
$info['summary'] = $existing['Addon']['summary'];
//Get tags based on addontype
$tagsQry = $this->Tag->findAll(array('addontype_id' => $info['addontype_id']),
null, null, null, null, -1);
foreach ($tagsQry as $k => $v) {
$tags[$v['Tag']['id']] = $v['Tag']['name'];
}
if (count($existing['Tag']) > 0) {
foreach ($existing['Tag'] as $tag) {
$info['selectedTags'][$tag['id']] = $tag['name'];
}
}
else {
$info['selectedTags'] = array();
}
$this->set('tags', $tags);
$this->set('info', $info);
$this->set('fileName', $fileName);
$this->set('fileSize', $fileSize);
$this->set('manifestData', $manifestData);
$this->render('add_step2');
}
elseif (isset($this->data['Addon']['add_step2']) || isset($this->data['Addon']['add_step25'])) {
//Step 2 processing
if (isset($this->data['Addon']['add_step2'])) {
//Check for model validation first
if (!$this->Addon->validates($this->data)) {
$this->validateErrors();
$this->render('add_step2');
die();
}
//Updated Addon
if ($newAddon === false) {
//Check for identical versions
if ($this->Version->findAll()) {
$this->invalidate('general');
$this->set('generalError', sprintf(_('An identical version (%s) already exists for this add-on and platform.'), $this->data['Addon']['version']));
$this->render('add_step2');
die();
}
//Update addon
//Delete current authors
//Add new authors
//Delete old tags
//Add new tags
}
//New Addon
else {
//Check for duplicate names
if ($this->Addon->findAllByName($this->data['Addon']['name'])) {
$this->invalidate('general');
$this->set('generalError', _('The name for your add-on already exists in the database. Please make sure that: <br /><li>Your GUIDs match. The most common cause for this error is mismatched GUIDs.</li><li>You do not have a duplicate entry in the database. If you do, you should update that entry or delete it and try again.</li>'));
$this->render('add_step2');
die();
}
//Insert addon
//Add authors
//Add tags
}
if($this->data['Addon']['ShowEula'] == 1) {
$this->render('add_step25');
die();
}
//Else, continue and show step3
}
//Step 2.5 processing
if (isset($this->data['Addon']['add_step25'])) {
//Update EULA/PP
}
//Get Platforms list
$platformQry = $this->Platform->findAll();
foreach ($platformQry as $k => $v) {
$platforms[$v['Platform']['id']] = $v['Platform']['name'];
}
$this->set('platforms', $platforms);
$this->render('add_step3');
}
elseif (isset($this->data['Addon']['add_step3'])) {
//Check for model validation first
if (!$this->Version->validates($this->data)) {
$this->validateErrors();
$this->render('add_step3');
die();
}
//Construct new filename
//Move file
//Insert version
//Insert files
//Cancel any pending approvals (TODO warn earlier in process)
//Approval queue
$this->render('add_step4');
}
//Step 1: Add-on type and file upload
else {
$this->set('fileError', '');
$this->render('add_step1');
}
}
/**
* Manage an add-on
* @param int $id
*/
function manage($id) {
}
/**
* Edit add-on
* @param int $id
*
function edit($id) {
}*/
/**
* Edit a version
* @param int $id
*/
function editVersion($id) {
}
/**
* AJAX action for looking up an author by email
* @param string $email
*/
function authorLookup($email) {
if ($authors = $this->User->findAllByEmail($email)) {
$author = $authors[0]['User']['firstname'].' '.$authors[0]['User']['lastname'];
$author .= ' ['.$authors[0]['User']['email'].']';
}
else {
$author = false;
}
$this->set('author', $author);
$this->set('email', $email);
$this->render('author_lookup', 'ajax');
}
}
?>