Merge branch 'cc-84-smart-playlist' of dev.sourcefabric.org:airtime into cc-84-smart-playlist

This commit is contained in:
Martin Konecny 2012-07-12 15:30:31 -04:00
commit a8f4148373
5 changed files with 340 additions and 36 deletions

View File

@ -22,6 +22,8 @@ class PlaylistController extends Zend_Controller_Action
->addActionContext('set-playlist-description', 'json')
->addActionContext('playlist-preview', 'json')
->addActionContext('get-playlist', 'json')
->addActionContext('smart-playlist-criteria-save', 'json')
->addActionContext('smart-playlist-generate', 'json')
->initContext();
$this->pl_sess = new Zend_Session_Namespace(UI_PLAYLIST_SESSNAME);
@ -438,5 +440,21 @@ class PlaylistController extends Zend_Controller_Action
$this->playlistUnknownError($e);
}
}
public function smartPlaylistCriteriaSaveAction()
{
$request = $this->getRequest();
$params = $request->getPost();
Application_Model_Playlist::saveSmartPlaylistCriteria($param['data']);
}
public function smartPlaylistGenerateAction()
{
$request = $this->getRequest();
$params = $request->getPost();
$result = Application_Model_Playlist::generateSmartPlaylist($params['data']);
die(json_encode($result));
}
}

View File

