diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e5d3c3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +/vendor diff --git a/LICENSE b/LICENSE.md similarity index 94% rename from LICENSE rename to LICENSE.md index a8b6ff0..ae185af 100644 --- a/LICENSE +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Robert Korulczyk +Copyright (c) 2017 Robert Korulczyk Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 61516f9..5373cd1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,62 @@ -# yii-tinymce -TinyMCE editor integration for Yii 1.1 +TinyMCE integration for Yii 1.1 +=============================== + +Yii 1.1 extension that provides basic integration with [TinyMce editor](https://www.tinymce.com/). + + +Installation +------------ + +The preferred way to install this extension is through [composer](https://getcomposer.org/download/). + +Either run + +```shell +php composer.phar require rob006/yii-tinymce +``` + +or add + +```json +"rob006/yii2-tinymce": "^1.0" +``` + +to the require section of your `composer.json` file. + + +Usage +----- + +Basic usage: + +```php +widget('TinyMceWidget', [ + 'model' => $model, + 'attribute' => 'value', +]) ?> +``` + +Usage with custom settings and [Yiistrap](http://www.getyiistrap.com/) and [elFinder](https://github.com/rob006/yii-elfinder2) extensions integration. + +```php +textAreaControlGroup($model, 'value', ['rows' => 6, 'span' => 8,]) ?> +widget('TinyMceWidget', [ + 'model' => $model, + 'attribute' => 'value', + 'dry_run' => true, + 'fileManager' => [ + 'class' => 'TinyMceElFinder', + 'popupConnectorRoute' => 'pageAssetsPopup', + 'popupTitle' => 'Files', + ], + 'settings' => [ + 'content_css' => $this->getEditorStyles(), + ], +]) ?> +``` +Resources +--------- + + * [Extension page](https://github.com/rob006/yii-tinymce) + * [elFinder extension](https://github.com/rob006/yii-elfinder2) + * [TinyMce page](https://www.tinymce.com/) diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..b9a74cb --- /dev/null +++ b/composer.json @@ -0,0 +1,37 @@ +{ + "name": "rob006/yii-tinymce", + "description": "TinyMCE editor integration for Yii 1.1.", + "type": "yii-extension", + "keywords": ["yii", "extension", "TinyMCE", "widget", "elFinder"], + "minimum-stability": "dev", + "license": "MIT", + "authors": [ + { + "name": "Robert Korulczyk", + "email": "robert@korulczyk.pl", + "homepage": "https://rob006.net/" + } + ], + "support": { + "issues": "https://github.com/rob006/yii-tinymce/issues", + "source": "https://github.com/rob006/yii-tinymce" + }, + "require": { + "php": ">=5.4.0", + "tinymce/tinymce": "^4.5.6", + "yiisoft/yii": "~1.1.18" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "suggest": { + "rob006/yii-elfinder2": "Provides file manager integration with editor." + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..ae23448 --- /dev/null +++ b/composer.lock @@ -0,0 +1,161 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "content-hash": "70a60c3178ff46959ee0583a6ab0fed8", + "packages": [ + { + "name": "tinymce/tinymce", + "version": "4.6.3", + "source": { + "type": "git", + "url": "https://github.com/tinymce/tinymce-dist.git", + "reference": "64bf45565b3f99f6c2313363ddd0f86077a84406" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tinymce/tinymce-dist/zipball/64bf45565b3f99f6c2313363ddd0f86077a84406", + "reference": "64bf45565b3f99f6c2313363ddd0f86077a84406", + "shasum": "" + }, + "type": "component", + "extra": { + "component": { + "scripts": [ + "tinymce.js", + "plugins/*/plugin.js", + "themes/*/theme.js" + ], + "files": [ + "tinymce.min.js", + "plugins/*/plugin.min.js", + "themes/*/theme.min.js", + "skins/**" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "description": "Web based JavaScript HTML WYSIWYG editor control.", + "homepage": "http://www.tinymce.com", + "keywords": [ + "editor", + "html", + "javascript", + "richtext", + "tinymce", + "wysiwyg" + ], + "time": "2017-05-30T12:56:46+00:00" + }, + { + "name": "yiisoft/yii", + "version": "1.1.18", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii.git", + "reference": "018a89e67c0f1e13b11630a26a953f1cb0678291" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii/zipball/018a89e67c0f1e13b11630a26a953f1cb0678291", + "reference": "018a89e67c0f1e13b11630a26a953f1cb0678291", + "shasum": "" + }, + "require": { + "php": ">=5.1.0" + }, + "require-dev": { + "phing/phing": "2.*", + "phpunit/phpunit": "~3.7", + "phpunit/phpunit-selenium": "~1.4.0" + }, + "bin": [ + "framework/yiic" + ], + "type": "library", + "autoload": { + "classmap": [ + "framework/YiiBase.php", + "framework/yii.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Qiang Xue", + "email": "qiang.xue@gmail.com", + "homepage": "http://www.yiiframework.com/", + "role": "Founder and project lead" + }, + { + "name": "Alexander Makarov", + "email": "sam@rmcreative.ru", + "homepage": "http://rmcreative.ru/", + "role": "Core framework development" + }, + { + "name": "Maurizio Domba", + "homepage": "http://mdomba.info/", + "role": "Core framework development" + }, + { + "name": "Carsten Brandt", + "email": "mail@cebe.cc", + "homepage": "http://cebe.cc/", + "role": "Core framework development" + }, + { + "name": "Wei Zhuo", + "email": "weizhuo@gmail.com", + "role": "Project site maintenance and development" + }, + { + "name": "Sebastián Thierer", + "email": "sebas@artfos.com", + "role": "Component development" + }, + { + "name": "Jeffrey Winesett", + "email": "jefftulsa@gmail.com", + "role": "Documentation and marketing" + }, + { + "name": "Timur Ruziev", + "email": "resurtm@gmail.com", + "homepage": "http://resurtm.com/", + "role": "Core framework development" + }, + { + "name": "Paul Klimov", + "email": "klimov.paul@gmail.com", + "role": "Core framework development" + } + ], + "description": "Yii Web Programming Framework", + "homepage": "http://www.yiiframework.com/", + "keywords": [ + "framework", + "yii" + ], + "time": "2017-04-19T11:51:43+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.4.0" + }, + "platform-dev": [] +} diff --git a/src/TinyMceFileManager.php b/src/TinyMceFileManager.php new file mode 100644 index 0000000..ee8c2f2 --- /dev/null +++ b/src/TinyMceFileManager.php @@ -0,0 +1,33 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE.md. + */ + +/** + * Abstract FileManager class to use with TinyMce. + * For example see elFinder extension. + * + * @see https://github.com/rob006/yii-elfinder2 + * + * @author Robert Korulczyk + * @since 1.0.0 + */ +abstract class TinyMceFileManager extends CComponent { + + /** + * Initialize FileManager component, registers required JS. + */ + public function init() { + } + + /** + * @return string JavaScript callback function, starts with "js:". + */ + abstract public function getFileBrowserCallback(); +} diff --git a/src/TinyMceWidget.php b/src/TinyMceWidget.php new file mode 100644 index 0000000..8f28035 --- /dev/null +++ b/src/TinyMceWidget.php @@ -0,0 +1,176 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE.md. + */ + +/** + * TinyMCE input widget. + * + * ```php + * $form->textArea($model, 'value', ['rows' => 6, 'span' => 8]); + * $this->widget('TinyMceWidget', [ + * 'model' => $model, + * 'attribute' => 'value', + * 'dry_run' => true, + * 'fileManager' => [ + * 'class' => 'TinyMceElFinder', + * 'popupConnectorRoute' => 'pageAssetsPopup', + * 'popupTitle' => 'Files', + * ], + * 'settings' => [ + * 'content_css' => $this->getEditorStyles(), + * ], + * ]); + * ``` + * + * @author Robert Korulczyk + * @since 1.0.0 + */ +class TinyMceWidget extends CInputWidget { + + /** + * If `true`, widget don't create a textarea, only register necessary scripts. + * + * @var bool + */ + public $dry_run = false; + + /** + * @var bool|array FileManager configuration. + * For example: + * 'fileManager' => [ + * 'class' => 'TinyMceElFinder', + * 'connectorRoute' => 'admin/elfinder/connector', + * ] + */ + public $fileManager = false; + + /** + * Default widget configuration. + * + * @var array + */ + public $defaultSettings = [ + 'plugins' => [ + 'advlist autolink lists link image charmap print preview hr anchor', + 'searchreplace visualblocks visualchars code wordcount autosave', + 'insertdatetime media nonbreaking save table directionality', + 'template paste textcolor', + ], + 'toolbar' => [ + 'undo redo | styleselect | forecolor backcolor | bold italic quote underline strikethrough subscript superscript | removeformat | alignleft aligncenter alignright alignjustify | ltr rtl', + 'bullist numlist outdent indent | link unlink anchor footnote index | image gallery media | nonbreaking charmap pagebreak hr searchreplace', + ], + 'indentation' => '2em', + 'paste_as_text' => true, + 'browser_spellcheck' => true, + 'style_formats' => [ + 'headers' => [ + 'title' => 'Headers', + 'items' => [ + 'h2' => ['title' => 'Header 2', 'format' => 'h2'], + 'h3' => ['title' => 'Header 3', 'format' => 'h3'], + 'h4' => ['title' => 'Header 4', 'format' => 'h4'], + 'h5' => ['title' => 'Header 5', 'format' => 'h5'], + 'h6' => ['title' => 'Header 6', 'format' => 'h6'], + ], + ], + 'others' => [ + 'title' => 'Others', + 'items' => [ + 'p' => ['title' => 'Paragraph', 'format' => 'p'], + 'div' => ['title' => 'Div', 'format' => 'div'], + 'pre' => ['title' => 'Pre', 'format' => 'pre'], + 'code' => ['title' => 'Code', 'icon' => 'code', 'format' => 'code'], + ], + ], + ], + 'toolbar_items_size' => 'small', + 'image_advtab' => true, + 'relative_urls' => false, + 'height' => 400, + 'content_css' => [], + // do not allow change list style + 'advlist_bullet_styles' => 'default', + // alow embed js files + 'extended_valid_elements' => 'script[src]', + // new features in TinyMCE 4.3.x + 'image_caption' => true, + 'media_live_embeds' => true, + // new features in TinyMCE 4.5.x + 'style_formats_autohide' => true, + ]; + + /** + * Widget settings will override defaultSettings + * + * @var array + */ + public $settings = []; + + /** + * @var string + */ + private $tinymceAssetsDir; + + /** + * {@inheritdoc} + * + * @throws CException + */ + public function init() { + $this->tinymceAssetsDir = Yii::app()->assetManager->publish(Yii::getPathOfAlias('vendor.tinymce.tinymce')); + + $this->settings = CMap::mergeArray($this->defaultSettings, $this->settings); + } + + /** + * {@inheritdoc} + * + * @throws CException + */ + public function run() { + list($name, $id) = $this->resolveNameID(); + if (isset($this->htmlOptions['id'])) { + $id = $this->htmlOptions['id']; + } else { + $this->htmlOptions['id'] = $id; + } + if (isset($this->htmlOptions['name'])) { + $name = $this->htmlOptions['name']; + } + + if (!$this->dry_run) { + if ($this->model !== null) { + echo CHtml::textArea($name, CHtml::resolveValue($this->model, $this->attribute), $this->htmlOptions); + } else { + echo CHtml::textArea($name, $this->value, $this->htmlOptions); + } + } + $this->registerAssets($id); + } + + private function registerAssets($id) { + $cs = Yii::app()->getClientScript(); + $cs->registerCoreScript('jquery'); + $cs->registerScriptFile($this->tinymceAssetsDir . '/tinymce.min.js'); + $cs->registerScriptFile($this->tinymceAssetsDir . '/jquery.tinymce.min.js'); + + if ($this->fileManager !== false) { + /* @var $fm TinyMceFileManager */ + $fm = Yii::createComponent($this->fileManager); + $fm->init(); + $this->settings['file_browser_callback'] = $fm->getFileBrowserCallback(); + } + + $settings = CJavaScript::encode($this->settings); + + $cs->registerScript("{$id}_tinyMce_init", "$('#{$id}').tinymce({$settings});"); + } +}