зеркало из https://github.com/mozilla/pjs.git
- Fixed a bug where plain text is echoed in a select list
- A new version of plotkit came out, and that is integrated here - Fixed bug 354391 - Added MPL/GPL/LGPL to all files
This commit is contained in:
Родитель
f98bfadac8
Коммит
d845dbc670
|
@ -1,52 +0,0 @@
|
|||
Mozilla Firefox Uninstall Survey
|
||||
================================
|
||||
|
||||
|
||||
How To Install
|
||||
--------------
|
||||
|
||||
Assumptions:
|
||||
1) You've got a working database with the appropriate schema
|
||||
2) You've got cake setup on your server already. The code you're looking at now
|
||||
is just what is in the /app/ directory - everything else will have to be on your
|
||||
server already.
|
||||
|
||||
Steps:
|
||||
|
||||
1) Copy config/database.php.default to config/database.php and fill in your database
|
||||
values (if you're only doing production, just fill in the production area).
|
||||
|
||||
2) Edit /webroot/index.php.
|
||||
Define ROOT:
|
||||
If you're installing this in your home directory, ROOT should be:
|
||||
|
||||
DS.'home'.DS.'username'.DS.'public_html'
|
||||
|
||||
Define APP_DIR:
|
||||
ROOT is the parent directory of the app, this is the actual app.
|
||||
Continuing the example above, if people are going to go to:
|
||||
http://server.com/~username/survey/ to get to the app, APP_DIR should be:
|
||||
|
||||
survey
|
||||
|
||||
Define CAKE_CORE_INCLUDE_PATH:
|
||||
This is the path to the actual cake install on your server. For example:
|
||||
|
||||
DS.'usr'.DS.'local'.DS.'lib'.DS.'php'.DS.'cake'
|
||||
|
||||
3) Edit /webroot/.htaccess. Add a RewriteBase line below the line that says 'RewriteEngine On'.
|
||||
For our example, we would add the line:
|
||||
|
||||
RewriteBase /~username/survey
|
||||
|
||||
4) Edit /.htaccess. Add the same RewriteBase line from step 3 directly below the
|
||||
'RewriteEngine On' line.
|
||||
|
||||
5) Go to the webroot/js/ directory and run the following two commands:
|
||||
ln -s plotkit-0.8/PlotKit/ plotkit
|
||||
ln -s MochiKit-1.3.1/lib/MochiKit/ mochikit
|
||||
|
||||
|
||||
|
||||
|
||||
Questions? Email clouserw@mozilla.com
|
|
@ -1,76 +0,0 @@
|
|||
;<?php die() ?>
|
||||
; SVN FILE: $Id: acl.ini.php,v 1.1 2006-05-24 19:14:24 uid815 Exp $
|
||||
;/**
|
||||
; * Short description for file.
|
||||
; *
|
||||
; *
|
||||
; * PHP versions 4 and 5
|
||||
; *
|
||||
; * CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
; * Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
; * 1785 E. Sahara Avenue, Suite 490-204
|
||||
; * Las Vegas, Nevada 89104
|
||||
; *
|
||||
; * Licensed under The MIT License
|
||||
; * Redistributions of files must retain the above copyright notice.
|
||||
; *
|
||||
; * @filesource
|
||||
; * @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
; * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
; * @package cake
|
||||
; * @subpackage cake.app.config
|
||||
; * @since CakePHP v 0.10.0.1076
|
||||
; * @version $Revision: 1.1 $
|
||||
; * @modifiedby $LastChangedBy: phpnut $
|
||||
; * @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
; * @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
; */
|
||||
|
||||
; acl.ini.php - Cake ACL Configuration
|
||||
; ---------------------------------------------------------------------
|
||||
; Use this file to specify user permissions.
|
||||
; aco = access control object (something in your application)
|
||||
; aro = access request object (something requesting access)
|
||||
;
|
||||
; User records are added as follows:
|
||||
;
|
||||
; [uid]
|
||||
; groups = group1, group2, group3
|
||||
; allow = aco1, aco2, aco3
|
||||
; deny = aco4, aco5, aco6
|
||||
;
|
||||
; Group records are added in a similar manner:
|
||||
;
|
||||
; [gid]
|
||||
; allow = aco1, aco2, aco3
|
||||
; deny = aco4, aco5, aco6
|
||||
;
|
||||
; The allow, deny, and groups sections are all optional.
|
||||
; NOTE: groups names *cannot* ever be the same as usernames!
|
||||
;
|
||||
; ACL permissions are checked in the following order:
|
||||
; 1. Check for user denies (and DENY if specified)
|
||||
; 2. Check for user allows (and ALLOW if specified)
|
||||
; 3. Gather user's groups
|
||||
; 4. Check group denies (and DENY if specified)
|
||||
; 5. Check group allows (and ALLOW if specified)
|
||||
; 6. If no aro, aco, or group information is found, DENY
|
||||
;
|
||||
; ---------------------------------------------------------------------
|
||||
|
||||
;-------------------------------------
|
||||
;Users
|
||||
;-------------------------------------
|
||||
|
||||
[username-goes-here]
|
||||
groups = group1, group2
|
||||
deny = aco1, aco2
|
||||
allow = aco3, aco4
|
||||
|
||||
;-------------------------------------
|
||||
;Groups
|
||||
;-------------------------------------
|
||||
|
||||
[groupname-goes-here]
|
||||
deny = aco5, aco6
|
||||
allow = aco7, aco8
|
|
@ -1,11 +0,0 @@
|
|||
-- @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
-- @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
-- @since CakePHP v 0.10.8.1997
|
||||
-- @version $Revision: 1.1 $
|
||||
|
||||
CREATE TABLE cake_sessions (
|
||||
id varchar(255) NOT NULL default '',
|
||||
data text,
|
||||
expires int(11) default NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
|
@ -1,7 +0,0 @@
|
|||
<?php
|
||||
class ApplicationsController extends AppController {
|
||||
|
||||
var $name = 'Applications';
|
||||
|
||||
}
|
||||
?>
|
|
@ -1,7 +0,0 @@
|
|||
<?php
|
||||
class ChoicesController extends AppController {
|
||||
|
||||
var $name = 'Choices';
|
||||
|
||||
}
|
||||
?>
|
|
@ -1,6 +0,0 @@
|
|||
<?php
|
||||
class CollectionsController extends AppController {
|
||||
|
||||
var $name = 'Collections';
|
||||
}
|
||||
?>
|
|
@ -1,241 +0,0 @@
|
|||
<?php
|
||||
|
||||
/* Include the CSV library. It would be nice to make this OO sometime */
|
||||
vendor('csv/csv');
|
||||
|
||||
class ResultsController extends AppController {
|
||||
|
||||
var $name = 'Results';
|
||||
|
||||
/**
|
||||
* Model's this controller uses
|
||||
* @var array
|
||||
*/
|
||||
var $uses = array('Application','Collection','Choice','Result');
|
||||
|
||||
/**
|
||||
* Cake Helpers
|
||||
* @var array
|
||||
*/
|
||||
var $helpers = array('Html', 'Javascript', 'Export', 'Pagination','Time','Breadcrumb');
|
||||
|
||||
/**
|
||||
* Pagination helper variable array
|
||||
* @access public
|
||||
* @var array
|
||||
*/
|
||||
var $pagination_parameters = array();
|
||||
|
||||
/**
|
||||
* Will hold a sanitize object
|
||||
* @var object
|
||||
*/
|
||||
var $Sanitize;
|
||||
|
||||
/**
|
||||
* Constructor - sets up the sanitizer and the pagination
|
||||
*/
|
||||
function ResultsController()
|
||||
{
|
||||
parent::AppController();
|
||||
|
||||
$this->Sanitize = new Sanitize();
|
||||
|
||||
// Pagination Stuff
|
||||
$this->pagination_parameters['show'] = empty($_GET['show'])? '10' : $this->Sanitize->paranoid($_GET['show']);
|
||||
$this->pagination_parameters['sortBy'] = empty($_GET['sort'])? 'created' : $this->Sanitize->paranoid($_GET['sort']);
|
||||
$this->pagination_parameters['direction'] = empty($_GET['direction'])? 'desc': $this->Sanitize->paranoid($_GET['direction']);
|
||||
$this->pagination_parameters['page'] = empty($_GET['page'])? '1': $this->Sanitize->paranoid($_GET['page']);
|
||||
$this->pagination_parameters['order'] = $this->modelClass.'.'.$this->pagination_parameters['sortBy'].' '.strtoupper($this->pagination_parameters['direction']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new result. This also means we're going to be adding to several other
|
||||
* tables (for the many to many relationships). First we'll show a form, then if
|
||||
* there is a $_POST, we'll process.
|
||||
*/
|
||||
function add()
|
||||
{
|
||||
// If these are set in $_POST, we'll use that for the query. If this is set
|
||||
// in $_GET, then use that. If neither are set, make it blank, and we'll
|
||||
// fail later on
|
||||
$_input_name = $this->Sanitize->Sql(isset($this->data['application'][0]) ? $this->data['application'][0] : (isset($this->params['url']['application']) ? $this->params['url']['application'] : ''));
|
||||
$_input_ua = $this->Sanitize->Sql(isset($this->data['ua'][0]) ? $this->data['ua'][0] : (isset($this->params['url']['ua']) ? $this->params['url']['ua'] : ''));
|
||||
|
||||
// The ua comes over $_GET in the form:
|
||||
// x.x.x.x (aa-bb)
|
||||
// Where x is the versions and a and b are locale information. We're not
|
||||
// interested in the locale information,
|
||||
|
||||
$_conditions = "name LIKE '{$_input_name}' AND version LIKE '{$_input_ua}'";
|
||||
$_application = $this->Application->findAll($_conditions);
|
||||
|
||||
if (empty($_application)) {
|
||||
// The application they entered in the URL is not in the db. We'll have
|
||||
// to put it in the db, but we don't want it to show up (in case they
|
||||
// just typed something in manually) so we'll flag it as not visible.
|
||||
$app = new Application();
|
||||
$app->set('name', $_input_name);
|
||||
$app->set('version', $_input_ua);
|
||||
$app->set('visible', 0);
|
||||
$app->save();
|
||||
|
||||
$app_id = $app->getLastInsertID();
|
||||
|
||||
// The database will handle any combination of questions
|
||||
// (issues/intentions) and applications+versions. However, since we're
|
||||
// adding stuff in that comes in over the URL, we kinda have to guess at
|
||||
// what questions should be associated. So, I'm running a stristr() on
|
||||
// the $_GET values to get a general set of questions to associate, and
|
||||
// then manually adding those values to the table.
|
||||
if (stristr($this->params['url']['application'], 'Firefox') !== false) {
|
||||
// Intention Id's
|
||||
$this->Application->query("INSERT INTO applications_collections VALUES ({$app_id}, ".DEFAULT_FIREFOX_INTENTION_SET_ID.")");
|
||||
|
||||
// Issue Id's
|
||||
$this->Application->query("INSERT INTO applications_collections VALUES ({$app_id}, ".DEFAULT_FIREFOX_ISSUE_SET_ID.")");
|
||||
|
||||
} elseif (stristr($this->params['url']['application'], 'Thunderbird') !== false) {
|
||||
|
||||
// Intention Id's
|
||||
$this->Application->query("INSERT INTO applications_collections VALUES ({$app_id}, ".DEFAULT_THUNDERBIRD_INTENTION_SET_ID.")");
|
||||
|
||||
// Issue Id's
|
||||
$this->Application->query("INSERT INTO applications_collections VALUES ({$app_id}, ".DEFAULT_THUNDERBIRD_ISSUE_SET_ID.")");
|
||||
|
||||
} else {
|
||||
// Whatever they entered doesn't have firefox or thunderbird in it.
|
||||
// All they're going to see is a comment box on the other end.
|
||||
}
|
||||
|
||||
|
||||
// We could just get the last inserted id, but we need all the info
|
||||
// below. Also, cake caches the query, and won't return
|
||||
// anything if we don't alter it (add 1=1 to the end), since we already
|
||||
// did the same query earlier
|
||||
$_conditions = "name LIKE '{$_input_name}' AND version LIKE '{$_input_ua}' AND 1=1";
|
||||
$_application = $this->Application->findAll($_conditions);
|
||||
}
|
||||
// Pull the information for our radio buttons (only the
|
||||
// questions for their applications will be shown)
|
||||
$this->set('intentions', $this->Application->getIntentions($this->Sanitize->sql($_application[0]['Application']['id'])));
|
||||
|
||||
// Checkboxes
|
||||
$this->set('issues', $this->Application->getIssues($this->Sanitize->sql($_application[0]['Application']['id'])));
|
||||
|
||||
// We'll need the url parameters to put in hidden fields
|
||||
$this->set('url_params', $this->Sanitize->html($this->params['url']));
|
||||
|
||||
// If there is no $_POST, show the form, otherwise, process the data and
|
||||
// forward the user on.
|
||||
if (empty($this->params['data'])) {
|
||||
$this->render();
|
||||
} else {
|
||||
// Add the application id from the last cake query
|
||||
$this->params['data'] = $this->params['data'] + $_application[0];
|
||||
if ($this->Result->save($this->params['data'])) {
|
||||
// Redirect
|
||||
$this->flash('Thank you.', '/results');
|
||||
exit;
|
||||
} else {
|
||||
// Saving failed. This probably means a required field wasn't set.
|
||||
// Should we tell them it failed, or just redirect? Hmm...
|
||||
$this->flash('Thank you.', '/results');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Front page will show the graph
|
||||
*/
|
||||
function index()
|
||||
{
|
||||
// Products dropdown
|
||||
$this->set('products', $this->Application->findAll('visible=1', null, 'Application.name ASC,Application.version DESC'));
|
||||
|
||||
// Fill in all the data passed in $_GET
|
||||
$this->set('url_params',$this->decodeAndSanitize($this->params['url']));
|
||||
|
||||
// Give us some breadcrumbs
|
||||
$this->set('breadcrumbs', array('Home' => 'http://mozilla.org', 'Uninstall Survey Results' => ''));
|
||||
|
||||
// We'll need to include the graphing libraries
|
||||
$this->set('include_graph_libraries', true);
|
||||
|
||||
// Fill in our question sets
|
||||
$this->set('collections',$this->Application->getCollectionsFromUrl($this->params['url'],'issue'));
|
||||
|
||||
// Core data to show on page
|
||||
$this->set('descriptionAndTotalsData',$this->Result->getDescriptionAndTotalsData($this->params['url']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a table of user comments
|
||||
*/
|
||||
function comments()
|
||||
{
|
||||
// Products dropdown
|
||||
$this->set('products', $this->Application->findAll('visible=1', null, 'Application.name ASC,Application.version DESC'));
|
||||
|
||||
// Fill in all the data passed in $_GET
|
||||
$this->set('url_params',$this->decodeAndSanitize($this->params['url']));
|
||||
|
||||
// Give us some breadcrumbs
|
||||
$this->set('breadcrumbs', array('Home' => 'http://mozilla.org', 'Uninstall Survey Results' => 'results/', 'Comments' => ''));
|
||||
|
||||
// Fill in our question sets
|
||||
$this->set('collections',$this->Application->getCollectionsFromUrl($this->params['url'],'issue'));
|
||||
|
||||
// Core data to show on page
|
||||
$this->set('commentsData',$this->Result->getComments($this->params['url'], $this->pagination_parameters));
|
||||
|
||||
// Pagination settings
|
||||
$paging['count'] = $this->Result->getCommentCount();
|
||||
$paging['style'] = 'html';
|
||||
$paging['link'] = "/results/comments/?collection=".urlencode($this->params['url']['collection'])."&product=".urlencode($this->params['url']['product'])."&start_date=".urlencode($this->params['url']['start_date'])."&end_date=".urlencode($this->params['url']['end_date'])."&show={$this->pagination_parameters['show']}&sort={$this->pagination_parameters['sortBy']}&direction={$this->pagination_parameters['direction']}&page=";
|
||||
$paging['page'] = $this->pagination_parameters['page'];
|
||||
$paging['limit'] = $this->pagination_parameters['show'];
|
||||
$paging['show'] = array('10','25','50');
|
||||
|
||||
// No point in showing them an error if they click on "show 50" but they are
|
||||
// already on the last page.
|
||||
if ($paging['count'] < ($this->pagination_parameters['page'] * ($this->pagination_parameters['show']/2))) {
|
||||
$this->pagination_parameters['page'] = $paging['page'] = 1;
|
||||
}
|
||||
|
||||
// Set pagination array
|
||||
$this->set('paging',$paging);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a csv
|
||||
*/
|
||||
function csv()
|
||||
{
|
||||
// Get rid of the header/footer/etc.
|
||||
$this->layout = null;
|
||||
|
||||
// Auto generated .csv's are turned off since they were taking too much
|
||||
// cpu/ram. If you turn them back on, be sure to check the code - there was
|
||||
// a substantial database change between the time they were disabled and now.
|
||||
return false;
|
||||
|
||||
$csv = new csv();
|
||||
|
||||
$csv->loadDataFromArray($this->Result->getCsvExportData($this->params['url'], false));
|
||||
|
||||
// Our CSV library sends headers and everything. Keep the view empty!
|
||||
$csv->sendCSV();
|
||||
|
||||
// I'm not exiting here in case someone is going to use post callback stuff.
|
||||
// In development, that means extra lines get added to our CSVs, but in
|
||||
// production it should be clean.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
?>
|
|
@ -1,4 +1,41 @@
|
|||
<?php
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is survey.mozilla.com site.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Wil Clouser <clouserw@mozilla.com> (Original Author)
|
||||
*
|
||||
* 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
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
uses('Sanitize');
|
||||
class Application extends AppModel {
|
||||
var $name = 'Application';
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
class Choice extends AppModel {
|
||||
var $name = 'Choice';
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
'Result' => array('className' => 'Result', 'uniq' => true ),
|
||||
'Collection' => array('className' => 'Collection', 'uniq' => true )
|
||||
);
|
||||
}
|
||||
?>
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
class Collection extends AppModel {
|
||||
var $name = 'Collection';
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
'Application' => array( 'className' => 'Application',
|
||||
'joinTable' => 'applications_collections',
|
||||
'foreignKey' => 'collection_id',
|
||||
'associationForeignKey' => 'application_id'
|
||||
),
|
||||
'Choice' => array('className' => 'Choice')
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
|
@ -1,4 +1,41 @@
|
|||
<?php
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is survey.mozilla.com site.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Wil Clouser <clouserw@mozilla.com> (Original Author)
|
||||
*
|
||||
* 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
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Result extends AppModel {
|
||||
var $name = 'Result';
|
||||
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* A simple class to print a csv from a 2 dimensional array.
|
||||
*
|
||||
*/
|
||||
class csv
|
||||
{
|
||||
var $filename = '';
|
||||
|
||||
var $data = array();
|
||||
|
||||
/**
|
||||
* @param string name of the file to send
|
||||
*/
|
||||
function csv($name=null)
|
||||
{
|
||||
$this->filename = $name;
|
||||
|
||||
if (empty($this->filename)) {
|
||||
$this->filename = 'export-'.date('Y-m-d').'.csv';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function to load data from an array into the object
|
||||
* @param array a 2 dimensional array
|
||||
*/
|
||||
function loadDataFromArray(&$array)
|
||||
{
|
||||
$this->data = $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will send the CSV to the browser (including headers)
|
||||
*/
|
||||
function sendCSV()
|
||||
{
|
||||
$this->_sendHeaders();
|
||||
|
||||
$this->_cleanData();
|
||||
|
||||
foreach ($this->data as $var => $val) {
|
||||
// We put quotes around each value here
|
||||
$line = implode('","',$val);
|
||||
echo "\"{$line}\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans data for export into a csv (quotes and newlines)
|
||||
* @access private
|
||||
*/
|
||||
function _cleanData()
|
||||
{
|
||||
foreach ($this->data as $var => $val) {
|
||||
// escape the quotes by doubling them
|
||||
$val = str_replace('"','""',$val);
|
||||
|
||||
// fix newlines
|
||||
$val = str_replace("\n\r", "\n", str_replace("\r", "\n", $val));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends headers for a .csv
|
||||
* @access private
|
||||
*/
|
||||
function _sendHeaders()
|
||||
{
|
||||
header("Content-type: application/x-csv");
|
||||
header('Content-disposition: inline; filename="'.$this->filename.'"');
|
||||
header('Cache-Control: private');
|
||||
header('Pragma: public');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
|
||||
<!-- content -->
|
||||
</div>
|
||||
|
||||
<div id="footer">
|
||||
<div id="footer-contents">
|
||||
<ul id="footer-menu">
|
||||
<li><a href="http://www.mozilla.com/about/">About Us</a></li>
|
||||
<li><a href="http://www.mozilla.com/privacy-policy.html">Privacy Policy</a></li>
|
||||
<li><a href="http://www.mozilla.com/about/legal.html">Legal Notices</a></li>
|
||||
|
||||
</ul>
|
||||
<p class="small-print">International Affiliates:
|
||||
<a href="http://www.mozilla-europe.org/">Mozilla Europe</a>
|
||||
<a href="http://www.mozilla-japan.org/">Mozilla Japan</a>
|
||||
<a href="http://www.mozilla.org.cn/">Mozilla China</a>
|
||||
</p>
|
||||
<p class="small-print">Mozilla Corporation is a wholly-owned subsidiary of the <a href="http://www.mozillafoundation.org">Mozilla Foundation</a>.</p>
|
||||
|
||||
<p class="small-print">Copyright © 2005–2006 Mozilla Corporation. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,3 +1,41 @@
|
|||
<?php
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is survey.mozilla.com site.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Wil Clouser <clouserw@mozilla.com> (Original Author)
|
||||
*
|
||||
* 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
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* The new layout uses breadcrumbs, so this is a helper to make using them easier.
|
||||
*/
|
||||
class BreadcrumbHelper
|
||||
{
|
||||
|
||||
/**
|
||||
* Will store all the links in an associative array
|
||||
*/
|
||||
var $links = array();
|
||||
|
||||
/**
|
||||
* Add a single link to the array
|
||||
* @param array in the form 'name' => 'url'
|
||||
*/
|
||||
function addlink($newlink)
|
||||
{
|
||||
array_push($this->links,$newlink);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk add some links to the array
|
||||
* @param array in the form 'name' => 'url', ... , 'name' => 'url'
|
||||
*/
|
||||
function addlinks($newlinks)
|
||||
{
|
||||
$this->links = $this->links + $newlinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk through the links and build an html string to echo. Note: this doesn't
|
||||
* actually echo the string, despite being a show* function. I did this to be
|
||||
* inline with the rest of cake.
|
||||
*
|
||||
* @return string html to echo
|
||||
*/
|
||||
function showLinks()
|
||||
{
|
||||
$_ret = '';
|
||||
|
||||
foreach ($this->links as $name => $link) {
|
||||
$name = htmlspecialchars($name);
|
||||
$link = htmlspecialchars($link);
|
||||
|
||||
if (empty($link)) {
|
||||
$_ret .= (empty($_ret)) ? "<span>{$name}</span>\n" : "» <span>{$name}</span>\n";
|
||||
} else {
|
||||
/* This should really check for any protocol */
|
||||
if (strpos($link,'http') === 0) {
|
||||
$href = $link;
|
||||
} else {
|
||||
$href = $this->webroot.$link;
|
||||
}
|
||||
$_ret .= (empty($_ret)) ? '<span><a href="'.$href.'">'.$name.'</a></span>'."\n" : '» <span><a href="'.$href.'">'.$name.'</a></span>'."\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $_ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,56 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* When we're exporting data, we end up having to pass all the parameters
|
||||
* via $_GET. Since we're doing this a few times per page (each graph, and the
|
||||
* export hrefs) this helper should make that easier.
|
||||
*/
|
||||
class ExportHelper
|
||||
{
|
||||
/**
|
||||
* Method to collect the current $_GET parameters and build another string from
|
||||
* them.
|
||||
*
|
||||
* @param string cake URL that you want prepended to the result. eg: reports/graph/
|
||||
* @param array the array of GET variables to add. These need to be
|
||||
* pre-sanitized to print in html! This is designed to
|
||||
* be used from the calling controller like:
|
||||
* $params = $this->sanitize->html($url_parameters);
|
||||
* @param string string to put between url and arguments (probably either '?' or
|
||||
* '&')
|
||||
* @param array array of strings which will be ignored
|
||||
* @return string string with the url variables appeneded to it
|
||||
*/
|
||||
function buildUrlString($url, $params, $seperator='?', $ignore=array('url'))
|
||||
{
|
||||
$arguments = '';
|
||||
|
||||
foreach ($params as $var => $val) {
|
||||
if (!in_array($var, $ignore)) {
|
||||
$arguments .= empty($arguments) ? "{$var}={$val}" : "&{$var}={$val}";
|
||||
}
|
||||
}
|
||||
|
||||
return "{$this->webroot}{$url}{$seperator}{$arguments}";
|
||||
}
|
||||
|
||||
function buildCsvExportString($params)
|
||||
{
|
||||
if (array_key_exists('product', $params)) {
|
||||
$filename = $params['product'];
|
||||
} else {
|
||||
$filename = DEFAULT_APP_NAME.' '.DEFAULT_APP_VERSION;
|
||||
}
|
||||
|
||||
// Our filenames have underscores
|
||||
$filename = str_replace(' ','_',$filename);
|
||||
|
||||
$filename = "export-{$filename}.csv";
|
||||
|
||||
if (is_readable(ROOT.DS.APP_DIR.DS.WEBROOT_DIR.DS.'export'.DS.$filename)) {
|
||||
return "{$this->webroot}export/{$filename}";
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -1,211 +0,0 @@
|
|||
<?php
|
||||
class PaginationHelper {
|
||||
|
||||
var $helpers = array('Html','Ajax');
|
||||
var $_pageDetails = array();
|
||||
var $link = '';
|
||||
var $show = array();
|
||||
var $page;
|
||||
var $style;
|
||||
|
||||
/**
|
||||
* Sets the default pagination options.
|
||||
*
|
||||
* @param array $paging an array detailing the page options
|
||||
*/
|
||||
function setPaging($paging)
|
||||
{
|
||||
if(!empty($paging))
|
||||
{
|
||||
|
||||
$this->link = $paging['link'];
|
||||
$this->show = $paging['show'];
|
||||
$this->page = $paging['page'];
|
||||
$this->style = $paging['style'];
|
||||
|
||||
$pageCount = ceil($paging['count'] / $paging['limit'] );
|
||||
|
||||
$this->_pageDetails = array(
|
||||
'page'=>$paging['page'],
|
||||
'recordCount'=>$paging['count'],
|
||||
'pageCount' =>$pageCount,
|
||||
'nextPage'=> ($paging['page'] < $pageCount) ? $paging['page']+1 : '',
|
||||
'previousPage'=> ($paging['page']>1) ? $paging['page']-1 : '',
|
||||
'limit'=>$paging['limit']
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Displays limits for the query
|
||||
*
|
||||
* @param string $text - text to display before limits
|
||||
* @param string $separator - display a separate between limits
|
||||
*
|
||||
**/
|
||||
function show($text=null, $separator=null)
|
||||
{
|
||||
if (empty($this->_pageDetails)) { return false; }
|
||||
if ( !empty($this->_pageDetails['recordCount']) )
|
||||
{
|
||||
$t = '';
|
||||
if(is_array($this->show))
|
||||
{
|
||||
$t = $text.$separator;
|
||||
foreach($this->show as $value)
|
||||
{
|
||||
$link = preg_replace('/show=(.*?)&/','show='.$value.'&',$this->link);
|
||||
if($this->_pageDetails['limit'] == $value)
|
||||
{
|
||||
$t .= '<em>'.$value.'</em>'.$separator;
|
||||
}
|
||||
else
|
||||
{
|
||||
if($this->style == 'ajax')
|
||||
{
|
||||
$t .= $this->Ajax->linkToRemote($value, array("fallback"=>$this->action."#","url" => $link.$this->_pageDetails['page'],"update" => "ajax_update","method"=>"get")).$separator;
|
||||
}
|
||||
else
|
||||
{
|
||||
$t .= $this->Html->link($value,$link.$this->_pageDetails['page']).$separator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
/**
|
||||
* Displays current result information
|
||||
*
|
||||
* @param string $text - text to preceeding the number of results
|
||||
*
|
||||
**/
|
||||
function result($text)
|
||||
{
|
||||
if (empty($this->_pageDetails)) { return false; }
|
||||
if ( !empty($this->_pageDetails['recordCount']) )
|
||||
{
|
||||
if($this->_pageDetails['recordCount'] > $this->_pageDetails['limit'])
|
||||
{
|
||||
$start_row = $this->_pageDetails['page'] > 1 ? (($this->_pageDetails['page']-1)*$this->_pageDetails['limit'])+1:'1';
|
||||
$end_row = ($this->_pageDetails['recordCount'] < ($start_row + $this->_pageDetails['limit']-1)) ? $this->_pageDetails['recordCount'] : ($start_row + $this->_pageDetails['limit']-1);
|
||||
$t = $text.$start_row.'-'.$end_row.' of '.$this->_pageDetails['recordCount'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$t = $text.$this->_pageDetails['recordCount'];
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns a "Google style" list of page numbers
|
||||
*
|
||||
* @param string $separator - defaults to null
|
||||
* @param string $prefix - defaults to null. If set, displays prefix before page links.
|
||||
* @param int $pageSetLength - defaults to 10. Maximum number of pages to show.
|
||||
* @param string $prevLabel - defaults to null. If set, displays previous link.
|
||||
* @param string $nextLabel - defaults to null. If set, displays next link.
|
||||
*
|
||||
**/
|
||||
function pageNumbers($separator=null, $prefix=null, $pageSetLength=10, $prevLabel=null, $nextLabel=null)
|
||||
{
|
||||
|
||||
if (empty($this->_pageDetails) || $this->_pageDetails['pageCount'] == 1) { return false; }
|
||||
|
||||
$t = array();
|
||||
|
||||
$modulo = $this->_pageDetails['page'] % $pageSetLength;
|
||||
if ($modulo)
|
||||
{ // any number > 0
|
||||
$prevSetLastPage = $this->_pageDetails['page'] - $modulo;
|
||||
} else { // 0, last page of set
|
||||
$prevSetLastPage = $this->_pageDetails['page'] - $pageSetLength;
|
||||
}
|
||||
//$nextSetFirstPage = $prevSetLastPage + $pageSetLength + 1;
|
||||
|
||||
if ($prevLabel) $t[] = $this->prevPage($prevLabel);
|
||||
|
||||
// loops through each page number
|
||||
$pageSet = $prevSetLastPage + $pageSetLength;
|
||||
if ($pageSet > $this->_pageDetails['pageCount']) $pageSet = $this->_pageDetails['pageCount'];
|
||||
for ($pageIndex = $prevSetLastPage+1; $pageIndex <= $pageSet; $pageIndex++)
|
||||
{
|
||||
if ($pageIndex == $this->_pageDetails['page'])
|
||||
{
|
||||
$t[] = '<em>'.$pageIndex.'</em>';
|
||||
}
|
||||
else
|
||||
{
|
||||
if($this->style == 'ajax')
|
||||
{
|
||||
$t[] = $this->Ajax->linkToRemote($pageIndex, array("fallback"=>$this->action."#","url" =>$this->link.$pageIndex,"update" => "ajax_update","method"=>"get"));
|
||||
} else {
|
||||
$t[] = $this->Html->link($pageIndex,$this->link.$pageIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($nextLabel) $t[] = $this->nextPage($nextLabel);
|
||||
|
||||
$t = implode($separator, $t);
|
||||
|
||||
return $prefix.$t;
|
||||
}
|
||||
/**
|
||||
* Displays a link to the previous page, where the page doesn't exist then
|
||||
* display the $text
|
||||
*
|
||||
* @param string $text - text display: defaults to next
|
||||
*
|
||||
**/
|
||||
function prevPage($text='prev')
|
||||
{
|
||||
if (empty($this->_pageDetails)) { return false; }
|
||||
if ( !empty($this->_pageDetails['previousPage']) )
|
||||
{
|
||||
if($this->style == 'ajax')
|
||||
{
|
||||
$t = $this->Ajax->linkToRemote($text, array("fallback"=>$this->action."#","url" => $this->link.$this->_pageDetails['previousPage'],"update" => "ajax_update","method"=>"get"));
|
||||
}
|
||||
else
|
||||
{
|
||||
$t = $this->Html->link($text,$this->link.$this->_pageDetails['previousPage']);
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Displays a link to the next page, where the page doesn't exist then
|
||||
* display the $text
|
||||
*
|
||||
* @param string $text - text to display: defaults to next
|
||||
*
|
||||
**/
|
||||
function nextPage($text='next')
|
||||
{
|
||||
if (empty($this->_pageDetails)) { return false; }
|
||||
if (!empty($this->_pageDetails['nextPage']))
|
||||
{
|
||||
if($this->style == 'ajax')
|
||||
{
|
||||
$t = $this->Ajax->linkToRemote($text, array("fallback"=>$this->action."#","url" => $this->link.$this->_pageDetails['nextPage'],"update" => "ajax_update","method"=>"get"));
|
||||
}
|
||||
else
|
||||
{
|
||||
$t = $this->Html->link($text,$this->link.$this->_pageDetails['nextPage']);
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -1,3 +0,0 @@
|
|||
<?php echo $this->renderElement( 'header' ); ?>
|
||||
<?php echo $content_for_layout;?>
|
||||
<?php echo $this->renderElement( 'footer'); ?>
|
|
@ -1,44 +0,0 @@
|
|||
<?php echo $html->formTag('/results/add'); ?>
|
||||
|
||||
<div class="special_note">
|
||||
Please note that all data entered on this page may be viewable by the public.
|
||||
</div>
|
||||
|
||||
<?php if(!empty($intentions)): ?>
|
||||
<h2>How did you intend to use <?php echo $intentions[0]['applications']['name']; ?> when you installed it?</h2>
|
||||
<?php foreach ($intentions as $var => $val) : ?>
|
||||
<input type="radio" name="data[Intention][id]" id="radio<?php echo $val['choices']['id']; ?>" value="<?php echo $val['choices']['id']; ?>"><label for="radio<?php echo $val['choices']['id']; ?>"><?php echo $val['choices']['description']; ?></label>
|
||||
<?php
|
||||
if ($val['choices']['description'] == 'Other') {
|
||||
echo $html->input('Intention/text');
|
||||
}
|
||||
|
||||
?>
|
||||
<br />
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if(!empty($issues)): ?>
|
||||
<h2>Why did you uninstall <?php echo $issues[0]['applications']['name']; ?>? (select all that apply)</h2>
|
||||
<?php foreach ($issues as $var => $val) : ?>
|
||||
<input type="checkbox" name="data[Issue][id][]" id="checkbox<?php echo $val['choices']['id']; ?>" value="<?php echo $val['choices']['id']; ?>"><label for="checkbox<?php echo $val['choices']['id']; ?>"><?php echo $val['choices']['description']; ?></label>
|
||||
<?php
|
||||
if ($val['choices']['description'] == 'Other') {
|
||||
echo $html->input('Issue/text');
|
||||
}
|
||||
?>
|
||||
<br />
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<h2>How can we improve <?php echo $intentions[0]['applications']['name']; ?>?</h2>
|
||||
<p>Please share your ideas, suggestions or details about any issues below.</p>
|
||||
<p><?php echo $html->textarea('Result/comments',array('id'=>'comments'));?></p>
|
||||
|
||||
<?php echo $html->hidden('version', 'value="'.$url_params['version'].'"') ?>
|
||||
<?php echo $html->hidden('application', 'value="'.$url_params['application'].'"') ?>
|
||||
<?php echo $html->hidden('ua', 'value="'.$url_params['ua'].'"') ?>
|
||||
<?php echo $html->hidden('lang', 'value="'.$url_params['lang'].'"') ?>
|
||||
|
||||
<p><?php echo $html->submit('Save') ?></p>
|
||||
</form>
|
|
@ -1,72 +0,0 @@
|
|||
<h1><?php echo Inflector::humanize($this->name); ?></h1>
|
||||
|
||||
<div id="queryform">
|
||||
<?php echo $html->formTag('/results/comments/','get'); ?>
|
||||
<span>
|
||||
<label for="start_date">Start Date:</label>
|
||||
<input type="text" name="start_date" id="start_date" value="<? echo isset($url_params['start_date']) ? $url_params['start_date'] : ''; ?>" />
|
||||
<label for="end_date">End Date:</label>
|
||||
<input type="text" name="end_date" id="end_date" value="<? echo isset($url_params['end_date']) ? $url_params['end_date'] : ''; ?>" />
|
||||
</span>
|
||||
|
||||
<label for="product">Product:</label>
|
||||
<select name="product" id="product">
|
||||
<?php
|
||||
foreach ($products as $select) :
|
||||
$product = $select['Application']['name'].' '.$select['Application']['version'];
|
||||
$selected = ($product == trim($url_params['product'])) ? ' selected="selected" ' : '';
|
||||
?>
|
||||
<option<?=$selected?>><?=$product?></option>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
||||
<?php if (!empty($collections)) : ?>
|
||||
<label for="collection">Questions:</label>
|
||||
<select name="collection" id="collection">
|
||||
<?php
|
||||
foreach ($collections as $select) :
|
||||
$collection = $select['collections']['description'];
|
||||
// php's built in functions won't decode UTF-8 or numeric
|
||||
// entities. Since we've only got 1, I'm putting in this to
|
||||
// get this done quickly. :(
|
||||
$url_params['collection'] = str_replace('-','-',urldecode($url_params['collection']));
|
||||
echo "{$url_params['collection']}<br />";
|
||||
$selected = ($collection == trim($url_params['collection'])) ? ' selected="selected" ' : '';
|
||||
?>
|
||||
<option<?=$selected?>><?=$collection?></option>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
|
||||
<input type="submit" name="submit" id="submit" value="Go" />
|
||||
</form>
|
||||
<br />
|
||||
<span><small>Date format is yyyy-mm-dd. A blank date will use the largest possible range.</small></span>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($commentsData)) : ?>
|
||||
|
||||
<table class="comments" summary="User submitted comments.">
|
||||
<tr><th>Date Recorded</th><th>Comment</th></tr>
|
||||
<?php foreach ($commentsData as $var => $val) : ?>
|
||||
<tr><td><?php echo $time->niceShort($val['Result']['created']); ?></td><td><?php echo nl2br(htmlspecialchars($val['Result']['comments'])); ?></td></tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
|
||||
<?php if($pagination->setPaging($paging)):?>
|
||||
<ul id="page-numbers">
|
||||
<li><?php echo $pagination->show('Show ', ' '); ?></li>
|
||||
<li><?php echo $pagination->result('Results: '); ?></li>
|
||||
<li><?php echo $pagination->pageNumbers(' ',null,10,'Prev','Next'); ?></li>
|
||||
</ul>
|
||||
<?php endif;?>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<div id="notice">There is no data available for your parameters. Please review your search criteria.</div>
|
||||
|
||||
<?php endif; ?>
|
|
@ -1,116 +0,0 @@
|
|||
<h1><?php echo Inflector::humanize($this->name); ?></h1>
|
||||
|
||||
<div id="queryform">
|
||||
<?php echo $html->formTag('/results/','get');?>
|
||||
<span>
|
||||
<label for="start_date">Start:</label>
|
||||
<input type="text" name="start_date" id="start_date" value="<? echo isset($url_params['start_date']) ? $url_params['start_date'] : ''; ?>" />
|
||||
<label for="end_date">End:</label>
|
||||
<input type="text" name="end_date" id="end_date" value="<? echo isset($url_params['end_date']) ? $url_params['end_date'] : ''; ?>" />
|
||||
</span>
|
||||
|
||||
<label for="product">Product:</label>
|
||||
<select name="product" id="product">
|
||||
<?php
|
||||
foreach ($products as $select) :
|
||||
$product = $select['Application']['name'].' '.$select['Application']['version'];
|
||||
$selected = ($product == trim($url_params['product'])) ? ' selected="selected" ' : '';
|
||||
?>
|
||||
<option<?=$selected?>><?=$product?></option>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php if (!empty($collections)) : ?>
|
||||
<label for="collection">Questions:</label>
|
||||
<select name="collection" id="collection">
|
||||
<?php
|
||||
foreach ($collections as $select) :
|
||||
$collection = $select['collections']['description'];
|
||||
// php's built in functions won't decode UTF-8 or numeric
|
||||
// entities. Since we've only got 1, I'm putting in this to
|
||||
// get this done quickly. :(
|
||||
$url_params['collection'] = str_replace('-','-',urldecode($url_params['collection']));
|
||||
echo "{$url_params['collection']}<br />";
|
||||
$selected = ($collection == trim($url_params['collection'])) ? ' selected="selected" ' : '';
|
||||
?>
|
||||
<option<?=$selected?>><?=$collection?></option>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php endif; ?>
|
||||
|
||||
<input type="submit" name="submit" id="submit" value="Go" />
|
||||
</form>
|
||||
<br />
|
||||
<div id="querynote">
|
||||
(Date format is yyyy-mm-dd. A blank date will use the largest possible range.)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($descriptionAndTotalsData)) : ?>
|
||||
<?php
|
||||
/* Prepare data for graphing */
|
||||
$_dataset = '';
|
||||
$_count = 0;
|
||||
$_total = 0;
|
||||
/* We've got to do 2 loops here because I need the totals to calculate
|
||||
* percentages.
|
||||
*/
|
||||
foreach ($descriptionAndTotalsData as $var => $val) {
|
||||
$_total += $val[0]['total'];
|
||||
}
|
||||
foreach ($descriptionAndTotalsData as $var => $val) {
|
||||
// We're putting this in a js string, so escape the double quotes
|
||||
$_description = str_replace('"','\"',$val['choices']['description']);
|
||||
$_percentage = intval(($val[0]['total'] / $_total)*100);
|
||||
|
||||
$_dataset .= "[{$_count}, {$val[0]['total']}, \"{$_description} (n={$val[0]['total']}, {$_percentage}%)\"], ";
|
||||
$_count++;
|
||||
}
|
||||
$_dataset = "[{$_dataset}]";
|
||||
?>
|
||||
<div id="graphcontainer">
|
||||
<canvas id="graph" height="400" width="800">
|
||||
<table class="results" summary="Firefox Uninstallation results.">
|
||||
<tr><th>Reason for uninstalling</th><th>Total</th></tr>
|
||||
<?php foreach ($descriptionAndTotalsData as $var => $val) : ?>
|
||||
<tr><td><?=$val['choices']['description']?></td><td><?=$val[0]['total']?></td></tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</canvas>
|
||||
</div>
|
||||
<script type="text/javascript"><!--
|
||||
var layout = new PlotKit.Layout("bar", {"barOrientation":"horizontal"});
|
||||
layout.addDataset("results", <?=$_dataset?>);
|
||||
layout.evaluate();
|
||||
|
||||
var canvas = MochiKit.DOM.getElement("graph");
|
||||
var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout,
|
||||
{
|
||||
"drawYAxis" : false,
|
||||
"drawXAxis" : false,
|
||||
"backgroundColor" : Color.fromHexString('#78c'),
|
||||
"strokeColor" : Color.fromHexString('#777'),
|
||||
"strokeWidth" : 1.0,
|
||||
"enableEvents" : false
|
||||
});
|
||||
|
||||
plotter.render();
|
||||
--></script>
|
||||
|
||||
|
||||
<div id="exportbox">
|
||||
<a href="<?php echo $export->buildUrlString('results/comments/',$url_params); ?>">View Any Associated Comments»</a><br />
|
||||
<?php
|
||||
$export_url = $export->buildCsvExportString($url_params);
|
||||
if (!empty($export_url)):
|
||||
?>
|
||||
<a href="<?php echo $export_url; ?>">Download the Complete Dataset»</a><br />
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<div id="notice">There is no data available for your parameters. Please review your search criteria.</div>
|
||||
|
||||
<?php endif; ?>
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
/* SVN FILE: $Id: index.php,v 1.2 2006-11-01 23:10:21 timeless%mozdev.org Exp $ */
|
||||
/* SVN FILE: $Id: index.php,v 1.3 2007-01-02 19:39:46 wclouser%mozilla.com Exp $ */
|
||||
|
||||
/**
|
||||
* Short description for file.
|
||||
|
@ -22,9 +22,9 @@
|
|||
* @package cake
|
||||
* @subpackage cake.app.webroot
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.2 $
|
||||
* @version $Revision: 1.3 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-11-01 23:10:21 $
|
||||
* @lastmodified $Date: 2007-01-02 19:39:46 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
|
@ -45,14 +45,15 @@ if (!defined('DS'))
|
|||
if (!defined('ROOT'))
|
||||
{
|
||||
//define('ROOT', 'FULL PATH TO DIRECTORY WHERE APP DIRECTORY IS LOCATED DO NOT ADD A TRAILING DIRECTORY SEPARATOR';
|
||||
//You should also use the DS define to separate your directories
|
||||
//You should also use the DS define to seperate your directories
|
||||
define('ROOT', dirname(dirname(dirname(__FILE__))));
|
||||
}
|
||||
|
||||
if (!defined('APP_DIR'))
|
||||
{
|
||||
//define('APP_DIR', 'DIRECTORY NAME OF APPLICATION';
|
||||
define ('APP_DIR', basename(dirname(dirname(__FILE__))));
|
||||
//define ('APP_DIR', basename(dirname(dirname(__FILE__))));
|
||||
define ('APP_DIR', 'uninstall_survey');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,8 +63,9 @@ if (!defined('APP_DIR'))
|
|||
if (!defined('CAKE_CORE_INCLUDE_PATH'))
|
||||
{
|
||||
//define ('CAKE_CORE_INCLUDE_PATH', FULL PATH TO DIRECTORY WHERE CAKE CORE IS INSTALLED DO NOT ADD A TRAILING DIRECTORY SEPARATOR';
|
||||
//You should also use the DS define to separate your directories
|
||||
define('CAKE_CORE_INCLUDE_PATH', ROOT);
|
||||
//You should also use the DS define to seperate your directories
|
||||
define('CAKE_CORE_INCLUDE_PATH', DS.'usr'.DS.'local'.DS.'lib'.DS.'php'.DS.'cake');
|
||||
//define('CAKE_CORE_INCLUDE_PATH', ROOT);
|
||||
}
|
||||
|
||||
|
||||
|
@ -111,4 +113,4 @@ if (DEBUG)
|
|||
{
|
||||
echo "<!-- ". round(getMicrotime() - $TIME_START, 4) ."s -->";
|
||||
}
|
||||
?>
|
||||
?>
|
||||
|
|
0
webtools/uninstall_survey/webroot/js/plotkit-0.8/README → webtools/uninstall_survey/webroot/js/plotkit-0.9.1/PlotKit/excanvas.js
Normal file → Executable file
0
webtools/uninstall_survey/webroot/js/plotkit-0.8/README → webtools/uninstall_survey/webroot/js/plotkit-0.9.1/PlotKit/excanvas.js
Normal file → Executable file
Загрузка…
Ссылка в новой задаче