@ -9,7 +9,7 @@ class Application_Form_SmartPlaylistCriteria extends Zend_Form_SubForm
"album_title" => "Album",
"artist_name" => "Artist",
"bit_rate" => "Bit Rate",
"bmp" => "Bpm",
"bpm" => "Bpm",
"comments" => "Comments",
"composer" => "Composer",
"conductor" => "Conductor",
@ -34,29 +34,6 @@ class Application_Form_SmartPlaylistCriteria extends Zend_Form_SubForm
"year" => "Year"
);
$criteriaTypes = array(
);
$stringCriteriaOptions = array(
0 => "Select modifier",
"contains" => "contains",
"does not contain" => "does not contain",
"is" => "is",
"is not" => "is not",
"starts with" => "starts with",
"ends with" => "ends with"
);
$numericCriteriaOptions = array(
0 => "Select modifier",
"is" => "is",
"is not" => "is not",
"is greater than" => "is greater than",
"is less than" => "is less than",
"is in the range" => "is in the range"
);
$limitOptions = array(
"hours" => "hours",
"minutes" => "minutes",
@ -94,7 +71,7 @@ class Application_Form_SmartPlaylistCriteria extends Zend_Form_SubForm
$criteriaModifers->setValue('Select modifier');
$criteriaModifers->setAttrib('class', 'input_select');
$criteriaModifers->setDecorators(array('viewHelper'));
$criteriaModifers->setMultiOptions($stringCriteriaOptions);
$criteriaModifers->setMultiOptions(array('0' => 'Select modifier'));
if ($i != 0){
$criteriaModifers->setAttrib('disabled', 'disabled');
}

View File

@ -45,6 +45,47 @@ class Application_Model_Playlist {
"dc:description" => "Description",
"dcterms:extent" => "Length"
);
private static $modifier2CriteriaMap = array(
"contains" => Criteria::LIKE,
"does not contain" => Criteria::NOT_LIKE,
"is" => Criteria::EQUAL,
"is not" => Criteria::NOT_EQUAL,
"starts with" => Criteria::LIKE,
"ends with" => Criteria::LIKE,
"is greater than" => Criteria::GREATER_THAN,
"is less than" => Criteria::LESS_THAN,
"is in the range" => Criteria::CUSTOM);
private static $criteria2PeerMap = array(
0 => "Select criteria",
"album_title" => CcFilesPeer::ALBUM_TITLE,
"artist_name" => CcFilesPeer::ARTIST_NAME,
"bit_rate" => CcFilesPeer::BIT_RATE,
"bpm" => CcFilesPeer::BPM,
"comments" => CcFilesPeer::COMMENTS,
"composer" => CcFilesPeer::COMPOSER,
"conductor" => CcFilesPeer::CONDUCTOR,
"utime" => CcFilesPeer::UTIME,
"mtime" => CcFilesPeer::MTIME,
"disc_number" => CcFilesPeer::DISC_NUMBER,
"genre" => CcFilesPeer::GENRE,
"isrc_number" => CcFilesPeer::ISRC_NUMBER,
"label" => CcFilesPeer::LABEL,
"language" => CcFilesPeer::LANGUAGE,
"length" => CcFilesPeer::LENGTH,
"lyricist" => CcFilesPeer::LYRICIST,
"mood" => CcFilesPeer::MOOD,
"name" => CcFilesPeer::NAME,
"orchestra" => CcFilesPeer::ORCHESTRA,
"radio_station_name" => CcFilesPeer::RADIO_STATION_NAME,
"rating" => CcFilesPeer::RATING,
"sample_rate" => CcFilesPeer::SAMPLE_RATE,
"soundcloud_id" => CcFilesPeer::SOUNDCLOUD_ID,
"track_title" => CcFilesPeer::TRACK_TITLE,
"track_num" => CcFilesPeer::TRACK_NUMBER,
"year" => CcFilesPeer::YEAR
);
public function __construct($id=null, $con=null)
@ -806,6 +847,139 @@ class Application_Model_Playlist {
{
CcPlaylistQuery::create()->findPKs($p_ids)->delete();
}
// smart playlist functions start
/**
* Saves smart playlist criteria
* @param array $p_criteria
*/
public static function saveSmartPlaylistCriteria($p_criteria)
{
$data = self::organizeSmartPlyalistCriteria($p_criteria);
// things we need to check
// 1. limit value shouldn't be empty and has upperbound of 24 hrs
// 2. sp_criteria or sp_criteria_modifier shouldn't be 0
$multiplier = 1;
$result = 0;
$errors = array();
if ($data['etc']['sp_limit_options'] == 'hours') {
$multiplier = 60;
}
if ($data['etc']['sp_limit_options'] == 'hours' || $data['etc']['sp_limit_options'] == 'mins') {
if ( $data['etc']['sp_limit_value'] == "" || intval($data['etc']['sp_limit_value']) == 0) {
$error[] = "Litmit cannot be empty or 0";
} else {
$mins = $data['etc']['sp_limit_value'] * $multiplier;
if ($mins > 14400) {
$error[] = "Litmit cannot be more than 24 hrs";
}
}
$errors[] = array("element"=>"sp_limit_value", "msg"=>$error);
}
// format validation
foreach ($data['criteria'] as $key=>$d){
$error = array();
// check for not selected select box
if ($d['sp_criteria'] == "0" || $d['sp_criteria_modifier'] == "0"){
$error[] = "You must select Criteria and Modifier";
} else {
// we need to take care 'length' specially since the column type is varchar
if ($d['sp_criteria'] == 'length') {
if (!preg_match("/(\d{2}):(\d{2}):(\d{2})/", $d['sp_criteria_value'])) {
$error[] = "'Length' should be in '00:00:00' format";
}
}else{
if (CcFilesPeer::getTableMap()->getColumn(self::$criteria2PeerMap[$d['sp_criteria']])->getType() == PropelColumnTypes::TIMESTAMP) {
if (!preg_match("/(\d{4})-(\d{2})-(\d{2})/", $d['sp_criteria_value'])) {
$error[] = "The value should be in timestamp format(eg. 0000-00-00 or 00-00-00 00:00:00";
}
}
}
}
if ($d['sp_criteria_value'] == "") {
$error[] = "Value cannot be empty";
}
$errors[] = array("element"=>"sp_criteria_".$key, "msg"=>$error);
}
$result = count($errors) > 0 ? 1 :0;
return array("result"=>$result, "errors"=>$errors);
}
/**
* Get smart playlist criteria
* @param array $p_playlistId
*/
public static function getSmartPlaylistCriteria($p_playlistId)
{
}
/**
* generate list of tracks. This function saves creiteria and generate
* tracks.
* @param array $p_criteria
*/
public static function generateSmartPlaylist($p_criteria)
{
$result = self::saveSmartPlaylistCriteria($p_criteria);
if ($result['result'] != 0) {
return $result;
}else{
Logging::log($p_criteria);
$data = self::organizeSmartPlyalistCriteria($p_criteria);
$list = self::getListofFilesMeetCriteria($data['criteria']);
}
}
// this function return list of propel object
private static function getListofFilesMeetCriteria($p_data)
{
$c = new Criteria();
foreach ($p_data as $criteria) {
$spCriteria = self::$criteria2PeerMap[$criteria['sp_criteria']];
$spCriteriaModifier = $criteria['sp_criteria_modifier'];
$spCriteriaValue = $criteria['sp_criteria_value'];
if ($spCriteriaModifier == "starts with") {
$spCriteriaValue = "$spCriteriaValue%";
} else if ($spCriteriaModifier == "ends with") {
$spCriteriaValue = "%$spCriteriaValue";
} else if ($spCriteriaModifier == "is in the range") {
$spCriteriaValue = "$spCriteria > '$spCriteriaValue' AND $spCriteria < '$criteria[sp_criteria_extra]'";
}
$spCriteriaModifier = self::$modifier2CriteriaMap[$spCriteriaModifier];
$c->add($spCriteria, $spCriteriaValue, $spCriteriaModifier);
}
try{
$out = CcFilesPeer::doSelect($c);
}catch(Exception $e){
//Logging::log($e);
}
}
private static function organizeSmartPlyalistCriteria($p_criteria)
{
$fieldNames = array('sp_criteria', 'sp_criteria_modifier', 'sp_criteria_value', 'sp_criteria_extra');
$output = array();
foreach ($p_criteria as $ele) {
$index = strrpos($ele['name'], '_');
$fieldName = substr($ele['name'], 0, $index);
if (in_array($fieldName, $fieldNames)) {
$rowNum = intval(substr($ele['name'], $index+1));
$output['criteria'][$rowNum][$fieldName] = trim($ele['value']);
}else{
$output['etc'][$ele['name']] = $ele['value'];
}
}
return $output;
}
// smart playlist functions end
} // class Playlist

View File

@ -26,11 +26,13 @@
<?php echo $this->element->getElement('sp_criteria_modifier_'.$i) ?>
<?php echo $this->element->getElement('sp_criteria_value_'.$i) ?>
<?php if ($i != 0) { ?>
<a href='#' id='criteria_remove_<?php echo $i ?>'>Remove</a>
<a href='#' id='criteria_remove_<?php echo $i ?>'>Remove&nbsp;</a>
<?php } else { ?>
<a href='#' id='criteria_add'>Add</a>
<?php } ?>
</div>
<?php } ?>
<a href='#' id='criteria_add'>Add</a>
</dd>
<dd id='sp_limit-element'>

