Integrating YII, CKEditor and KCFinder

To integrating YII and CKEditor I used editme extension. You can download it from YII Extensions directory. I found installing and using editme extension is easier than the other CKEditor extension that I ever used. Here the link of editme extension: http://www.yiiframework.com/extension/editme/

Then, here came the hard question for me, about how to integrating kcfinder into existing application. For you that want to know what kcfinder is, then you may go to the project website here in http://kcfinder.sunhater.com/.

And because the limitation of my English, I will show you how I integrating kcfinder with YII in code and avoiding too much technique discussion about it ::) .

First, I create yii.php and saved it in integration folder of kcfinder. That is kcfinder/integration/yii.php




<?php

/**

 * set with your webroot application (this is not YII framework path)

 */

$yii_app = dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'..';


// -- main logic

$current_cwd = getcwd();

// we need ability to share SESSION between kcfinder and YII ?

chdir($yii_app);

// get current after change directory ...

$curr = getcwd();


// set $yii and $config path value

// THIS IS YII Framework directory, relative with your application. 

// For easier purpose, I just copy paste my code in index.php

// ---

$yii=$curr.'/../yii/framework/yii.php';


if(!($_SERVER['HTTP_HOST']=='localhost')) {

    // change the following paths if necessary

    $yii=$curr.'/yii/framework/yii.php';


    $config=$curr.'/protected/config/production.php';


    // specify how many levels of call stack should be shown in each log message

    defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);

} else {

     $config=$curr.'/protected/config/main.php';


    // remove the following lines when in production mode

    defined('YII_DEBUG') or define('YII_DEBUG',true);

    // specify how many levels of call stack should be shown in each log message

    defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);

}


require_once($yii);


Yii::createWebApplication($config);


/**

 * SET WITH YOUR VALUE ------------------------

 * decide your own PATH here

 * for description then you need to read kcfinder manual

 */

$uploadURL = Yii::app()->baseUrl

        .'/..'

        .Yii::app()->params['fileDownloadPath'];

$uploadDir = dirname(__FILE__).DIRECTORY_SEPARATOR

        .'..'.DIRECTORY_SEPARATOR // out of integration

        .'..' // out of kcfinder

        .Yii::app()->params['fileDownloadPath'];


$session = new CHttpSession;

$session->setSavePath(Yii::app()->session->savePath);

$session->open();

$session['KCFINDER'] = array();

$session['KCFINDER'] = array(

    'disabled'=> !UserIdentity::canBrowseServer(),

    'uploadURL'=> $uploadURL,

    'uploadDir'=>$uploadDir,

);

// then back to our path

chdir($current_cwd);


spl_autoload_unregister(array('YiiBase','autoload'));

spl_autoload_register('__autoload');

spl_autoload_register(array('YiiBase','autoload'));

?>

After that I change kcfinder/core/autoload.php, I add yii as the another CMS integration into kcfinder. Yes I know it’s not true because YII is not a CMS. But currently, change too much core code will cause a headache next time when we decide to upgrade kcfinder with the new version.

In my code it is about line number 40, change it into code like this.


// CMS INTEGRATION

if (isset($_GET['cms'])) {

    switch ($_GET['cms']) {

        case "drupal": require "integration/drupal.php"; break;

        case "yii": require "integration/yii.php"; break;

    }

}

And then we need to change kcfinder/core/uploader.php too.

About line 118 we need to add yii, here I show you my code …


 // SET CMS INTEGRATION ATTRIBUTE

        if (isset($this->get['cms']) &&

            (

                in_array($this->get['cms'], array("drupal", "yii"))

            )

        )

            $this->cms = $this->get['cms'];

And then in the same file about line 140, when kcfinder set the SESSION; we don’t want kcfinder execute session_start() because we already did that with integration code previously. I change it into this …


        switch ($this->cms) {

            case "drupal": break;

            case "yii": break;

            default: session_start(); break;

        }



And finally, to used it with editme extension I code it like this:


$this->widget('application.extensions.editme.ExtEditMe', array(

    'model'=>$model,

    'height'=>$height,

    'attribute'=>$the_attribute,

    'toolbar'=>$btoolbar,

    'filebrowserImageBrowseUrl'=>  Yii::app()->baseUrl.'/kcfinder/browse.php?type=images&cms=yii',

    'filebrowserImageBrowseLinkUrl'=>Yii::app()->baseUrl.'/kcfinder/browse.php?type=images&cms=yii',

    'filebrowserImageUploadUrl'=>Yii::app()->baseUrl.'/kcfinder/upload.php?type=images&cms=yii',

));

As an info, in my application kcfinder installed in webroot and not inside protected directory; and Of course PHP safe_mode value must be off.

