2007-07-19 12:40:28 +02:00
< ? php
/**
2009-10-11 02:07:13 +02:00
* A TinyMCE - powered WYSIWYG HTML editor field with image and link insertion and tracking capabilities . Editor fields
* are created from < textarea > tags , which are then converted with JavaScript .
*
2008-01-09 05:18:36 +01:00
* @ package forms
* @ subpackage fields - formattedinput
2007-07-19 12:40:28 +02:00
*/
class HtmlEditorField extends TextareaField {
2012-01-06 12:01:33 +01:00
/**
* @ var Boolean Use TinyMCE ' s GZIP compressor
*/
static $use_gzip = true ;
2012-02-10 12:15:21 +01:00
2012-03-12 16:03:13 +01:00
protected $rows = 30 ;
2009-06-15 07:17:48 +02:00
2009-05-18 02:19:47 +02:00
/**
2009-10-11 02:07:13 +02:00
* Includes the JavaScript neccesary for this field to work using the { @ link Requirements } system .
2009-05-18 02:19:47 +02:00
*/
2009-10-11 02:07:13 +02:00
public static function include_js () {
2012-01-06 12:01:33 +01:00
require_once 'tinymce/tiny_mce_gzip.php' ;
$configObj = HtmlEditorConfig :: get_active ();
if ( self :: $use_gzip ) {
$internalPlugins = array ();
foreach ( $configObj -> getPlugins () as $plugin => $path ) if ( ! $path ) $internalPlugins [] = $plugin ;
$tag = TinyMCE_Compressor :: renderTag ( array (
'url' => THIRDPARTY_DIR . '/tinymce/tiny_mce_gzip.php' ,
'plugins' => implode ( ',' , $internalPlugins ),
'themes' => 'advanced' ,
'languages' => $configObj -> getOption ( 'language' )
), true );
preg_match ( '/src="([^"]*)"/' , $tag , $matches );
Requirements :: javascript ( $matches [ 1 ]);
} else {
Requirements :: javascript ( MCE_ROOT . 'tiny_mce_src.js' );
}
Requirements :: customScript ( $configObj -> generateJS (), 'htmlEditorConfig' );
2009-05-18 02:19:47 +02:00
}
2009-10-11 02:07:13 +02:00
2007-07-19 12:40:28 +02:00
/**
2009-10-11 02:07:13 +02:00
* @ see TextareaField :: __construct ()
2007-07-19 12:40:28 +02:00
*/
2012-01-02 17:44:23 +01:00
public function __construct ( $name , $title = null , $value = '' ) {
if ( count ( func_get_args ()) > 3 ) Deprecation :: notice ( '3.0' , 'Use setRows() and setCols() instead of constructor arguments' );
parent :: __construct ( $name , $title , $value );
2009-10-11 02:07:13 +02:00
self :: include_js ();
2007-07-19 12:40:28 +02:00
}
/**
2009-10-11 02:07:13 +02:00
* @ return string
2007-07-19 12:40:28 +02:00
*/
2012-04-11 07:33:36 +02:00
function Field ( $properties = array ()) {
2009-10-11 02:07:27 +02:00
// mark up broken links
$value = new SS_HTMLValue ( $this -> value );
if ( $links = $value -> getElementsByTagName ( 'a' )) foreach ( $links as $link ) {
$matches = array ();
if ( preg_match ( '/\[sitetree_link id=([0-9]+)\]/i' , $link -> getAttribute ( 'href' ), $matches )) {
if ( ! DataObject :: get_by_id ( 'SiteTree' , $matches [ 1 ])) {
$class = $link -> getAttribute ( 'class' );
$link -> setAttribute ( 'class' , ( $class ? " $class ss-broken " : 'ss-broken' ));
}
}
2012-03-01 11:24:58 +01:00
if ( preg_match ( '/\[file_link id=([0-9]+)\]/i' , $link -> getAttribute ( 'href' ), $matches )) {
if ( ! DataObject :: get_by_id ( 'File' , $matches [ 1 ])) {
$class = $link -> getAttribute ( 'class' );
$link -> setAttribute ( 'class' , ( $class ? " $class ss-broken " : 'ss-broken' ));
}
}
2009-10-11 02:07:27 +02:00
}
2012-03-01 11:24:58 +01:00
2009-10-11 02:07:13 +02:00
return $this -> createTag (
'textarea' ,
2011-12-22 13:10:57 +01:00
$this -> getAttributes (),
2009-10-11 02:07:27 +02:00
htmlentities ( $value -> getContent (), ENT_COMPAT , 'UTF-8' )
2009-10-11 02:07:13 +02:00
);
2007-07-19 12:40:28 +02:00
}
2011-12-22 13:10:57 +01:00
function getAttributes () {
return array_merge (
parent :: getAttributes (),
array (
'tinymce' => 'true' ,
2012-03-12 16:03:13 +01:00
'style' => 'width: 97%; height: ' . ( $this -> rows * 16 ) . 'px' , // prevents horizontal scrollbars
2011-12-22 13:10:57 +01:00
'value' => null ,
)
);
}
2007-07-19 12:40:28 +02:00
2012-04-11 07:00:57 +02:00
public function saveInto ( DataObjectInterface $record ) {
2008-01-17 05:23:31 +01:00
if ( $record -> escapeTypeForField ( $this -> name ) != 'xml' ) {
2009-10-11 02:07:13 +02:00
throw new Exception (
'HtmlEditorField->saveInto(): This field should save into a HTMLText or HTMLVarchar field.'
2008-01-17 05:22:13 +01:00
);
}
2009-02-02 00:49:53 +01:00
$linkedPages = array ();
2009-10-11 02:07:13 +02:00
$linkedFiles = array ();
2007-07-19 12:40:28 +02:00
2009-10-11 02:07:27 +02:00
$htmlValue = new SS_HTMLValue ( $this -> value );
2009-10-11 02:07:13 +02:00
2011-03-23 02:32:38 +01:00
if ( class_exists ( 'SiteTree' )) {
// Populate link tracking for internal links & links to asset files.
if ( $links = $htmlValue -> getElementsByTagName ( 'a' )) foreach ( $links as $link ) {
$href = Director :: makeRelative ( $link -> getAttribute ( 'href' ));
if ( $href ) {
if ( preg_match ( '/\[sitetree_link id=([0-9]+)\]/i' , $href , $matches )) {
$ID = $matches [ 1 ];
// clear out any broken link classes
if ( $class = $link -> getAttribute ( 'class' )) {
$link -> setAttribute ( 'class' , preg_replace ( '/(^ss-broken|ss-broken$| ss-broken )/' , null , $class ));
}
$linkedPages [] = $ID ;
if ( ! DataObject :: get_by_id ( 'SiteTree' , $ID )) $record -> HasBrokenLink = true ;
2010-10-12 23:42:25 +02:00
2011-03-23 02:32:38 +01:00
} else if ( substr ( $href , 0 , strlen ( ASSETS_DIR ) + 1 ) == ASSETS_DIR . '/' ) {
$candidateFile = File :: find ( Convert :: raw2sql ( urldecode ( $href )));
if ( $candidateFile ) {
$linkedFiles [] = $candidateFile -> ID ;
} else {
$record -> HasBrokenFile = true ;
}
} else if ( $href == '' || $href [ 0 ] == '/' ) {
$record -> HasBrokenLink = true ;
2009-10-13 03:45:01 +02:00
}
2007-07-19 12:40:28 +02:00
}
}
}
2007-11-07 22:39:57 +01:00
2009-10-11 02:07:13 +02:00
// Resample images, add default attributes and add to assets tracking.
2009-10-11 02:07:27 +02:00
if ( $images = $htmlValue -> getElementsByTagName ( 'img' )) foreach ( $images as $img ) {
// strip any ?r=n data from the src attribute
$img -> setAttribute ( 'src' , preg_replace ( '/([^\?]*)\?r=[0-9]+$/i' , '$1' , $img -> getAttribute ( 'src' )));
2010-10-04 06:29:00 +02:00
if ( ! $image = File :: find ( $path = urldecode ( Director :: makeRelative ( $img -> getAttribute ( 'src' ))))) {
2009-10-11 02:07:13 +02:00
if ( substr ( $path , 0 , strlen ( ASSETS_DIR ) + 1 ) == ASSETS_DIR . '/' ) {
$record -> HasBrokenFile = true ;
2007-07-19 12:40:28 +02:00
}
2009-10-11 02:07:13 +02:00
continue ;
}
2007-07-19 12:40:28 +02:00
2009-10-11 02:07:13 +02:00
// Resample the images if the width & height have changed.
$width = $img -> getAttribute ( 'width' );
$height = $img -> getAttribute ( 'height' );
2010-04-12 04:45:35 +02:00
if ( $image ){
if ( $width && $height && ( $width != $image -> getWidth () || $height != $image -> getHeight ())) {
//Make sure that the resized image actually returns an image:
$resized = $image -> ResizedImage ( $width , $height );
2012-05-28 12:27:20 +02:00
if ( $resized ) $img -> setAttribute ( 'src' , $resized -> getRelativePath ());
2010-04-12 04:45:35 +02:00
}
2007-07-19 12:40:28 +02:00
}
2009-10-11 02:07:13 +02:00
// Add default empty title & alt attributes.
if ( ! $img -> getAttribute ( 'alt' )) $img -> setAttribute ( 'alt' , '' );
if ( ! $img -> getAttribute ( 'title' )) $img -> setAttribute ( 'title' , '' );
2010-04-12 04:45:35 +02:00
//If the src attribute is not set, then we won't add this to the list:
if ( $img -> getAttribute ( 'src' )){
// Add to the tracked files.
$linkedFiles [] = $image -> ID ;
}
2007-07-19 12:40:28 +02:00
}
2009-10-11 02:07:13 +02:00
// Save file & link tracking data.
2011-03-23 02:32:38 +01:00
if ( class_exists ( 'SiteTree' )) {
if ( $record -> ID && $record -> many_many ( 'LinkTracking' ) && $tracker = $record -> LinkTracking ()) {
2009-11-22 06:16:38 +01:00
$tracker -> removeByFilter ( sprintf ( '"FieldName" = \'%s\' AND "SiteTreeID" = %d' , $this -> name , $record -> ID ));
2009-11-26 23:18:59 +01:00
2011-03-23 02:32:38 +01:00
if ( $linkedPages ) foreach ( $linkedPages as $item ) {
$SQL_fieldName = Convert :: raw2sql ( $this -> name );
DB :: query ( " INSERT INTO \" SiteTree_LinkTracking \" ( \" SiteTreeID \" , \" ChildID \" , \" FieldName \" )
VALUES ( $record -> ID , $item , '$SQL_fieldName' ) " );
}
2007-07-19 12:40:28 +02:00
}
2009-11-22 06:16:38 +01:00
2011-03-23 02:32:38 +01:00
if ( $record -> ID && $record -> many_many ( 'ImageTracking' ) && $tracker = $record -> ImageTracking ()) {
2011-10-29 06:23:53 +02:00
$tracker -> where ( sprintf ( '"FieldName" = \'%s\' AND "SiteTreeID" = %d' , $this -> name , $record -> ID )) -> removeAll ();
2011-03-23 02:32:38 +01:00
$fieldName = $this -> name ;
if ( $linkedFiles ) foreach ( $linkedFiles as $item ) {
$tracker -> add ( $item , array ( 'FieldName' => $this -> name ));
}
2009-10-11 02:07:13 +02:00
}
2007-07-19 12:40:28 +02:00
}
2009-10-11 02:07:27 +02:00
$record -> { $this -> name } = $htmlValue -> getContent ();
2007-07-19 12:40:28 +02:00
}
2009-11-26 23:18:59 +01:00
2009-10-11 02:07:13 +02:00
/**
* @ return HtmlEditorField_Readonly
*/
public function performReadonlyTransformation () {
$field = new HtmlEditorField_Readonly ( $this -> name , $this -> title , $this -> value );
2007-07-19 12:40:28 +02:00
$field -> setForm ( $this -> form );
$field -> dontEscape = true ;
return $field ;
}
2009-10-11 02:07:13 +02:00
2012-01-02 16:19:22 +01:00
public function performDisabledTransformation () {
return $this -> performReadonlyTransformation ();
}
2007-07-19 12:40:28 +02:00
}
2008-01-10 01:34:18 +01:00
/**
* Readonly version of an { @ link HTMLEditorField } .
* @ package forms
* @ subpackage fields - formattedinput
*/
2009-10-11 02:07:13 +02:00
class HtmlEditorField_Readonly extends ReadonlyField {
2012-04-11 07:33:36 +02:00
function Field ( $properties = array ()) {
2007-07-19 12:40:28 +02:00
$valforInput = $this -> value ? Convert :: raw2att ( $this -> value ) : " " ;
2007-11-07 05:17:58 +01:00
return " <span class= \" readonly typography \" id= \" " . $this -> id () . " \" > " . ( $this -> value && $this -> value != '<p></p>' ? $this -> value : '<i>(not set)</i>' ) . " </span><input type= \" hidden \" name= \" " . $this -> name . " \" value= \" " . $valforInput . " \" /> " ;
2007-07-19 12:40:28 +02:00
}
function Type () {
2007-11-06 22:01:37 +01:00
return 'htmleditorfield readonly' ;
2007-07-19 12:40:28 +02:00
}
}
2008-01-10 01:34:18 +01:00
/**
2012-02-09 17:17:39 +01:00
* Toolbar shared by all instances of { @ link HTMLEditorField }, to avoid too much markup duplication .
* Needs to be inserted manually into the template in order to function - see { @ link LeftAndMain -> EditorToolbar ()} .
*
2008-01-10 01:34:18 +01:00
* @ package forms
* @ subpackage fields - formattedinput
*/
2008-10-30 23:03:21 +01:00
class HtmlEditorField_Toolbar extends RequestHandler {
2012-02-08 21:32:25 +01:00
static $allowed_actions = array (
'LinkForm' ,
'MediaForm' ,
2012-02-09 17:17:39 +01:00
'viewfile'
2012-02-08 21:32:25 +01:00
);
2012-02-09 17:17:39 +01:00
/**
* @ var string
*/
protected $templateViewFile = 'HtmlEditorField_viewfile' ;
2007-07-19 12:40:28 +02:00
protected $controller , $name ;
function __construct ( $controller , $name ) {
2008-11-05 02:59:27 +01:00
parent :: __construct ();
2012-02-08 21:32:25 +01:00
2012-03-24 04:38:57 +01:00
Requirements :: javascript ( FRAMEWORK_DIR . " /thirdparty/jquery/jquery.js " );
2012-02-08 21:32:25 +01:00
Requirements :: javascript ( THIRDPARTY_DIR . '/jquery-ui/jquery-ui.js' );
Requirements :: javascript ( THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js' );
2012-03-24 04:38:57 +01:00
Requirements :: javascript ( FRAMEWORK_ADMIN_DIR . '/javascript/ssui.core.js' );
Requirements :: javascript ( FRAMEWORK_DIR . " /javascript/HtmlEditorField.js " );
2012-02-08 21:32:25 +01:00
Requirements :: css ( THIRDPARTY_DIR . '/jquery-ui-themes/smoothness/jquery-ui.css' );
2008-11-05 02:59:27 +01:00
2007-07-19 12:40:28 +02:00
$this -> controller = $controller ;
$this -> name = $name ;
}
2010-04-13 01:34:08 +02:00
2012-04-12 22:28:00 +02:00
public function forTemplate () {
return sprintf (
'<div id="cms-editor-dialogs" data-url-linkform="%s" data-url-mediaform="%s"></div>' ,
Controller :: join_links ( $this -> controller -> Link ( $this -> name ), 'LinkForm' , 'forTemplate' ),
Controller :: join_links ( $this -> controller -> Link ( $this -> name ), 'MediaForm' , 'forTemplate' )
);
}
2010-04-13 01:34:08 +02:00
/**
* Searches the SiteTree for display in the dropdown
*
* @ return callback
*/
function siteTreeSearchCallback ( $sourceObject , $labelField , $search ) {
return DataObject :: get ( $sourceObject , " \" MenuTitle \" LIKE '% $search %' OR \" Title \" LIKE '% $search %' " );
}
2007-07-19 12:40:28 +02:00
/**
2008-11-04 05:12:54 +01:00
* Return a { @ link Form } instance allowing a user to
* add links in the TinyMCE content editor .
*
* @ return Form
2007-07-19 12:40:28 +02:00
*/
function LinkForm () {
2010-04-13 01:34:08 +02:00
$siteTree = new TreeDropdownField ( 'internal' , _t ( 'HtmlEditorField.PAGE' , " Page " ), 'SiteTree' , 'ID' , 'MenuTitle' , true );
// mimic the SiteTree::getMenuTitle(), which is bypassed when the search is performed
$siteTree -> setSearchFunction ( array ( $this , 'siteTreeSearchCallback' ));
2012-01-03 22:30:24 +01:00
$numericLabelTmpl = '<span class="step-label"><span class="flyout">%d</span><span class="arrow"></span><strong class="title">%s</strong></span>' ;
2007-07-19 12:40:28 +02:00
$form = new Form (
$this -> controller ,
2008-08-11 01:35:11 +02:00
" { $this -> name } /LinkForm " ,
2011-05-11 09:51:54 +02:00
new FieldList (
2009-11-21 03:22:44 +01:00
new LiteralField (
'Heading' ,
2012-04-17 05:43:53 +02:00
sprintf ( '<h3>%s</h3>' , _t ( 'HtmlEditorField.LINK' , 'Insert Link' ))
2007-07-19 12:40:28 +02:00
),
2009-11-21 03:22:44 +01:00
$contentComposite = new CompositeField (
new OptionsetField (
'LinkType' ,
2012-01-03 22:30:24 +01:00
sprintf ( $numericLabelTmpl , '1' , _t ( 'HtmlEditorField.LINKTO' , 'Link to' )),
2009-11-21 03:22:44 +01:00
array (
'internal' => _t ( 'HtmlEditorField.LINKINTERNAL' , 'Page on the site' ),
'external' => _t ( 'HtmlEditorField.LINKEXTERNAL' , 'Another website' ),
'anchor' => _t ( 'HtmlEditorField.LINKANCHOR' , 'Anchor on this page' ),
'email' => _t ( 'HtmlEditorField.LINKEMAIL' , 'Email address' ),
2012-05-09 07:11:59 +02:00
'file' => _t ( 'HtmlEditorField.LINKFILE' , 'Download a file' ),
),
'internal'
2009-11-21 03:22:44 +01:00
),
2012-01-03 22:30:24 +01:00
new LiteralField ( 'Step2' ,
'<div class="step2">' . sprintf ( $numericLabelTmpl , '2' , _t ( 'HtmlEditorField.DETAILS' , 'Details' )) . '</div>'
),
2010-04-13 01:34:08 +02:00
$siteTree ,
2009-11-21 03:22:44 +01:00
new TextField ( 'external' , _t ( 'HtmlEditorField.URL' , 'URL' ), 'http://' ),
new EmailField ( 'email' , _t ( 'HtmlEditorField.EMAIL' , 'Email address' )),
2012-03-01 09:13:42 +01:00
new TreeDropdownField ( 'file' , _t ( 'HtmlEditorField.FILE' , 'File' ), 'File' , 'ID' , 'Title' , true ),
2009-11-21 03:22:44 +01:00
new TextField ( 'Anchor' , _t ( 'HtmlEditorField.ANCHORVALUE' , 'Anchor' )),
new TextField ( 'Description' , _t ( 'HtmlEditorField.LINKDESCR' , 'Link description' )),
2010-10-15 05:25:51 +02:00
new CheckboxField ( 'TargetBlank' , _t ( 'HtmlEditorField.LINKOPENNEWWIN' , 'Open link in a new window?' )),
new HiddenField ( 'Locale' , null , $this -> controller -> Locale )
2009-11-21 03:22:44 +01:00
)
2007-07-19 12:40:28 +02:00
),
2011-05-11 09:51:54 +02:00
new FieldList (
2012-04-04 16:59:30 +02:00
ResetFormAction :: create ( 'remove' , _t ( 'HtmlEditorField.BUTTONREMOVELINK' , 'Remove link' ))
2012-02-17 00:35:10 +01:00
-> addExtraClass ( 'ss-ui-action-destructive' )
-> setUseButtonTag ( true )
,
FormAction :: create ( 'insert' , _t ( 'HtmlEditorField.BUTTONINSERTLINK' , 'Insert link' ))
-> addExtraClass ( 'ss-ui-action-constructive' )
-> setAttribute ( 'data-icon' , 'accept' )
-> setUseButtonTag ( true )
2007-07-19 12:40:28 +02:00
)
);
2008-11-04 05:12:54 +01:00
2009-11-21 03:22:44 +01:00
$contentComposite -> addExtraClass ( 'content' );
2009-11-21 03:31:11 +01:00
$form -> unsetValidator ();
2007-07-19 12:40:28 +02:00
$form -> loadDataFrom ( $this );
2012-01-03 17:38:11 +01:00
$form -> addExtraClass ( 'htmleditorfield-form htmleditorfield-linkform cms-dialog-content' );
2008-11-04 05:12:54 +01:00
2010-05-25 06:56:02 +02:00
$this -> extend ( 'updateLinkForm' , $form );
2007-07-19 12:40:28 +02:00
return $form ;
}
2008-11-04 05:12:54 +01:00
/**
* Return a { @ link Form } instance allowing a user to
2012-02-08 21:32:25 +01:00
* add images and flash objects to the TinyMCE content editor .
2008-11-04 05:12:54 +01:00
*
* @ return Form
*/
2012-02-08 21:32:25 +01:00
function MediaForm () {
// TODO Handle through GridState within field - currently this state set too late to be useful here (during request handling)
$parentID = $this -> controller -> getRequest () -> requestVar ( 'ParentID' );
$fileFieldConfig = GridFieldConfig :: create ();
$fileFieldConfig -> addComponent ( new GridFieldSortableHeader ());
2012-03-09 00:54:02 +01:00
$fileFieldConfig -> addComponent ( new GridFieldFilterHeader ());
2012-03-09 02:07:40 +01:00
$fileFieldConfig -> addComponent ( new GridFieldDataColumns ());
2012-02-09 17:17:39 +01:00
$fileFieldConfig -> addComponent ( new GridFieldPaginator ( 5 ));
$fileField = new GridField ( 'Files' , false , null , $fileFieldConfig );
2012-02-08 21:32:25 +01:00
$fileField -> setList ( $this -> getFiles ( $parentID ));
$fileField -> setAttribute ( 'data-selectable' , true );
$fileField -> setAttribute ( 'data-multiselect' , true );
2012-04-19 01:25:37 +02:00
$columns = $fileField -> getConfig () -> getComponentByType ( 'GridFieldDataColumns' );
$columns -> setDisplayFields ( array (
2012-02-09 17:17:39 +01:00
'CMSThumbnail' => false ,
'Name' => _t ( 'File.Name' ),
));
2011-03-23 03:38:31 +01:00
2012-02-08 21:32:25 +01:00
$numericLabelTmpl = '<span class="step-label"><span class="flyout">%d</span><span class="arrow"></span><strong class="title">%s</strong></span>' ;
2012-03-29 02:34:55 +02:00
$fromCMS = new CompositeField (
new LiteralField ( 'headerSelect' , '<h4 class="field header-select">' . sprintf ( $numericLabelTmpl , '1' , _t ( 'HtmlEditorField.Find' , 'Find' )) . '</h4>' ),
2012-02-09 17:17:39 +01:00
$selectComposite = new CompositeField (
new TreeDropdownField ( 'ParentID' , _t ( 'HtmlEditorField.FOLDER' , 'Folder' ), 'Folder' ),
$fileField
)
2012-03-29 02:34:55 +02:00
);
$fromCMS -> addExtraClass ( 'content' );
$selectComposite -> addExtraClass ( 'content-select' );
2012-05-22 06:45:36 +02:00
$fromWeb = new CompositeField (
new LiteralField ( 'headerURL' , '<h4 class="field header-url">' . sprintf ( $numericLabelTmpl , '1' , _t ( 'HtmlEditorField.ADDURL' , 'Add URL' )) . '</h4>' ),
$remoteURL = new TextField ( 'RemoteURL' , '' ),
2012-06-11 02:55:40 +02:00
new LiteralField ( 'addURLImage' , '<button class="action ui-action-constructive ui-button field add-url" data-icon="addMedia"></button>' )
2012-05-22 06:45:36 +02:00
);
$remoteURL -> addExtraClass ( 'remoteurl' );
2012-03-24 04:38:57 +01:00
Requirements :: css ( FRAMEWORK_DIR . '/css/AssetUploadField.css' );
2012-03-29 02:34:55 +02:00
$computerUploadField = Object :: create ( 'UploadField' , 'AssetUploadField' , '' );
$computerUploadField -> setConfig ( 'previewMaxWidth' , 40 );
$computerUploadField -> setConfig ( 'previewMaxHeight' , 30 );
$computerUploadField -> addExtraClass ( 'ss-assetuploadfield' );
$computerUploadField -> removeExtraClass ( 'ss-uploadfield' );
2012-03-30 02:44:39 +02:00
$computerUploadField -> setTemplate ( 'HtmlEditorField_UploadField' );
2012-03-29 02:34:55 +02:00
$computerUploadField -> setFolderName ( Upload :: $uploads_folder );
$tabSet = new TabSet (
2012-05-22 06:45:36 +02:00
" MediaFormInsertMediaTabs " ,
2012-03-29 02:34:55 +02:00
new Tab (
2012-03-29 04:09:20 +02:00
_t ( 'HtmlEditorField.FROMCOMPUTER' , 'From your computer' ),
2012-03-29 02:34:55 +02:00
$computerUploadField
),
2012-05-22 06:45:36 +02:00
new Tab (
_t ( 'HtmlEditorField.FROMWEB' , 'From the web' ),
$fromWeb
),
2012-03-29 02:34:55 +02:00
new Tab (
2012-03-29 04:09:20 +02:00
_t ( 'HtmlEditorField.FROMCMS' , 'From the CMS' ),
2012-03-29 02:34:55 +02:00
$fromCMS
)
);
$allFields = new CompositeField (
$tabSet ,
2012-05-22 08:18:31 +02:00
new LiteralField ( 'headerEdit' , '<h4 class="field header-edit">' . sprintf ( $numericLabelTmpl , '2' , _t ( 'HtmlEditorField.ADJUSTDETAILSDIMENSIONS' , 'Details & dimensions' )) . '</h4>' ),
2012-03-29 02:34:55 +02:00
$editComposite = new CompositeField (
2012-05-22 08:18:31 +02:00
new LiteralField ( 'contentEdit' , '<div class="content-edit ss-uploadfield-files files"></div>' )
2012-05-28 12:27:20 +02:00
)
2007-07-19 12:40:28 +02:00
);
2012-03-29 02:34:55 +02:00
2012-05-28 12:27:20 +02:00
$allFields -> addExtraClass ( 'ss-insert-media' );
2012-05-22 08:18:31 +02:00
$headings = new CompositeField (
2012-03-29 02:34:55 +02:00
new LiteralField (
'Heading' ,
2012-05-22 06:45:36 +02:00
sprintf ( '<h3 class="htmleditorfield-mediaform-heading insert">%s</h3>' , _t ( 'HtmlEditorField.INSERTMEDIA' , 'Insert Media' )) .
sprintf ( '<h3 class="htmleditorfield-mediaform-heading update">%s</h3>' , _t ( 'HtmlEditorField.UpdateMEDIA' , 'Update Media' ))
2012-05-28 12:27:20 +02:00
)
2012-05-22 08:18:31 +02:00
);
$headings -> addExtraClass ( 'cms-content-header' );
$editComposite -> addExtraClass ( 'ss-assetuploadfield' );
$fields = new FieldList (
$headings ,
2012-03-29 02:34:55 +02:00
$allFields
);
2008-11-04 05:12:54 +01:00
2011-05-11 09:51:54 +02:00
$actions = new FieldList (
2012-05-22 06:45:36 +02:00
FormAction :: create ( 'insertmedia' , _t ( 'HtmlEditorField.BUTTONINSERT' , 'Insert' ))
-> addExtraClass ( 'ss-ui-action-constructive media-insert' )
2012-04-20 06:11:15 +02:00
-> setAttribute ( 'data-icon' , 'accept' )
-> setUseButtonTag ( true ),
2012-05-22 06:45:36 +02:00
FormAction :: create ( 'insertmedia' , _t ( 'HtmlEditorField.BUTTONUpdate' , 'Update' ))
-> addExtraClass ( 'ss-ui-action-constructive media-update' )
2012-02-17 00:35:10 +01:00
-> setAttribute ( 'data-icon' , 'accept' )
-> setUseButtonTag ( true )
2010-05-25 06:56:02 +02:00
);
2012-01-03 09:38:33 +01:00
2010-05-25 06:56:02 +02:00
$form = new Form (
$this -> controller ,
2012-02-08 21:32:25 +01:00
" { $this -> name } /MediaForm " ,
2010-05-25 06:56:02 +02:00
$fields ,
$actions
);
2012-03-29 02:34:55 +02:00
2009-11-21 03:31:11 +01:00
$form -> unsetValidator ();
2009-06-28 03:17:20 +02:00
$form -> disableSecurityToken ();
2007-07-19 12:40:28 +02:00
$form -> loadDataFrom ( $this );
2012-02-08 21:32:25 +01:00
$form -> addExtraClass ( 'htmleditorfield-form htmleditorfield-mediaform cms-dialog-content' );
2012-02-09 17:17:39 +01:00
// TODO Re-enable once we remove $.metadata dependency which currently breaks the JS due to $.ui.widget
// $form->setAttribute('data-urlViewfile', $this->controller->Link($this->name));
// Allow other people to extend the fields being added to the imageform
$this -> extend ( 'updateMediaForm' , $form );
2008-11-04 05:12:54 +01:00
2007-07-19 12:40:28 +02:00
return $form ;
}
2012-02-09 17:17:39 +01:00
/**
* View of a single file , either on the filesystem or on the web .
*/
public function viewfile ( $request ) {
2012-06-08 06:42:14 +02:00
2012-02-09 17:17:39 +01:00
// TODO Would be cleaner to consistently pass URL for both local and remote files,
// but GridField doesn't allow for this kind of metadata customization at the moment.
if ( $url = $request -> getVar ( 'FileURL' )) {
2012-03-12 16:31:32 +01:00
if ( Director :: is_absolute_url ( $url ) && ! Director :: is_site_url ( $url )) {
2012-02-09 17:17:39 +01:00
$url = $url ;
2012-03-12 16:31:32 +01:00
$file = new File ( array (
'Title' => basename ( $url ),
'Filename' => $url
));
2012-02-09 17:17:39 +01:00
} else {
$url = Director :: makeRelative ( $request -> getVar ( 'FileURL' ));
2012-03-12 16:31:32 +01:00
$url = preg_replace ( '/_resampled\/[^-]+-/' , '' , $url );
2012-05-28 11:13:42 +02:00
$file = File :: get () -> filter ( 'Filename' , $url ) -> first ();
2012-03-12 16:31:32 +01:00
if ( ! $file ) $file = new File ( array (
'Title' => basename ( $url ),
'Filename' => $url
));
2012-02-09 17:17:39 +01:00
}
} elseif ( $id = $request -> getVar ( 'ID' )) {
$file = DataObject :: get_by_id ( 'File' , $id );
$url = $file -> RelativeLink ();
} else {
throw new LogicException ( 'Need either "ID" or "FileURL" parameter to identify the file' );
}
// Instanciate file wrapper and get fields based on its type
if ( $file && $file -> appCategory () == 'image' ) {
$fileWrapper = new HtmlEditorField_Image ( $url , $file );
2012-05-22 06:45:36 +02:00
} elseif ( ! Director :: is_site_url ( $url )) {
$fileWrapper = new HtmlEditorField_Embed ( $url , $file );
2012-02-09 17:17:39 +01:00
} else {
$fileWrapper = new HtmlEditorField_File ( $url , $file );
}
2012-03-12 16:31:32 +01:00
2012-02-09 17:17:39 +01:00
$fields = $this -> getFieldsForFile ( $url , $fileWrapper );
$this -> extend ( 'updateFieldsForFile' , $fields , $url , $fileWrapper );
return $fileWrapper -> customise ( array (
'Fields' => $fields ,
)) -> renderWith ( $this -> templateViewFile );
}
/**
* Similar to { @ link File -> getCMSFields ()}, but only returns fields
* for manipulating the instance of the file as inserted into the HTML content ,
* not the " master record " in the database - hence there ' s no form or saving logic .
*
* @ param String Relative or absolute URL to file
* @ return FieldList
*/
protected function getFieldsForFile ( $url , $file ) {
$fields = $this -> extend ( 'getFieldsForFile' , $url , $file );
if ( ! $fields ) {
2012-05-22 06:45:36 +02:00
if ( $file instanceof HtmlEditorField_Embed ) {
$fields = $this -> getFieldsForOembed ( $url , $file );
} elseif ( $file -> Extension == 'swf' ) {
2012-02-09 17:17:39 +01:00
$fields = $this -> getFieldsForFlash ( $url , $file );
} else {
$fields = $this -> getFieldsForImage ( $url , $file );
}
$fields -> push ( new HiddenField ( 'URL' , false , $url ));
}
$this -> extend ( 'updateFieldsForFile' , $fields , $url , $file );
2011-03-23 03:38:31 +01:00
2012-02-09 17:17:39 +01:00
return $fields ;
}
2012-05-22 06:45:36 +02:00
/**
* @ return FieldList
*/
protected function getFieldsForOembed ( $url , $file ) {
if ( isset ( $file -> Oembed -> thumbnail_url )) {
$thumbnailURL = $file -> Oembed -> thumbnail_url ;
} elseif ( $file -> Type == 'photo' ) {
$thumbnailURL = $file -> Oembed -> url ;
} else {
2012-05-24 10:05:51 +02:00
$thumbnailURL = FRAMEWORK_DIR . '/images/default_media.png' ;
2012-05-22 06:45:36 +02:00
}
$previewField = new LiteralField ( " ImageFull " ,
" <img id='thumbnailImage' class='thumbnail-preview' src=' { $thumbnailURL } ?r= " . rand ( 1 , 100000 ) . " ' alt=' { $file -> Name } ' /> \n "
);
2012-06-08 06:42:14 +02:00
if ( $file -> Width != null ){
$dimensionsField = new FieldGroup ( _t ( 'HtmlEditorField.IMAGEDIMENSIONS' , 'Dimensions' ),
$widthField = new TextField ( 'Width' , _t ( 'HtmlEditorField.IMAGEWIDTHPX' , 'Width' ), $file -> Width ),
2012-06-08 17:04:40 +02:00
$heightField = new TextField ( 'Height' , _t ( 'HtmlEditorField.IMAGEHEIGHTPX' , 'Height' ), $file -> Height )
2012-06-08 06:42:14 +02:00
);
}
2012-05-22 06:45:36 +02:00
$fields = new FieldList (
$filePreview = CompositeField :: create (
CompositeField :: create (
$previewField
) -> setName ( " FilePreviewImage " ) -> addExtraClass ( 'cms-file-info-preview' ),
CompositeField :: create (
CompositeField :: create (
new ReadonlyField ( " FileType " , _t ( 'AssetTableField.TYPE' , 'File type' ) . ':' , $file -> Type ),
$urlField = new ReadonlyField ( 'ClickableURL' , _t ( 'AssetTableField.URL' , 'URL' ),
2012-06-08 06:42:14 +02:00
sprintf ( '<a href="%s" target="_blank" class="file">%s</a>' , $url , $url )
2012-05-22 06:45:36 +02:00
)
)
) -> setName ( " FilePreviewData " ) -> addExtraClass ( 'cms-file-info-data' )
) -> setName ( " FilePreview " ) -> addExtraClass ( 'cms-file-info' ),
new TextField ( 'CaptionText' , _t ( 'HtmlEditorField.CAPTIONTEXT' , 'Caption text' )),
2012-06-08 06:42:14 +02:00
$alignment = new DropdownField (
2012-05-22 06:45:36 +02:00
'CSSClass' ,
_t ( 'HtmlEditorField.CSSCLASS' , 'Alignment / style' ),
array (
'left' => _t ( 'HtmlEditorField.CSSCLASSLEFT' , 'On the left, with text wrapping around.' ),
'leftAlone' => _t ( 'HtmlEditorField.CSSCLASSLEFTALONE' , 'On the left, on its own.' ),
'right' => _t ( 'HtmlEditorField.CSSCLASSRIGHT' , 'On the right, with text wrapping around.' ),
'center' => _t ( 'HtmlEditorField.CSSCLASSCENTER' , 'Centered, on its own.' ),
)
),
2012-06-08 06:42:14 +02:00
$dimensionsField
2012-05-22 06:45:36 +02:00
);
2012-06-08 06:42:14 +02:00
$urlField -> addExtraClass ( 'text-wrap' );
2012-05-22 06:45:36 +02:00
$urlField -> dontEscape = true ;
2012-06-08 06:42:14 +02:00
if ( $dimensionsField ){
$dimensionsField -> addExtraClass ( 'dimensions last' );
$widthField -> setMaxLength ( 5 );
$heightField -> setMaxLength ( 5 );
} else {
$alignment -> addExtraClass ( 'last' );
}
2012-05-22 06:45:36 +02:00
if ( $file -> Type == 'photo' ) {
$filePreview -> FieldList () -> insertBefore ( new TextField (
'AltText' ,
_t ( 'HtmlEditorField.IMAGEALTTEXT' , 'Alternative text (alt) - shown if image cannot be displayed' ),
$file -> Title ,
80
), 'CaptionText' );
$filePreview -> FieldList () -> insertBefore ( new TextField (
'Title' ,
_t ( 'HtmlEditorField.IMAGETITLE' , 'Title text (tooltip) - for additional information about the image' )
), 'CaptionText' );
}
$this -> extend ( 'updateFieldsForImage' , $fields , $url , $file );
return $fields ;
}
2012-02-09 17:17:39 +01:00
/**
* @ return FieldList
*/
protected function getFieldsForFlash ( $url , $file ) {
$fields = new FieldList (
$dimensionsField = new FieldGroup ( _t ( 'HtmlEditorField.IMAGEDIMENSIONS' , 'Dimensions' ),
$widthField = new TextField ( 'Width' , _t ( 'HtmlEditorField.IMAGEWIDTHPX' , 'Width' ), $file -> Width ),
$heightField = new TextField ( 'Height' , " x " . _t ( 'HtmlEditorField.IMAGEHEIGHTPX' , 'Height' ), $file -> Height )
)
);
$dimensionsField -> addExtraClass ( 'dimensions' );
$widthField -> setMaxLength ( 5 );
$heightField -> setMaxLength ( 5 );
$this -> extend ( 'updateFieldsForFlash' , $fields , $url , $file );
return $fields ;
}
/**
* @ return FieldList
*/
protected function getFieldsForImage ( $url , $file ) {
2012-05-22 06:45:36 +02:00
if ( $file -> File instanceof Image ) {
$formattedImage = $file -> File -> generateFormattedImage ( 'SetWidth' , Image :: $asset_preview_width );
2012-03-12 16:31:32 +01:00
$thumbnailURL = $formattedImage ? $formattedImage -> URL : $url ;
} else {
$thumbnailURL = $url ;
}
2012-02-28 18:07:55 +01:00
$previewField = new LiteralField ( " ImageFull " ,
2012-03-12 16:31:32 +01:00
" <img id='thumbnailImage' class='thumbnail-preview' src=' { $thumbnailURL } ?r= " . rand ( 1 , 100000 ) . " ' alt=' { $file -> Name } ' /> \n "
2012-02-28 18:07:55 +01:00
);
2012-06-08 06:42:14 +02:00
if ( $file -> Width != null ){
$dimensionsField = new FieldGroup ( _t ( 'HtmlEditorField.IMAGEDIMENSIONS' , 'Dimensions' ),
$widthField = new TextField ( 'Width' , _t ( 'HtmlEditorField.IMAGEWIDTHPX' , 'Width' ), $file -> Width ),
$heightField = new TextField ( 'Height' , " x " . _t ( 'HtmlEditorField.IMAGEHEIGHTPX' , 'Height' ), $file -> Height )
);
}
2012-02-09 17:17:39 +01:00
$fields = new FieldList (
2012-04-09 21:35:07 +02:00
$filePreview = CompositeField :: create (
CompositeField :: create (
2012-02-28 18:07:55 +01:00
$previewField
) -> setName ( " FilePreviewImage " ) -> addExtraClass ( 'cms-file-info-preview' ),
2012-04-09 21:35:07 +02:00
CompositeField :: create (
CompositeField :: create (
2012-02-28 18:07:55 +01:00
new ReadonlyField ( " FileType " , _t ( 'AssetTableField.TYPE' , 'File type' ) . ':' , $file -> FileType ),
new ReadonlyField ( " Size " , _t ( 'AssetTableField.SIZE' , 'File size' ) . ':' , $file -> getSize ()),
2012-06-08 06:42:14 +02:00
$urlField = new ReadonlyField ( 'ClickableURL' , _t ( 'AssetTableField.URL' , 'URL' ),
sprintf ( '<a href="%s" target="_blank" class="file-url">%s</a>' , $file -> Link (), $file -> RelativeLink ())
2012-02-28 18:07:55 +01:00
),
new DateField_Disabled ( " Created " , _t ( 'AssetTableField.CREATED' , 'First uploaded' ) . ':' , $file -> Created ),
new DateField_Disabled ( " LastEdited " , _t ( 'AssetTableField.LASTEDIT' , 'Last changed' ) . ':' , $file -> LastEdited )
)
) -> setName ( " FilePreviewData " ) -> addExtraClass ( 'cms-file-info-data' )
2012-06-08 06:42:14 +02:00
) -> setName ( " FilePreview " ) -> addExtraClass ( 'cms-file-info' ),
CompositeField :: create (
new TextField (
'AltText' ,
_t ( 'HtmlEditorField.IMAGEALT' , 'Alternative text (alt)' ),
$file -> Title ,
80
),
new LiteralField ( 'extraAlt' , '<div class="middleColumn extraLabel">' . _t ( 'HtmlEditorField.IMAGEALTTEXTDESC' , 'Shown to screen readers or if image can not be displayed' ) . '</div>' )
) -> addExtraClass ( 'img-detail-group first' ),
CompositeField :: create (
new TextField (
'Title' ,
_t ( 'HtmlEditorField.IMAGETITLETEXT' , 'Title text (tooltip)' )
),
new LiteralField ( 'extraTitle' , '<div class="middleColumn extraLabel">' . _t ( 'HtmlEditorField.IMAGETITLETEXTDESC' , 'For additional information about the image' ) . '</div>' )
) -> addExtraClass ( 'img-detail-group' ),
2012-02-09 17:17:39 +01:00
new TextField ( 'CaptionText' , _t ( 'HtmlEditorField.CAPTIONTEXT' , 'Caption text' )),
2012-06-08 06:42:14 +02:00
$alignment = new DropdownField (
2012-02-09 17:17:39 +01:00
'CSSClass' ,
_t ( 'HtmlEditorField.CSSCLASS' , 'Alignment / style' ),
array (
'left' => _t ( 'HtmlEditorField.CSSCLASSLEFT' , 'On the left, with text wrapping around.' ),
'leftAlone' => _t ( 'HtmlEditorField.CSSCLASSLEFTALONE' , 'On the left, on its own.' ),
'right' => _t ( 'HtmlEditorField.CSSCLASSRIGHT' , 'On the right, with text wrapping around.' ),
'center' => _t ( 'HtmlEditorField.CSSCLASSCENTER' , 'Centered, on its own.' ),
)
),
2012-06-08 06:42:14 +02:00
$dimensionsField
2012-02-09 17:17:39 +01:00
);
2012-02-28 18:07:55 +01:00
$urlField -> dontEscape = true ;
2012-06-08 06:42:14 +02:00
if ( $dimensionsField ){
$dimensionsField -> addExtraClass ( 'dimensions last' );
$widthField -> setMaxLength ( 5 );
$heightField -> setMaxLength ( 5 );
} else {
$alignment -> addExtraClass ( 'last' );
}
2012-02-09 17:17:39 +01:00
$this -> extend ( 'updateFieldsForImage' , $fields , $url , $file );
return $fields ;
2012-02-08 21:32:25 +01:00
}
/**
* @ param Int
* @ return DataList
*/
protected function getFiles ( $parentID = null ) {
// TODO Use array('Filename:EndsWith' => $exts) once that's supported
2012-02-09 17:17:39 +01:00
$exts = $this -> getAllowedExtensions ();
2012-02-08 21:32:25 +01:00
$wheres = array ();
foreach ( $exts as $ext ) $wheres [] = '"Filename" LIKE \'%.' . $ext . '\'' ;
2012-05-28 11:13:42 +02:00
$files = File :: get () -> where ( implode ( ' OR ' , $wheres ));
2009-11-21 03:31:11 +01:00
2012-02-08 21:32:25 +01:00
// Limit by folder (if required)
if ( $parentID ) $files -> filter ( 'ParentID' , $parentID );
2010-05-25 06:56:02 +02:00
2012-02-08 21:32:25 +01:00
return $files ;
2007-07-19 12:40:28 +02:00
}
2012-02-09 17:17:39 +01:00
/**
* @ return Array All extensions which can be handled by the different views .
*/
protected function getAllowedExtensions () {
$exts = array ( 'jpg' , 'gif' , 'png' , 'swf' );
$this -> extend ( 'updateAllowedExtensions' , $exts );
return $exts ;
}
2012-04-12 22:28:00 +02:00
2012-02-09 17:17:39 +01:00
}
/**
* Encapsulation of a file which can either be a remote URL
* or a { @ link File } on the local filesystem , exhibiting common properties
* such as file name or the URL .
*
* @ todo Remove once core has support for remote files
*/
class HtmlEditorField_File extends ViewableData {
/** @var String */
protected $url ;
/** @var File */
protected $file ;
/**
* @ param String
* @ param File
*/
function __construct ( $url , $file = null ) {
$this -> url = $url ;
$this -> file = $file ;
2012-02-28 18:07:55 +01:00
$this -> failover = $file ;
2012-02-09 17:17:39 +01:00
parent :: __construct ();
}
/**
* @ return File Might not be set ( for remote files )
*/
function getFile () {
return $this -> file ;
}
function getURL () {
return $this -> url ;
}
function getName () {
return ( $this -> file ) ? $this -> file -> Name : preg_replace ( '/\?.*/' , '' , basename ( $this -> url ));
}
/**
* @ return String HTML
*/
function getPreview () {
$preview = $this -> extend ( 'getPreview' );
if ( $preview ) return $preview ;
if ( $this -> file ) {
return $this -> file -> CMSThumbnail ();
} else {
// Hack to use the framework's built-in thumbnail support without creating a local file representation
$tmpFile = new File ( array ( 'Name' => $this -> Name , 'Filename' => $this -> Name ));
return $tmpFile -> CMSThumbnail ();
}
}
function getExtension () {
return strtolower (( $this -> file ) ? $this -> file -> Extension : pathinfo ( $this -> Name , PATHINFO_EXTENSION ));
}
function appCategory () {
if ( $this -> file ) {
return $this -> file -> appCategory ();
} else {
// Hack to use the framework's built-in thumbnail support without creating a local file representation
$tmpFile = new File ( array ( 'Name' => $this -> Name , 'Filename' => $this -> Name ));
return $tmpFile -> appCategory ();
}
}
}
2012-05-22 06:45:36 +02:00
class HtmlEditorField_Embed extends HtmlEditorField_File {
protected $oembed ;
public function __construct ( $url , $file = null ) {
parent :: __construct ( $url , $file );
$this -> oembed = Oembed :: get_oembed_from_url ( $url );
if ( ! $this -> oembed ) {
2012-05-24 04:28:47 +02:00
$controller = Controller :: curr ();
$controller -> response -> addHeader ( 'X-Status' ,
rawurlencode ( _t (
'HtmlEditorField.URLNOTANOEMBEDRESOURCE' ,
" The URL ' { url}' could not be turned into a media resource. " ,
" The URL that has been passed is not a valid Oembed resource, and the embed element could not be created. " ,
array ( 'url' => $url )
)));
$controller -> response -> setStatusCode ( 404 );
throw new SS_HTTPResponse_Exception ( $controller -> response );
2012-05-22 06:45:36 +02:00
}
}
public function getWidth () {
2012-05-24 08:16:00 +02:00
return $this -> oembed -> Width ? : 100 ;
2012-05-22 06:45:36 +02:00
}
public function getHeight () {
2012-05-24 08:16:00 +02:00
return $this -> oembed -> Height ? : 100 ;
2012-05-22 06:45:36 +02:00
}
public function getPreview () {
if ( isset ( $this -> oembed -> thumbnail_url )) {
return sprintf ( '<img src="%s" />' , $this -> oembed -> thumbnail_url );
}
}
public function getName () {
if ( isset ( $this -> oembed -> title )) {
return $this -> oembed -> title ;
} else {
return parent :: getName ();
}
}
public function getType () {
return $this -> oembed -> type ;
}
public function getOembed () {
return $this -> oembed ;
}
public function appCategory () {
return 'embed' ;
}
}
2012-02-09 17:17:39 +01:00
class HtmlEditorField_Image extends HtmlEditorField_File {
protected $width ;
protected $height ;
function __construct ( $url , $file = null ) {
parent :: __construct ( $url , $file );
// Get dimensions for remote file
$info = @ getimagesize ( $url );
if ( $info ) {
$this -> width = $info [ 0 ];
$this -> height = $info [ 1 ];
}
}
function getWidth () {
return ( $this -> file ) ? $this -> file -> Width : $this -> width ;
}
function getHeight () {
return ( $this -> file ) ? $this -> file -> Height : $this -> height ;
}
function getPreview () {
return ( $this -> file ) ? $this -> file -> CMSThumbnail () : sprintf ( '<img src="%s" />' , $this -> url );
}
2012-03-01 09:13:42 +01:00
}