View File

@ -3,34 +3,77 @@ $(document).ready(function() {
});
function setSmartPlaylistEvents() {
var form = $('#smart-playlist-form');
var form = $('#smart-playlist-form');
form.find('a[id="criteria_add"]').click(function(){
var div = $('dd[id="sp_criteria-element"]').children('div:visible:last').next();
form.find('a[id="criteria_add"]').click(function(){
var div = $('dd[id="sp_criteria-element"]').children('div:visible:last').next(),
add_button = $(this);
div.show();
div.find('a[id^="criteria_remove"]').after(add_button);
div.children().removeAttr('disabled');
div = div.next();
if(div.length === 0) {
if (div.length === 0) {
$(this).hide();
}
});
});
form.find('a[id^="criteria_remove"]').click(function(){
form.find('a[id^="criteria_remove"]').click(function(){
var curr = $(this).parent();
var curr_pos = curr.index();
var list = curr.parent();
var list_length = list.find("div:visible").length;
var count = list_length - curr_pos;
var next = curr.next();
for(var i=0; i<=count; i++) {
var add_button = form.find('a[id="criteria_add"]');
/* assign next row to current row for all rows below and including
* the row getting removed
*/
for (var i=0; i<=count; i++) {
var criteria = next.find('[name^="sp_criteria"]').val();
curr.find('[name^="sp_criteria"]').val(criteria);
var modifier = next.find('[name^="sp_criteria_modifier"]').val();
curr.find('[name^="sp_criteria_modifier"]').val(modifier);
var criteria_value = next.find('[name^="sp_criteria_value"]').val();
curr.find('[name^="sp_criteria_value"]').val(criteria_value);
/* if current and next row have the extra criteria value
* (for 'is in the range' modifier), then assign the next
* extra value to current and remove that element from
* next row
*/
if (curr.find('[name^="sp_criteria_extra"]').length > 0
&& next.find('[name^="sp_criteria_extra"]').length > 0) {
var criteria_extra = next.find('[name^="sp_criteria_extra"]').val();
curr.find('[name^="sp_criteria_extra"]').val(criteria_extra);
next.find('[name^="sp_criteria_extra"]').remove();
next.find('span[id="sp_criteria_extra_label"]').remove();
/* if only the current row has the extra criteria value,
* then just remove the current row's extra criteria element
*/
} else if (curr.find('[name^="sp_criteria_extra"]').length > 0
&& next.find('[name^="sp_criteria_extra"]').length == 0) {
curr.find('[name^="sp_criteria_extra"]').remove();
curr.find('span[id="sp_criteria_extra_label"]').remove();
/* if only the next row has the extra criteria value,
* then add the extra criteria element to current row
* and assign next row's value to it
*/
} else if (next.find('[name^="sp_criteria_extra"]').length > 0) {
var index_name = curr.find('[name^="sp_criteria_value"]').attr('id'),
index_num = index_name.charAt(index_name.length-1),
criteria_extra = next.find('[name^="sp_criteria_extra"]').val();
curr.find('[name^="sp_criteria_value"]')
.after($('<input type="text" class="input_text">')
.attr('id', 'sp_criteria_extra_'+index_num)
.attr('name', 'sp_criteria_extra_'+index_num)).after('<span id="sp_criteria_extra_label"> to </span>');
curr.find('[name^="sp_criteria_extra"]').val(criteria_extra);
}
curr = next;
next = curr.next();
@ -44,6 +87,13 @@ function setSmartPlaylistEvents() {
.end().hide();
list.next().show();
// always put 'add' button on the last row
if (list.find('div:visible').length > 1) {
list.find('div:visible:last').find('a[id^="criteria_remove"]').after(add_button);
} else {
list.find('div:visible:last').find('[name^="sp_criteria_value"]').after(add_button);
}
});
form.find('button[id="save_button"]').click(function(event){
@ -74,6 +124,40 @@ function setSmartPlaylistEvents() {
}
$('button[id="save_button"]').text(button_text);
});
form.find('select[id^="sp_criteria"]').change(function(){
var criteria = $(this).val(),
criteria_type = criteriaTypes[criteria],
div = $(this);
$(this).next().children().remove();
if (criteria_type == 's') {
$.each(stringCriteriaOptions, function(key, value){
div.next().append($('<option></option>')
.attr('value', key)
.text(value));
});
} else {
$.each(numericCriteriaOptions, function(key, value){
div.next().append($('<option></option>')
.attr('value', key)
.text(value));
})
}
});
form.find('select[id^="sp_criteria_modifier"]').change(function(){
if ($(this).val() == 'is in the range') {
var criteria_value = $(this).next(),
index_name = criteria_value.attr('id'),
index_num = index_name.charAt(index_name.length-1);
criteria_value.after($('<input type="text" class="input_text">')
.attr('id', 'sp_criteria_extra_'+index_num)
.attr('name', 'sp_criteria_extra_'+index_num)).after('<span id="sp_criteria_extra_label"> to </span>');
}
});
}
@ -84,3 +168,52 @@ function staticCallback() {
function dynamicCallback() {
}
var criteriaTypes = {
0 : "",
"album_title" : "s",
"artist_name" : "s",
"bit_rate" : "n",
"bmp" : "n",
"comments" : "s",
"composer" : "s",
"conductor" : "s",
"utime" : "n",
"mtime" : "n",
"disc_number" : "n",
"genre" : "s",
"isrc_number" : "s",
"label" : "s",
"language" : "s",
"length" : "n",
"lyricist" : "s",
"mood" : "s",
"name" : "s",
"orchestra" : "s",
"radio_station_name" : "s",
"rating" : "n",
"sample_rate" : "n",
"soundcloud_id" : "n",
"track_title" : "s",
"track_num" : "n",
"year" : "n"
};
var stringCriteriaOptions = {
"0" : "Select modifier",
"contains" : "contains",
"does not contain" : "does not contain",
"is" : "is",
"is not" : "is not",
"starts with" : "starts with",
"ends with" : "ends with"
};
var numericCriteriaOptions = {
"0" : "Select modifier",
"is" : "is",
"is not" : "is not",
"is greater than" : "is greater than",
"is less than" : "is less than",
"is in the range" : "is in the range"
};