Adding a TinyMCE image browser to CakePHP 2.+
This is just and update to Adding a TinyMCE image browser the CakePHP way as applicable to the 2.+ versions of Cake. Nothing major, just following with the api changes to make this work smoothly.
Here is the updated Model code:
<?php
App::uses('Folder', 'Utility');
App::uses('File', 'Utility');
class Imageupload extends AppModel {
var $name = 'Imageupload';
var $validate = array(
'imageupload' => array(
'rule' => array(
'validFile',
array(
'required' => true,
'extensions' => array(
'jpg',
'jpeg',
'gif',
'png'
)
)
)
)
);
var $useTable = false;
function readFolder($folderName = null) {
$folder = new Folder($folderName);
$images = $folder->read(
true,
array(
'.',
'..',
'Thumbs.db'
),
true
);
$images = $images[1]; // We are only interested in files
// Get more infos about the images
$retVal = array();
foreach ($images as $the_image)
{
$the_image = new File($the_image);
$retVal[] = array_merge(
$the_image->info(),
array(
'size' => $the_image->size(),
'last_changed' => $the_image->lastChange()
)
);
}
return $retVal;
}
function upload($data = null) {
$this->set($data);
if(empty($this->data)) {
return false;
}
// Validation
if(!$this->validates()) {
return false;
}
//print_r($this->data);
// Move the file to the uploads folder
if(!move_uploaded_file($this->data['Imageupload']['Image']['image']['tmp_name'], WWW_ROOT.DS.'uploads'.DS.$this->data['Imageupload']['Image']['image']['name'])) {
return false;
}
return true;
}
function validFile($check, $settings) {
$_default = array(
'required' => false,
'extensions' => array(
'jpg',
'jpeg',
'gif',
'png'
)
);
$_settings = array_merge(
$_default,
ife(
is_array($settings),
$settings,
array()
)
);
// Remove first level of Array
$_check = array_shift($check);
if($_settings['required'] == false && $_check['size'] == 0) {
return true;
}
// No file uploaded.
if($_settings['required'] && $_check['size'] == 0) {
return false;
}
// Check for Basic PHP file errors.
if($_check['error'] !== 0) {
return false;
}
// Use PHPs own file validation method.
if(is_uploaded_file($_check['tmp_name']) == false) {
return false;
}
// Valid extension
return Validation::extension(
$_check,
$_settings['extensions']
);
}
}
?>
You'll notice a couple of small changes, mainly addin the App:uses functionality before the class declaration, and also i renamed it to Imageuploads, as Images redirected to the webroot/images folders.
And here is the updated Controller code
<?php
class ImageuploadsController extends AppController {
var $name = 'Imageuploads';
var $uses = array('Imageupload');
var $helpers = array(
'Html',
'Form',
'Js',
'Number' // Used to show readable filesizes
);
function admin_index() {
$this->layout = 'admin';
$this->set(
'images',
$this->Imageupload->readFolder(WWW_ROOT.DS.'uploads')
);
}
function admin_upload() {
// Upload an image
if (!empty($this->data)) {
// Validate and move the file
if($this->Imageupload->upload($this->data)) {
$this->Session->setFlash('The image was successfully uploaded.');
} else {
$this->Session->setFlash('There was an error with the uploaded file.');
}
$this->redirect(
array(
'action' => 'index'
)
);
} else {
$this->redirect(
array(
'action' => 'index'
)
);
}
}
}
?>
<p>I added the admin_ part because this functionality is behind an auth system and I wanted consistent URI's but that is up to to you.</p>
<p>Here is the tinymce.ctp code</p>
<?php echo $this->Html->script("tiny_mce/tiny_mce.js"); ?>
<?php
echo $this->Html->scriptBlock(
"function fileBrowserCallBack(field_name, url, type, win) {
browserField = field_name;
browserWin = win;
window.open('".Helper::url(array('controller' => 'imageuploads'))."', 'browserWindow', 'modal,width=600,height=400,scrollbars=yes');
}"
);
?>
<?php
echo $this->Html->scriptBlock(
"tinyMCE.init({
mode : 'textareas',
theme : 'advanced',
theme_advanced_buttons1 : 'forecolor, bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,|,undo,redo,|,link,unlink,|,image,emotions,code',
theme_advanced_buttons2 : '',
theme_advanced_buttons3 : '',
theme_advanced_toolbar_location : 'top',
theme_advanced_toolbar_align : 'left',
theme_advanced_path_location : 'bottom',
extended_valid_elements : 'a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]',
file_browser_callback: 'fileBrowserCallBack',
width: '620',
height: '480',
relative_urls : false
});"
);
?>
And lastly the the index (or admin_index in my case) view located in View/imageuploads/
<?php
echo $this->Html->scriptBlock(
"function selectURL(url) {
if (url == '') return false;
url = '".Helper::url('/uploads/')."' + url;
field = window.top.opener.browserWin.document.forms[0].elements[window.top.opener.browserField];
field.value = url;
if (field.onchange != null) field.onchange();
window.top.close();
window.top.opener.browserWin.focus();
}"
);
?>
<?php
echo $this->Form->create(
null,
array(
'type' => 'file',
'url' => array(
'action' => 'upload'
)
)
);
echo $this->Form->label(
'Image.image',
'Upload image'
);
echo $this->Form->file(
'Image.image'
);
echo $this->Form->end('Upload');
?>
<?php if(isset($images[0])) {
$tableCells = array();
foreach($images As $the_image) {
$tableCells[] = array(
$this->Html->link(
$the_image['basename'],
'#',
array(
'onclick' => 'selectURL("'.$the_image['basename'].'");'
)
),
$this->Number->toReadableSize($the_image['size']),
date('m/d/Y H:i', $the_image['last_changed'])
);
}
echo $this->Html->tag(
'table',
$this->Html->tableHeaders(
array(
'File name',
'Size',
'Date created'
)
).$this->Html->tableCells(
$tableCells
)
);
} ?>
You'll notice a few small differences, like $this->Html->scriptBlock
Finally just make sure you add
Element('tinymce'); ?>
to the form you want to add this to.
Cheers!







