diff --git a/assets/images/false.png b/assets/images/failure.png similarity index 100% rename from assets/images/false.png rename to assets/images/failure.png diff --git a/assets/images/true.png b/assets/images/success.png similarity index 100% rename from assets/images/true.png rename to assets/images/success.png diff --git a/assets/massuploadutility.css b/assets/massuploadutility.css index eee2e7c..35cbd86 100755 --- a/assets/massuploadutility.css +++ b/assets/massuploadutility.css @@ -17,7 +17,11 @@ height: 100%; } +#error #file_list { +} + #file_list { + color: black; height: 100px; overflow: auto; padding: 8px; diff --git a/assets/massuploadutility.js b/assets/massuploadutility.js index a41b78e..f1de3ee 100644 --- a/assets/massuploadutility.js +++ b/assets/massuploadutility.js @@ -5,13 +5,13 @@ // check for html5 input multiple support first html5Support = ("multiple" in document.createElement("input")); if(!html5Support){ - alert("Sorry, your browser doesn't support HTML5!"); + console.log("Sorry, your browser doesn't support HTML5!"); return false; } Symphony.Language.add({ 'Successfully added a whole slew of entries, {$total} to be exact.': false, - 'But {$total} entries were successfully added.': false, + 'However, {$total} entries were successfully added.': false, 'Some errors were encountered while attempting to save.': false, 'View all Entries': false, 'Create more?': false, @@ -35,7 +35,6 @@ return string.replace(/([^\w\d_-])/gi,'-'); }; - // if there's more than one upload field, I have no idea what to do, and it's not terribly important if (fileField.size() == 1) { label = fileField.parent().parent(); @@ -44,6 +43,7 @@ fileField.attr('multiple', 'true'); fileField.parent().append(" \ \ + \
\
\
\ @@ -69,6 +69,7 @@ return urlBase + urlMuu + '?' + string; }, autostart: false, + autoclear: false, method: "post", sendBoundary: window.FormData || $.browser.mozilla, onChange: function(event, files) { @@ -100,33 +101,60 @@ $("#progress_report_bar").css('width', Math.ceil(val*100)+"%"); }, onFinishOne: function(event, response, name, number, total) { - // check json["message"] if its set nothing happened at all. + // change errorsInQueue to true if you want errors shown in the queue and not on the fields themselves + errorsInQueue = false; json = $.parseJSON(response); - css = (json.status == 1) ? "success" : "failure"; id = idSafeFilename(name); - p = "

 " + name + " "; - $.each(json["errors"], function(k,v) { - p += v; - }); - p += "

"; + p = "

"; + if (json != null) { + css = (json.response["_result"] == 'error') ? "failure" : "success"; + p += " " + name + " "; + if (json.response["_result"] == "error") { + $.each(json.response, function(k,v) { + if (k != "_result" && k != "message" && k != "post-values") { + field = $("form *[name='fields["+k+"]']"); + if (errorsInQueue || field.attr('type') == 'file') { + p += v._message + " "; + } + else { + // highlight the fields that have errors + // if (v._type == "missing") { + field = field.parents("label"); + console.log(field); + if (field.parent().attr('id') != 'error') { + // field.children(":first").attr("name") + " " + v; + field.wrap("

"); + field.parent().append("

" + v._message + "

"); + } + } + } + }); + } + p += "

"; + } + else { + p += "An unknown error occurred.

"; + } $("#file_list").show(); $('p#'+id).replaceWith(p); + }, onFinish: function(total) { failed = $("#MUU-list.failure").size(); total = failed + $("#MUU-list.success").size(); success = total - failed; p = "

0) { p += "success\">" + Symphony.Language.get('Successfully added a whole slew of entries, {$total} to be exact.', { 'total': total }); p += " \ "+Symphony.Language.get("Create more?")+" \ - "+Symphony.Language.get("View all Entries")+""; + "+Symphony.Language.get("View all Entries")+""; + // reset the form here maybe } else { p += "error\">" + Symphony.Language.get('Some errors were encountered while attempting to save.'); if (success > 0) - p += " " + Symphony.Language.get('But {$total} entries were successfully added.', { 'total' : success}); + p += " " + Symphony.Language.get('However, {$total} entries were successfully added.', { 'total' : success}); $("#file_list") .animate({ backgroundColor: "#eeee55", opacity: 1.0 }, 200) .animate({ backgroundColor: "transparent", opacity: 1.0}, 350); @@ -159,10 +187,10 @@ }); } else if (fileField.size() > 1) { - console.log("MUU doesn't work with multiple upload fields"); + console.log("The Mass Upload Utility doesn't work with multiple upload fields."); } else { - console.log("No upload fields detected"); + console.log("No upload fields detected."); } }); diff --git a/content/content.index.php b/content/content.index.php index c7de71f..71e8629 100644 --- a/content/content.index.php +++ b/content/content.index.php @@ -3,6 +3,9 @@ require_once(TOOLKIT . '/class.administrationpage.php'); require_once(TOOLKIT . '/class.sectionmanager.php'); require_once(TOOLKIT . '/class.entrymanager.php'); + require_once(CORE . '/class.frontend.php'); + require_once(EXTENSIONS . '/massuploadutility/events/event.mass_upload_utility_entry.php'); + require_once(EXTENSIONS . '/massuploadutility/lib/class.xmltoarray.php'); /** * Called to build the content for the page. @@ -13,8 +16,8 @@ class contentExtensionMassUploadUtilityIndex extends AdministrationPage { protected $_valid = false; protected $_message = ''; - public function getSectionID() { - $sectionManager = new SectionManager($this->_Parent); + public function getSectionId() { + $sectionManager = new SectionManager(Frontend::instance()); $section_id = $sectionManager->fetchIDFromHandle(General::sanitize($_REQUEST['MUUsource'])); @@ -24,109 +27,34 @@ public function getSectionID() { return $section_id; } /** - * --------------------------------------------------------- - * This functionality is essentially duplicated (and slightly changed) - * from Symphony's content.publish.php - * in the function public function __actionNew(){ - * Should that core ever change, this needs to be as well. * - * _REQUEST view() are used because jquery.html5_upload.js can't deal + * _REQUEST in view() are used because jquery.html5_upload.js can't deal * with extra variables in the POST * Should this change, view() will need to be changed to action() * --------------------------------------------------------- */ public function view() { if (!isset($_REQUEST['MUUsource']) or $_REQUEST['MUUsource'] == '') - { $this->_message = __("You didn't choose a source, perhaps you don't have any sections with an upload field in them?"); $this->__response(); } - - if (($section_id = $this->getSectionID()) === NULL) - { $this->_message = __('The Section you are looking, %s for could not be found.', $this->_context['section_handle']); $this->__response(); } - $sectionManager = new SectionManager($this->_Parent); - - $entryManager = new EntryManager($this->_Parent); + { exit; } - $entry =& $entryManager->create(); - $entry->set('section_id', $section_id); - $entry->set('author_id', Administration::instance()->Author->get('id')); - $entry->set('creation_date', DateTimeObj::get('Y-m-d H:i:s')); - $entry->set('creation_date_gmt', DateTimeObj::getGMT('Y-m-d H:i:s')); - - $fields = $_REQUEST['fields']; - if ((!$this->__processFilePostData($fields)) === NULL) - { $this->_message = __("Did you forget to upload some files?"); $this->__response(); } - - if(__ENTRY_FIELD_ERROR__ == $entry->checkPostData($fields, $error)) - { $this->_errors[key($error)] = $error[key($error)]; $this->__response(); } + if (($section_id = $this->getSectionId()) === NULL) + { exit; } - // setup the data, process it - // if(__ENTRY_OK__ != $this->setDataFromPost($entry, $fields, $this->_errors, false, false, $entries)) - elseif(__ENTRY_OK__ != $entry->setDataFromPost($fields, $error)) { - $this->_errors[key($error)] = $error[key($error)]; - $this->__response(); - } + $_POST['fields'] = $_REQUEST['fields']; + $_POST['action'] = $_REQUEST['action']; - else { - Symphony::ExtensionManager()->notifyMembers('EntryPreCreate', '/publish/new/', array('section' => $section, 'entry' => &$entry, 'fields' => &$nfields)); + $event = new Event_Mass_Upload_Utility_Entry(Frontend::instance(), array()); - $prepopulate_field_id = $prepopulate_value = NULL; - if(isset($_POST['prepopulate'])){ - $prepopulate_field_id = array_shift(array_keys($_POST['prepopulate'])); - $prepopulate_value = stripslashes(rawurldecode(array_shift($_POST['prepopulate']))); - } + // Borrowed from Nick Dunn + $xml = $event->load(); + if(is_array($xml)) $xml = reset($xml); + if($xml instanceOf XMLElement) $xml = $xml->generate(TRUE); - // commit the entry if we made it - if(!$entry->commit()){ - define_safe('__SYM_DB_INSERT_FAILED__', true); - $this->pageAlert(NULL, Alert::ERROR); - } - else - { - // keep track of it if it was inserted - $entries[] = $entry->get('id'); - $this->_valid = true; - Symphony::ExtensionManager()->notifyMembers('EntryPostCreate', '/publish/new/', array('section' => $section, 'entry' => $entry, 'fields' => $nfields)); - } + echo(json_encode(XMLToArray::convert($xml))); - } - - $this->__response(); exit; } - - /* main page */ - - - public function __processFilePostData(&$fields) { - if(isset($_FILES['fields'])){ - $filedata = General::processFilePostData($_FILES['fields']); - - foreach($filedata as $handle => $data){ - if(!isset($fields[$handle])) $fields[$handle] = $data; - elseif(isset($data['error']) && $data['error'] == 4) $fields['handle'] = NULL; - else{ - foreach($data as $ii => $d){ - if(isset($d['error']) && $d['error'] == 4) $fields[$handle][$ii] = NULL; - elseif(is_array($d) && !empty($d)){ - - foreach($d as $key => $val) - $fields[$handle][$ii][$key] = $val; - } - } - } - } - return TRUE; - } - else - return NULL; - - } - - - private function __response() { - echo json_encode(array("status"=>$this->_valid, "message"=>$this->_message, "errors" => $this->_errors)); - exit; - } } ?> diff --git a/events/event.mass_upload_utility_entry.php b/events/event.mass_upload_utility_entry.php index 295d4b0..bdec7c0 100644 --- a/events/event.mass_upload_utility_entry.php +++ b/events/event.mass_upload_utility_entry.php @@ -1,8 +1,12 @@ 'http://tesoriere.com', 'email' => 'scott@tesoriere.com'), 'version' => '1.0', - 'release-date' => '2009-11-13T11:35:07+00:00', + 'release-date' => '2011-05-12T11:35:07+00:00', 'trigger-condition' => 'action[api]'); } @@ -28,8 +32,8 @@ public static function documentation(){ return ''; } - public function load(){ - return $this->__trigger(); + public function load(){ + if(isset($_POST['action']['api'])) return $this->__trigger(); } protected function __trigger(){ diff --git a/lang/lang.de.example.php b/lang/lang.de.example.php deleted file mode 100644 index 2239301..0000000 --- a/lang/lang.de.example.php +++ /dev/null @@ -1,25 +0,0 @@ - 'Deutsch', - 'author' => array( - 'name' => 'Scott Tesoriere', - 'email' => 'scott@tesoriere.com', - 'website' => 'http://tesoriere.com' - ), - 'release-date' => '2011-05-09' - ); - - /** - * Mass Upload Utility - */ - $dictionary = array( - - 'Did you forget to upload some files?' => - '', - - 'You didn\'t choose a source, perhaps you don\'t have any sections with an upload field in them?' => - '', - - - ); diff --git a/lib/class.xmltoarray.php b/lib/class.xmltoarray.php new file mode 100644 index 0000000..8190702 --- /dev/null +++ b/lib/class.xmltoarray.php @@ -0,0 +1,72 @@ + +https://github.com/nickdunn/rest_api/blob/master/lib/class.xmltoarray.php + +Converts a string of XML to a keyed array +Adapted from http://mysrc.blogspot.com/2007/02/php-xml-to-array-and-backwards.html +*/ +Class XMLToArray { + + public static function convert($string) { + $parser = xml_parser_create(); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parse_into_struct($parser, $string, $vals, $index); + xml_parser_free($parser); + + $return = array(); + $ary = &$return; + + foreach ($vals as $r) { + + $t = $r['tag']; + + if ($r['type'] == 'open' || $r['type']=='complete') { + + if (isset($ary[$t])) { + if (isset($ary[$t][0])) { + $ary[$t][] = array(); + } else { + $ary[$t] = array($ary[$t], array()); + } + $cv = &$ary[$t][count($ary[$t])-1]; + } else { + $cv = &$ary[$t]; + } + if (isset($r['attributes'])) { + foreach ($r['attributes'] as $k => $v) { + $cv['_' . $k] = $v; + } + } + } + + if ($r['type'] == 'open') { + //$cv[] = array(); + $cv['_p'] = &$ary; + $ary = &$cv; + } + elseif ($r['type']=='complete') { + $cv['value'] = (isset($r['value']) ? $r['value'] : ''); + } + elseif ($r['type']=='close') { + $ary = &$ary['_p']; + } + } + + self::deleteParents($return); + return $return; + } + + // Remove recursion in result array + private function deleteParents(&$ary) { + foreach ($ary as $k => $v) { + if ($k === '_p') { + unset($ary[$k]); + } + elseif (is_array($ary[$k])) { + self::deleteParents($ary[$k]); + } + } + } + +} \ No newline at end of file diff --git a/readme.md b/readme.md index c090d79..96b8ab2 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,7 @@ # Mass Upload Utility -- Version: 0.9.3 -- Date: 10 May 2011 +- Version: 0.9.5 +- Date: 12 May 2011 - Requirements: Symphony 2.2 - Author: Scott Tesoriere - Github Repository: http://github.com/scottkf/massuploadutility @@ -11,12 +11,25 @@ THIS REQUIRES AN HTML5 COMPATIBLE BROWSER If you're using an older version of Symphony, please use v0.9 of the Mass Upload Utility: https://github.com/scottkf/massuploadutility/tree/v0.9 -## PURPOSE +## Purpose A symphony extension to allow you to add a folder of files into a section that has an upload field, it *should* work with all upload fields. Testing is needed. -## CHANGELOG +## Changelog + +**v0.9.5** + +- No longer clears files from the input[file] box if failed +- Under the hood changes, no longer duplicates Symphony code, uses a custom event to add entries. + Inspiration and thanks to Nick Dunn and his REST API extension! +- Will highlight which fields have problems and display errors on them (except the upload field) + This may get obnoxious and I might turn it off. This is instead of showing them in the queue list. + It's customizable by changing a variable in the javascript. + +**v0.9.4** + +- Under the hood changes, internal **v0.9.3** @@ -56,8 +69,8 @@ has an upload field, it *should* work with all upload fields. Testing is needed. ## Todo -- Repopulate the upload list (or don't delete) if a file fails to upload for whatever reason - Possibly expand the {$} variables to contain other things (like what?) +- Refine the UI some ## Installation @@ -79,5 +92,5 @@ has an upload field, it *should* work with all upload fields. Testing is needed. ## Bugs/Features -- If you receive an error on the form, you have to select all the files again -- If more than one upload field is in a section, this will fail on purpose (feature?) +- If more than one upload field is in a section, this will not get used + I consider this more a feature.