= USERLEVEL_ADMIN) {
return false;
}
// do we already have it?
if (!$this->forceZipInstall && is_dir($this->cke_dir) && is_file($this->cke_dir . '/ckeditor.js')) {
// this is running while getting a new Plugin version
if ($this->checkUpdate()) {
$this->set_config('installer', '4-'.date('Ymd-H:i:s')); // this is a faked debug notice, since falldown is extract true with case 0, 1 or 2
} else {
$this->set_config('installer', '3-'.date('Ymd-H:i:s')); // this will happen, if no further extract is necessary in case of an update
return;
}
}
if (!extension_loaded('zip')) {
trigger_error(' ZIP extension has not been compiled or loaded in php.', E_USER_WARNING);
return;
}
if (is_writable($this->cke_path)) {
$zip = new ZipArchive;
if ($zip->open($this->cke_path . '/' . $this->cke_zipfile) === true) {
$zip->extractTo($this->cke_path);
$zip->close();
$this->set_config('installer', '2-'.date('Ymd-H:i:s')); // returned by string[0], which is better than substr in this case
// Check to remove every old ckeditor_(*)_standard-plus.zip files
foreach (glob($this->cke_path . '/*.zip') as $filename) {
if($this->cke_path . '/' . $this->cke_zipfile != $filename) {
@unlink($filename);
$is_update = true;
}
}
if ($is_update) {
// purge removed files for upgraders to ckeditor v. 4.2 only
@unlink($this->cke_path . '/ckeditor/build_config.js');
@unlink($this->cke_path . '/ckeditor/skins/moono/images/mini.png');
}
} else {
$this->set_config('installer', '1-'.date('Ymd-H:i:s'));
return false;
}
} else {
$this->set_config('installer', '0-'.date('Ymd-H:i:s')); // do it again, Sam
return false;
}
// make sure the new versions are set to last_ckeditor_version and last_kcfinder_version
$this->updateTableZip();
return true;
}
function uninstall(&$propbag) {
// todo? uninstall old instances which may be in there, caused by a duplicating bug using installer fallback without right instance in 2.3.2 for one day online
}
function introspect(&$propbag)
{
global $serendipity;
$propbag->add('name', PLUGIN_EVENT_CKEDITOR_NAME);
$propbag->add('description', PLUGIN_EVENT_CKEDITOR_DESC);
$propbag->add('stackable', false);
$propbag->add('author', 'Rustam Abdullaev, Ian');
$propbag->add('version', '3.2.1'); // is CKEDITOR Series 4 (hidden) - revision .3.2 - and appended plugin revision .1
$propbag->add('copyright', 'GPL or LGPL License');
$propbag->add('requirements', array(
'serendipity' => '1.7',
'smarty' => '3.1.13',
'php' => '5.2.6'
));
$propbag->add('event_hooks', array(
'frontend_footer' => true,
'backend_header' => true,
'css_backend' => true,
'external_plugin' => true,
'backend_plugins_update' => true,
'backend_media_path_exclude_directories' => true,
'backend_wysiwyg' => true,
'backend_wysiwyg_finish' => true
));
$propbag->add('configuration', array('path', 'plugpath', 'codebutton', 'prettify', 'kcfinder', 'acf_off', 'toolbar_break', 'force_install'));
$propbag->add('groups', array('BACKEND_EDITOR'));
}
function introspect_config_item($name, &$propbag)
{
global $serendipity;
switch($name) {
case 'path':
$propbag->add('type', 'string');
$propbag->add('name', INSTALL_RELPATH);
$propbag->add('description', PLUGIN_EVENT_CKEDITOR_OPTION_BLAHBLAH . '"plugins/serendipity_event_ckeditor/ckeditor/"');
$propbag->add('default', 'plugins/serendipity_event_ckeditor/ckeditor/');
break;
case 'plugpath':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_EVENT_CKEDITOR_INSTALL_PLUGPATH);
$propbag->add('description', PLUGIN_EVENT_CKEDITOR_OPTION_BLAHBLAH . '"' . $serendipity['serendipityHTTPPath'] . 'plugins/"');
$propbag->add('default', $serendipity['serendipityHTTPPath'] . 'plugins/');
break;
case 'codebutton':
$propbag->add('type', 'boolean');
$propbag->add('name', PLUGIN_EVENT_CKEDITOR_CODEBUTTON_OPTION);
$propbag->add('description', '');
$propbag->add('default', 'false');
break;
case 'prettify':
$propbag->add('type', 'boolean');
$propbag->add('name', PLUGIN_EVENT_CKEDITOR_PRETTIFY_OPTION);
$propbag->add('description', PLUGIN_EVENT_CKEDITOR_PRETTIFY_OPTION_BLAHBLAH);
$propbag->add('default', 'false');
break;
case 'kcfinder':
$propbag->add('type', 'boolean');
$propbag->add('name', PLUGIN_EVENT_CKEDITOR_KCFINDER_OPTION);
$propbag->add('description', PLUGIN_EVENT_CKEDITOR_KCFINDER_OPTION_BLAHBLAH);
$propbag->add('default', 'false');
break;
case 'acf_off':
$propbag->add('type', 'boolean');
$propbag->add('name', PLUGIN_EVENT_CKEDITOR_CKEACF_OPTION);
$propbag->add('description', PLUGIN_EVENT_CKEDITOR_CKEACF_OPTION_BLAHBLAH);
$propbag->add('default', 'false');
break;
case 'toolbar_break':
$propbag->add('type', 'boolean');
$propbag->add('name', PLUGIN_EVENT_CKEDITOR_TOOLBAR_OPTION);
$propbag->add('description', '');
$propbag->add('default', 'true');
break;
case 'force_install':
$propbag->add('type', 'boolean');
$propbag->add('name', PLUGIN_EVENT_CKEDITOR_FORCEINSTALL_OPTION);
$propbag->add('description', PLUGIN_EVENT_CKEDITOR_FORCEINSTALL_OPTION_BLAHBLAH . $this->cke_zipfile);
$propbag->add('default', 'false');
break;
default:
return false;
}
return true;
}
function generate_content(&$title) {
$title = $this->title;
}
function example() {
if (serendipity_db_bool($this->get_config('force_install'))) {
$this->forceZipInstall = true;
$this->install();
$this->forceZipInstall = false;
$this->set_config('force_install', 'false');
// forceZipInstall forces to surround the checkUpdate function, thus we set config database table to keep track
$this->updateTableZip();
echo '
';
}
$installer = $this->get_config('installer'); // Can't use method return value in write context in '' with substr(), get_config() and isset()
$parts = explode(':', $this->checkUpdateVersion[0]); // this is ckeditor only
echo PLUGIN_EVENT_CKEDITOR_REVISION_TITLE;
echo "\n
\n";
// hook this as a scalar value into this plugins lang files (would be needed by adding this to a constant)
foreach( $this->revisionPackage AS $revision ) {
echo '
' . $revision . "
\n";
}
echo "
\n\n";
if( isset($installer) && !empty($installer) ) {
switch ($installer[0]) {
case '4': // this won't happen, since case 2 is true - just a fake
echo '
Check Plugin Update Message: NO CONFIG SET OR NO MATCH -> config_set: "last_'.$parts[0].'_version:'. $parts[1].'"
';
break;
case '3':
echo '
Installer Update Message: Check Update found false, no unpack needed. Plugin upgrade successfully done or has been triggered to be checked by an other Spartacus Plugin update!
';
break;
case '2':
echo '
Installer Message: Extracting the zip to ' . $this->cke_path . ' directory done!
';
break;
case '1':
echo '
Installer Error[1]: Extracting the zip to ' . $this->cke_path . ' directory failed! Please extract ' . $this->cke_zipfile . ' by hand.
';
break;
case '0':
echo '
Installer Error[0]: Due to a writing permission error, extracting the zip to ' . $this->cke_path . ' directory failed! Please set "/plugins" or "/plugins/serendipity_event_ckeditor" directory and files correct writing permissions and extract ' . $this->cke_zipfile . ' by hand or try again and remove(!) this plugin from your plugin list and install it again.
';
break;
}
$this->set_config('installer', ''); // can't use serendipity_plugin_api::remove_plugin_value($this->instance, array('installer')); here, since it delivers the wrong instance
}
#echo $installer[0] . ' - ' . $this->instance; // this debug message on the other hand will do well, if all went through w/o install() returning false
echo PLUGIN_EVENT_CKEDITOR_INSTALL;
echo PLUGIN_EVENT_CKEDITOR_CONFIG;
}
/**
* Set config database table to keep track to zip updates
* @access private
*/
private function updateTableZip() {
foreach(array_values($this->checkUpdateVersion) AS $package) {
$match = explode(':', $package);
$this->set_config('last_'.$match[0].'_version', $match[1]);
}
}
/**
* Check update versions to perform unzip and create config values
* @access private
* @return boolean
*/
private function checkUpdate() {
$doupdate = false;
foreach(array_values($this->checkUpdateVersion) AS $package) {
$match = explode(':', $package);
// always set and extract if not match
if ($this->get_config('last_'.$match[0].'_version') == $match[1]) {
$doupdate = false;
} else {
$this->set_config('last_'.$match[0].'_version', $match[1]); // redundant, since now done for both in updateTableZip, but leave here until new is proofed
$doupdate = true;
break; // this is possibly needed to force install upgrade routines
}
}
return $doupdate ? true : false;
}
/**
* empty a directory using the Standard PHP Library (SPL) iterator
* @access private
* @param string directory
*/
private function empty_dir($dir) {
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::CHILD_FIRST);
foreach ($iterator as $file) {
if ($file->isFile()) {
@unlink($file->__toString());
} else {
@rmdir($file->__toString());
}
}
}
/**
* Check and purge KCFinder Error fallback files to avoid errors
* @access private
*/
private function checkFallback() {
// kcfinder has a fallback media library mode if not properly loaded, or an other error occurs - get rid of it by default, since it stops image browser executing!
// this is only executed once for the finish hook with entryforms - but sadly twice for staticpages forms
if( is_file(dirname(__FILE__) . '/kcfinder/.htaccess') ) {
@unlink(dirname(__FILE__) . '/kcfinder/.htaccess');
$this->empty_dir(dirname(__FILE__) . '/kcfinder/.thumbs');
@rmdir(dirname(__FILE__) . '/kcfinder/.thumbs');
}
}
function event_hook($event, &$bag, &$eventData, $addData = null) {
global $serendipity;
$hooks = &$bag->get('event_hooks');
if (isset($hooks[$event])) {
switch($event) {
case 'frontend_footer':
// set prettify.css and prettify.js in frontend footer by plugin option (too much overhead to split this into head css and food js!)
if ($this->get_config('prettify')) {
$plugingpath = htmlspecialchars($this->get_config('plugpath'));
?>
get_config('path'));
$plgpath = htmlspecialchars($this->get_config('plugpath'));
$acf_off = serendipity_db_bool($this->get_config('acf_off')) ? 'true' : 'false'; // need this, to be passed correctly as boolean true/false to custom cke_config.js
$kcfd_on = serendipity_db_bool($this->get_config('kcfinder')) ? 'true' : 'false'; // same here
$pbck_on = serendipity_db_bool($this->get_config('codebutton')) ? 'true' : 'false'; // same here for cke_plugins.js
if(!isset($_COOKIE['KCFINDER_uploadurl']) || empty($_COOKIE['KCFINDER_uploadurl'])) {
setcookie('KCFINDER_uploadurl', serialize($serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath']), time()+60*60*24*30, $serendipity['serendipityHTTPPath'], $_SERVER['HTTP_HOST'], false);
// Google Chrome browser does not set cookies for domain "localhost" or other dotless hostnames. $_SERVER['HTTP_HOST'] must be NULL explicitely. Also do not use httponly parameter.
if(!isset($_COOKIE['KCFINDER_uploadurl']) || empty($_COOKIE['KCFINDER_uploadurl'])) {
setcookie('KCFINDER_uploadurl', serialize($serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath']), time()+60*60*24*30, $serendipity['serendipityHTTPPath'], NULL, false);
//setcookie($AUTH_COOKIE_NAME, $cookie_value, time() + cookie_expiration(), $BASE_DIRECTORY, null, false, true);
//this solved, Chrome still has some follow-up errors, not easy to solve. Please do not use Chrome with KCFINDER for domain "localhost" and similar local dotless named servers
}
}
/* set some global vars */
/* bind ckeditor */
/* build specific dynamic plugins and set custom config (cke_config.js) */
?>
/* CKE BACKEND MESSAGES
----------------------------------------------------------------- */
.msg_error,
.msg_success,
.msg_notice,
.msg_dialogue {
display:block;
margin: 1.5em 0;
padding: 10px;
}
.msg_error {
background: #f2dede;
border: 1px solid #e4b9b9;
color: #b94a48;
}
.msg_success {
background: #dff0d8;
border: 1px solid #c1e2b3;
color: #468847;
}
.msg_notice {
background: #fcf8e3;
border: 1px solid #f7ecb5;
color: #c09853;
}
.msg_dialogue {
background: #eee;
border: 1px solid #aaa;
color: #777;
}
.cke_config_block {
opacity: 0.7;
font-size: smaller;
border: 1px dashed;
}
/* CKE end ----------------------------------------------------------------- */
install()) {
header('Location: ' . $serendipity['baseURL'] . 'serendipity_admin.php?serendipity[adminModule]=plugins&serendipity[plugin_to_conf]='.urlencode($this->instance));
} else {
header('Location: ' . $serendipity['baseURL'] . 'serendipity_admin.php?serendipity[adminModule]=plugins&serendipity[adminAction]=addnew&serendipity[only_group]=UPGRADE&serendipity[type]=event');
}
}
break;
case 'backend_plugins_update':
// Make sure a Spartacus update really falls down to plugins config, for the need to deflate the zip, if necessary.
// This needs a *real* new HTTP request! Using plugin_to_conf:instance (see above) would not do here!!
// A request to ...&serendipity[install_plugin]=serendipity_event_ckeditor would force a deflate, but would install another plugin instance!
header('Location: ' . $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/triggerckeinstall');
break;
case 'backend_media_path_exclude_directories':
$eventData[".thumbs"] = true;
return true;
break;
case 'backend_wysiwyg':
$eventData['skip'] = true; // this skips htmlarea drop-in
if (preg_match('@^nugget@i', $eventData['item'])) {
// switch to finisher, in case of nuggets
$this->event_hook('backend_wysiwyg_finish', $bag, $eventData);
} else {
// this builds both textareas of entry forms only
if (isset($eventData['item']) && !empty($eventData['item'])) {
$jebtnarr = (isset($eventData['buttons']) && (is_array($eventData['buttons']) && !empty($eventData['buttons']))) ? json_encode($eventData['buttons']) : 'null';
?>
checkFallback();
return true;
break;
default:
return false;
}
} else {
return false;
}
}
}
?>