GOOOOOOOOOOLD!

I must try this as soon as I get back home. I’ve also used editme and its great, but the kcfinder i havent been able to set up… i can see why now.

Thanks for sharing, ckeditor and kcfinder is so powerfull tools

well, glad to hear that Sampa … It’s my 1st month with YII and I really like how fast is my developing process when I choose to use YII.

It might be better if you shared what you have done with us here :) Because it take couple days for me to learnt how to call YII from external library, especially when I touch spl_autoload_register function :D

And It’s far from standard coding like what I’ve learnt from the other extension, but for me it’s a huge step with YII :)

Hello, well I installed the editme and works fine to me, but the file/image upload doesn’t work to me. Is there any special configuration that is needed?

thanks

I’m afraid I don’t really understand what difficulties do you have.

But, to add file/image upload worked then you need to set some options with editme, that options will tell editme to generate CKEditor configuration to used kcfinder as file/image upload/browse manager …

Here I show you my code when I call kcfinder:




$this->widget('application.extensions.editme.ExtEditMe', array(

    'model'=>$model,

    'height'=>$height,

    'attribute'=>$the_attribute,

    'toolbar'=>$btoolbar,

    'filebrowserImageBrowseUrl'=>  Yii::app()->baseUrl.'/kcfinder/browse.php?type=images&cms=yii',

    'filebrowserImageBrowseLinkUrl'=>Yii::app()->baseUrl.'/kcfinder/browse.php?type=images&cms=yii',

    'filebrowserImageUploadUrl'=>Yii::app()->baseUrl.'/kcfinder/upload.php?type=images&cms=yii',

));

About how to integrating kcfinder with YII :) I’ve write the step above. It’s Not good enough, but it works …

Hope it help …

Yes you are right with these settings works. Thanks.

Another issue is that if I have different types of users how I have separate folders from each other and how I isolate the access to each one? kcfinder seems to work better if you want to have a folder with all files together and all user have access to the same uploaded files. Any suggestions?

To separate folders we can do it from code when we initialize kcfinder setting.


$session['KCFINDER'] = array();

$session['KCFINDER'] = array(

    'disabled'=> !Yii::app()->user->canBrowseServer(),

    'uploadURL'=> Yii::app()->user->initialPathURL(),

    'uploadDir'=>Yii::app()->user->initialPathDir(),

);

After that each user can not view folders that owned by the another user, as long as user folders are located on the same level.

But to isolate folder access, I’m afraid it would needs more works if we used folder that set with 777 privileges :)

First of all the yii.php integration doesn’t work for me. It doesn’t return any error but it seems that inside yii.php in the integration folder cannot find my path variable from config of my application. Also if we consider that I don’t use this integration and just before the widget I write there the paths…again seems that kcfinder still uses his path from his config file.

If it seems that kcfinder still uses his path from his config file, then it means yii integration script cannot make YII and kcfinder shared the same SESSION.

That’s why in the integration script you need to set the value of $yii_app (it would be your webroot application), $yii (it would be YII framework path) and $config (it would be your application path).

thank you this is work for me. :)


CWebUser and its behaviors do not have a method or closure named "canBrowseServer". 

:blink: please help.

See the part of kcfinder/integration/yii.php …


$session['KCFINDER'] = array(

    'disabled'=> !UserIdentity::canBrowseServer(),

    'uploadURL'=> $uploadURL,

    'uploadDir'=>$uploadDir,

);

You need to have method named canBrowseServer() that will set the value of KCFINDER session…

Or you can change it with your code …

in UserIdentity? what kind of example? can you show me? plz :unsure:

This is as easy as write a function that return boolean value …

Here I show you my code …




    public static function canBrowseServer($toCheck=-1)

    {

        $ret = false;

        if($toCheck!=-1) {

            return $toCheck == UserIdentity::LEVEL_SUPER_ADMIN || 

                    $toCheck == UserIdentity::LEVEL_ADMIN || 

                    $toCheck == UserIdentity::LEVEL_OPERATOR;

        }

        if(Yii::app()->user->isGuest) return false;

        switch(Yii::app()->user->level)

        {

            case UserIdentity::LEVEL_SUPER_ADMIN || 

                    UserIdentity::LEVEL_ADMIN || 

                    UserIdentity::LEVEL_OPERATOR:

                $ret = true;

                break;

            default:

                $ret = false;

        }

        return $ret;

    }

Can you make sure the folder file/image exists with write permission ‘777’

Click to:Browse Server

Failed opening required ‘/home/person/public_html/protected/config/production.php’ (include_path=’.:/usr/lib/php:/usr/local/lib/php’) in /home/person/public_html/framework/base/CApplication.php on line 133