From 51b9518492808a7d3b025de94e65ee982405fcf6 Mon Sep 17 00:00:00 2001 From: colymba Date: Wed, 18 Jul 2012 02:12:10 +0300 Subject: [PATCH] Automatic Fields detection + EditForm generation Component now finds the Image relation and all 'editable fields' itself. Also gets the edit Forms from the record's getCMSFields() + other little fixes --- code/GridFieldBulkImageUpload.php | 35 ++- code/GridFieldBulkImageUpload_Request.php | 246 +++++++++++------- javascript/GridFieldBulkImageUpload.js | 2 +- ...idFieldBulkImageUpload_downloadtemplate.js | 13 +- 4 files changed, 186 insertions(+), 110 deletions(-) diff --git a/code/GridFieldBulkImageUpload.php b/code/GridFieldBulkImageUpload.php index 2045b91..d90dcfd 100644 --- a/code/GridFieldBulkImageUpload.php +++ b/code/GridFieldBulkImageUpload.php @@ -7,7 +7,6 @@ class GridFieldBulkImageUpload implements GridField_HTMLProvider, GridField_URLH * @var String */ protected $recordImageFieldName; - //protected $labelFieldName; /** * Target record editablez fields @@ -20,29 +19,45 @@ class GridFieldBulkImageUpload implements GridField_HTMLProvider, GridField_URLH * @param String $imageField * @param String/Array $editableFields */ - public function __construct($imageField, $editableFields) + public function __construct($imageField = null, $editableFields = null) { - $this->imageFieldName = $imageField; - - if ( !is_array($editableFields) ) $editableFields = array($editableFields); - $this->recordEditableFields = $editableFields; + $this->setRecordImageField($imageField); + + if ( !is_array($editableFields) && $editableFields != null ) $editableFields = array($editableFields); + $this->setRecordEditableFields($editableFields); } - public function setRecordImageField($field) + /** + * + * @param String $field + */ + function setRecordImageField($field) { - $this->imageFieldName = $field; + $this->recordImageFieldName = $field; } - public function setRecordEditableFields($fields) + /** + * + * @param Array $fields + */ + function setRecordEditableFields($fields) { $this->recordEditableFields = $fields; } + /** + * + * @return type + */ public function getRecordImageField() { - return $this->imageFieldName; + return $this->recordImageFieldName; } + /** + * + * @return type + */ public function getRecordEditableFields() { return $this->recordEditableFields; diff --git a/code/GridFieldBulkImageUpload_Request.php b/code/GridFieldBulkImageUpload_Request.php index a202bef..1a402c3 100644 --- a/code/GridFieldBulkImageUpload_Request.php +++ b/code/GridFieldBulkImageUpload_Request.php @@ -19,16 +19,19 @@ class GridFieldBulkImageUpload_Request extends RequestHandler { * @var Controller */ protected $controller; - + /** - * - * @var Array + * + * @var FieldList */ - protected $createdRecords; - + protected $recordCMSFieldList; + /** + * + */ static $url_handlers = array( - '$Action!' => '$Action' + '$Action!' => '$Action'/*, + '' => 'uploadForm'*/ ); /** @@ -40,27 +43,112 @@ class GridFieldBulkImageUpload_Request extends RequestHandler { public function __construct($gridField, $component, $controller) { $this->gridField = $gridField; $this->component = $component; - $this->controller = $controller; - $this->createdRecords = array(); + $this->controller = $controller; parent::__construct(); } /** * Returns the URL for this RequestHandler + * * @param String $action * @return String */ public function Link($action = null) { return Controller::join_links($this->gridField->Link(), 'bulkimageupload', $action); } - + + /** + * Returns the name of the Image field name from the managed record + * Either as set in the component config or the default one + * + * @return string + */ + function getRecordImageField() + { + $fieldName = $this->component->getRecordImageField(); + if ( $fieldName == null ) $fieldName = $this->getDefaultRecordImageField(); + + return $fieldName; + } + + /** + * Returns the list of editable fields from the managed record + * Either as set in the component config or the default ones + * + * @return array + */ + function getRecordEditableFields() + { + $fields = $this->component->getRecordEditableFields(); + if ( $fields == null ) $fields = $this->getDefaultRecordEditableFields(); + + return $fields; + } + + /** + * Get the first has_one Image realtion from the GridField managed DataObject + * + * @return string + */ + function getDefaultRecordImageField() + { + $recordClass = $this->gridField->list->dataClass; + $recordHasOneFields = Config::inst()->get($recordClass, 'has_one', Config::UNINHERITED); + + $imageField = null; + foreach( $recordHasOneFields as $field => $type ) + { + if ( $type == 'Image' ) { + $imageField = $field . 'ID'; + break; + } + } + + return $imageField; + } + + /** + * Return a list of the GridField managed DataObject (HTML)Text, (HTML)Varchar and Enum fields + * + * @return array + */ + function getDefaultRecordEditableFields() + { + $recordClass = $this->gridField->list->dataClass; + $recordDbFields = Config::inst()->get($recordClass, 'db', Config::UNINHERITED); + + $editableFields = array(); + foreach ( $recordDbFields as $field => $type ) + { + if ( preg_match( '/(Text|Varchar|Enum)/i', $type ) > 0 ) { + array_push($editableFields, $field); + } + } + + return $editableFields; + } + + /** + * Return the CMS edit field for a given name. As set in the GridField managed DataObject getCMSFields method + * @param string $fieldName + * @return FormField + */ + function getFieldEditForm($fieldName) + { + if ( !$this->recordCMSFieldList ) { + $recordClass = $this->gridField->list->dataClass; + $this->recordCMSFieldList = singleton($recordClass)->getCMSFields(); + } + + return $this->recordCMSFieldList->fieldByName($fieldName); + } + /** * Default and main action that returns the upload form etc... - * @param SS_HTTPRequest $request * @return String Form HTML ??? */ - public function index(SS_HTTPRequest $request) - { + public function index() + { Requirements::javascript(FRAMEWORK_DIR . '/javascript/AssetUploadField.js'); Requirements::css(FRAMEWORK_DIR . '/css/AssetUploadField.css'); @@ -68,13 +156,10 @@ class GridFieldBulkImageUpload_Request extends RequestHandler { Requirements::javascript('GridFieldBulkImageUpload/javascript/GridFieldBulkImageUpload.js'); Requirements::css('GridFieldBulkImageUpload/css/GridFieldBulkImageUpload.css'); + $crumbs = $this->Breadcrumbs(); + if($crumbs && $crumbs->count()>=2) $one_level_up = $crumbs->offsetGet($crumbs->count()-2); $actions = new FieldList(); - /* - $actions->push(FormAction::create('update', 'Finish') - ->setUseButtonTag(true)->addExtraClass('ss-ui-action-constructive')->addExtraClass('bulkImageUploadUpdateBtn')->setAttribute('data-icon', 'accept')); - */ - $html = " Link('update')."\" href=\"#\"> @@ -82,10 +167,9 @@ class GridFieldBulkImageUpload_Request extends RequestHandler { "; $actions->push(new LiteralField('savebutton', $html)); - $crumbs = $this->Breadcrumbs(); - if($crumbs && $crumbs->count()>=2){ - $one_level_up = $crumbs->offsetGet($crumbs->count()-2); - + + if($crumbs && $crumbs->count()>=2) + { $html = " Link('update')."\" href=\"".$one_level_up->Link."\"> Save All & Finish @@ -97,8 +181,7 @@ class GridFieldBulkImageUpload_Request extends RequestHandler { Cancel & Delete All "; $actions->push(new LiteralField('cancelbutton', $html)); - } - + } $uploadField = UploadField::create('BulkImageUploadField', ''); $uploadField->setConfig('previewMaxWidth', 40); @@ -124,24 +207,29 @@ class GridFieldBulkImageUpload_Request extends RequestHandler { ), $actions ); - + $form->setTemplate('LeftAndMain_EditForm'); - $form->addExtraClass('center cms-edit-form'); + $form->addExtraClass('center cms-edit-form cms-content'); $form->setAttribute('data-pjax-fragment', 'CurrentForm Content'); if($crumbs && $crumbs->count()>=2){ $form->Backlink = $one_level_up->Link; } - return $form->forTemplate(); - /* - $response = new SS_HTTPResponse(Convert::raw2json(array('Content' => $form->forTemplate()))); - $response->addHeader('Content-Type', 'text/json'); + $response = new SS_HTTPResponse($form->forTemplate()); + $response->addHeader('Content-Type', 'text/plain'); $response->addHeader('X-Title', 'SilverStripe - Bulk '.$this->gridField->list->dataClass.' Image Upload'); - return $response; */ + return $response; } - + /** + * Process image upload and Object creation + * Create new DataObject and add image relation + * returns Image data and editable Fields forms + * + * @param SS_HTTPRequest $request + * @return \SS_HTTPResponse + */ public function upload(SS_HTTPRequest $request) { $recordClass = $this->gridField->list->dataClass; @@ -165,10 +253,6 @@ class GridFieldBulkImageUpload_Request extends RequestHandler { 'type' => $tmpfile['type'], 'error' => $tmpfile['error'] ); - /* - $record->setField($this->component->getLabelFieldName(), $tmpfile['name']); - $record->write(); - */ } // Process the uploaded file @@ -189,10 +273,18 @@ class GridFieldBulkImageUpload_Request extends RequestHandler { } else { $file = $upload->getFile(); - // Attach the file to the related record. - $record->setField($this->component->getRecordImageField(), $file->ID); + // Attach the file to the related record. + $record->setField($this->getRecordImageField(), $file->ID); $record->write(); + + // collect all editable fields forms + $recordEditableFieldsForms = array(); + foreach ( $this->getRecordEditableFields() as $editableFieldName ) + { + array_push($recordEditableFieldsForms, $this->parseFieldHTMLWithRecordID($this->getFieldEditForm($editableFieldName)->FieldHolder(), $record->ID) ); + } + // Collect all output data. $return = array_merge($return, array( 'id' => $file->ID, @@ -204,15 +296,14 @@ class GridFieldBulkImageUpload_Request extends RequestHandler { //'buttons' => $file->UploadFieldFileButtons, 'record' => array( 'ID' => $record->ID, - 'fields' => $this->component->getRecordEditableFields() + 'fields' => $recordEditableFieldsForms ) )); + } } } - - array_push($this->createdRecords, $record->ID); - + $response = new SS_HTTPResponse(Convert::raw2json(array($return))); $response->addHeader('Content-Type', 'text/plain'); return $response; @@ -226,38 +317,25 @@ class GridFieldBulkImageUpload_Request extends RequestHandler { */ public function update(SS_HTTPRequest $request) { - $data = $request->requestVars(); - $recordID = false; - $recordFields = array(); - - foreach( $data as $key => $val) - { - if ( stripos($key, 'record_') !== false ) - { - if ( $key == 'record_ID' ) - { - $recordID = $val; - }else{ - $recordFields[str_ireplace('record_', '', $key)] = $val; - } - } - } + $data = $this->getParsedPostData($request->requestVars()); $recordClass = $this->gridField->list->dataClass; - $record = DataObject::get_by_id($recordClass, $recordID); + $record = DataObject::get_by_id($recordClass, $data['ID']); - foreach($recordFields as $field => $value) + foreach($data as $field => $value) { $record->setField($field, $value); } $record->write(); - return '{done:1,recordID:'.$recordID.'}'; + return '{done:1,recordID:'.$data['ID'].'}'; } /** - * + * Delete the Image Object and File as well as the DataObject + * according to the ID sent from the form + * * @param SS_HTTPRequest $request * @return String JSON */ @@ -268,8 +346,8 @@ class GridFieldBulkImageUpload_Request extends RequestHandler { $recordClass = $this->gridField->list->dataClass; $record = DataObject::get_by_id($recordClass, $data['ID']); - $imageField = $this->component->getRecordImageField(); + $imageField = $this->getRecordImageField(); $imageID = $record->$imageField; $image = DataObject::get_by_id('Image', $imageID); @@ -286,50 +364,40 @@ class GridFieldBulkImageUpload_Request extends RequestHandler { } /** - * + * Simple function taht replace the 'record_XX_' off of the ID field name + * prefix needed since it was taken for a pageID if sent as is as well as fixing other things + * * @param array $data * @return array */ - public function getParsedPostData(array $data) + function getParsedPostData(array $data) { $return = array(); - $fields = array(); foreach( $data as $key => $val) { - if ( stripos($key, 'record_') !== false ) - { - if ( $key == 'record_ID' ) - { - $return['ID'] = $val; - }else{ - $fields[str_ireplace('record_', '', $key)] = $val; - } - } + $return[ preg_replace( '/record_(\d+)_(\w+)/i', '$2', $key) ] = $val; } - $return['fields'] = $fields; - return $return; } /** - * Traverse up nested requests until we reach the first that's not a GridFieldBulkImageUpload_Request. - * The opposite of {@link Controller::curr()}, required because - * Controller::$controller_stack is not directly accessible. + * Add a unique prefix to sensitive HTML attributes (ID, FOR, NAME) + * Fixes rendering issue (i.e. dropdown fields) and IDs being mistaken for page IDs * - * @return Controller + * @param string $html + * @param string/int $id + * @return string */ - /* - protected function getToplevelController() { - $c = $this->controller; - while($c && $c instanceof GridFieldBulkImageUpload_Request) { - $c = $c->getController(); - } - return $c; + function parseFieldHTMLWithRecordID($html, $id) + { + $prefix = 'record_'.$id.'_'; + return str_ireplace ( array('id="', 'for="', 'name="'), + array('id="'.$prefix, 'for="'.$prefix, 'name="'.$prefix), + $html); } - */ - + /** * CMS-specific functionality: Passes through navigation breadcrumbs * to the template, and includes the currently edited record (if any). diff --git a/javascript/GridFieldBulkImageUpload.js b/javascript/GridFieldBulkImageUpload.js index d182add..c56b565 100644 --- a/javascript/GridFieldBulkImageUpload.js +++ b/javascript/GridFieldBulkImageUpload.js @@ -137,7 +137,7 @@ $(this).parents('li.ss-uploadfield-item').empty().remove(); - if ( $('li.ss-uploadfield-item').lenght == 0 ) { + if ( $('li.ss-uploadfield-item').length == 0 ) { $('.ss-uploadfield-editandorganize').css('display', 'none'); $('#Form_bulkImageUploadForm').removeClass('loading'); } diff --git a/javascript/GridFieldBulkImageUpload_downloadtemplate.js b/javascript/GridFieldBulkImageUpload_downloadtemplate.js index 55cf6a5..19dd3a8 100644 --- a/javascript/GridFieldBulkImageUpload_downloadtemplate.js +++ b/javascript/GridFieldBulkImageUpload_downloadtemplate.js @@ -23,18 +23,11 @@ window.tmpl.cache['GridFieldBulkImageUpload_downloadtemplate'] = tmpl( '{% if (!file.error) { %}' + '
'+ '
'+ - ''+ + ''+ ''+ - '{% for (var j=0; j' + - '' + - '
' + - '' + - '
' + - '
' + - + '{% for (var j=0; j'+