├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── composer.json └── lib ├── FroalaEditor.php ├── FroalaEditor ├── File.php ├── Image.php ├── S3.php ├── Utils │ ├── DiskManagement.php │ └── Utils.php └── Video.php └── autoload.php /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | examples/uploads 3 | composer.lock 4 | vendor/ 5 | **/.DS_STORE 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Froala Labs 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Froala WYSIWYG Editor PHP SDK 2 | 3 | [![Packagist](https://img.shields.io/packagist/v/froala/wysiwyg-editor-php-sdk.svg)](https://packagist.org/packages/froala/wysiwyg-editor-php-sdk) 4 | [![Packagist](https://img.shields.io/packagist/dt/froala/wysiwyg-editor-php-sdk.svg)](https://packagist.org/packages/froala/wysiwyg-editor-php-sdk) 5 | 6 | Easing the [Froala WYSIWYG HTML Editor](https://github.com/froala/wysiwyg-editor) server side integration in PHP projects. 7 | 8 | ## Dependencies 9 | 10 | PHP version >= 5.4.0 is required. 11 | 12 | The following PHP extensions are required: 13 | 14 | * fileinfo 15 | * imagick 16 | 17 | ## Setup Instructions 18 | 1. Install composer within the example directory. You can find instructions on how to install composer on composer’s website (https://getcomposer.org/download/) 19 | 2. Add Froala WYSIWYG Editor PHP SDK in your compose.json file 20 | 21 | { 22 | "require" : { 23 | "froala/wysiwyg-editor-php-sdk" : "" 24 | } 25 | } 26 | 3. Run composer: 27 | 28 | php composer.phar install 29 | 30 | Or if you installed composer globally: 31 | 32 | composer install 33 | 34 | ## Documentation 35 | 36 | * [Official documentation](https://www.froala.com/wysiwyg-editor/docs/sdks/php) 37 | 38 | ## Help 39 | - Found a bug or have some suggestions? Just submit an issue. 40 | - Having trouble with your integration? [Contact Froala Support team](http://froala.dev/wysiwyg-editor/contact). 41 | 42 | ## License 43 | 44 | The Froala WYSIWYG Editor PHP SDK is licensed under MIT license. However, in order to use Froala WYSIWYG HTML Editor plugin you should purchase a license for it. 45 | 46 | Froala Editor has [3 different licenses](http://froala.com/wysiwyg-editor/pricing) for commercial use. 47 | For details please see [License Agreement](http://froala.com/wysiwyg-editor/terms). 48 | 49 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "froala/wysiwyg-editor-php-sdk", 3 | "version": "4.5.2", 4 | "description": "PHP SDK for Froala WYSIWYG Editor", 5 | "type": "php-plugin", 6 | "keywords": [ 7 | "froala", 8 | "editor", 9 | "php", 10 | "sdk", 11 | "froala", 12 | "html", 13 | "text", 14 | "editor", 15 | "wysiwyg", 16 | "rich editor", 17 | "rich text editor", 18 | "rte", 19 | "php wysiwyg", 20 | "php rich text editor", 21 | "php rte" 22 | ], 23 | "homepage": "https://www.froala.com/wysiwyg-editor", 24 | "license": "proprietary", 25 | "authors": [ 26 | { 27 | "name": "Froala Labs", 28 | "role": "Maintainer" 29 | } 30 | ], 31 | "require": { 32 | "php": ">=5.4.0", 33 | "ext-fileinfo": "*", 34 | "ext-imagick": "*" 35 | }, 36 | "autoload": { 37 | "psr-0": { 38 | "FroalaEditor": "lib/" 39 | }, 40 | "psr-4": { 41 | "FroalaEditor\\": "lib/FroalaEditor" 42 | } 43 | }, 44 | "support": { 45 | "issues": "https://github.com/froala/froala-editor-php-sdk/issues", 46 | "source": "https://www.froala.com/wysiwyg-editor" 47 | }, 48 | "extra": { 49 | "installer-name": "FroalaEditor" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/FroalaEditor.php: -------------------------------------------------------------------------------- 1 | = 5.4.0 required'); 12 | } 13 | 14 | function requireDependencies() { 15 | $requiredExtensions = ['fileinfo', 'imagick']; 16 | foreach ($requiredExtensions AS $ext) { 17 | if (!extension_loaded($ext)) { 18 | throw new Exception('The Froala Editor SDK library requires the ' . $ext . ' extension.'); 19 | } 20 | } 21 | } 22 | 23 | requireDependencies(); 24 | -------------------------------------------------------------------------------- /lib/FroalaEditor/File.php: -------------------------------------------------------------------------------- 1 | 'file', 10 | 'validation' => array( 11 | 'allowedExts' => array('txt', 'pdf', 'doc'), 12 | 'allowedMimeTypes' => array('text/plain', 'application/msword', 'application/x-pdf', 'application/pdf') 13 | ) 14 | ); 15 | 16 | /** 17 | * File upload to disk. 18 | * 19 | * @param fileRoute string 20 | * @param options [optional] 21 | * ( 22 | * fieldname => string 23 | * validation => array OR function 24 | * ) 25 | * @return {link: 'linkPath'} or error string 26 | */ 27 | public static function upload($fileRoute, $options = NULL) { 28 | 29 | if (is_null($options)) { 30 | $options = File::$defaultUploadOptions; 31 | } else { 32 | $options = array_merge(File::$defaultUploadOptions, $options); 33 | } 34 | 35 | return DiskManagement::upload($fileRoute, $options); 36 | } 37 | 38 | /** 39 | * Delete file from disk. 40 | * 41 | * @param src string 42 | * @return boolean 43 | */ 44 | public static function delete($src) { 45 | 46 | return DiskManagement::delete($src); 47 | } 48 | } 49 | 50 | class_alias('FroalaEditor\File', 'FroalaEditor_File'); 51 | ?> 52 | -------------------------------------------------------------------------------- /lib/FroalaEditor/Image.php: -------------------------------------------------------------------------------- 1 | 'file', 11 | 'validation' => array( 12 | 'allowedExts' => array('gif', 'jpeg', 'jpg', 'png', 'svg', 'blob'), 13 | 'allowedMimeTypes' => array('image/gif', 'image/jpeg', 'image/pjpeg', 'image/x-png', 'image/png', 'image/svg+xml') 14 | ), 15 | 'resize' => NULL 16 | ); 17 | 18 | /** 19 | * Image upload to disk. 20 | * 21 | * @param fileRoute string 22 | * @param options [optional] 23 | * ( 24 | * fieldname => string 25 | * validation => array OR function 26 | * resize: => array 27 | * ) 28 | * @return {link: 'linkPath'} or error string 29 | */ 30 | public static function upload($fileRoute, $options = NULL) { 31 | // Check if there are any options passed. 32 | if (is_null($options)) { 33 | $options = Image::$defaultUploadOptions; 34 | } else { 35 | $options = array_merge(Image::$defaultUploadOptions, $options); 36 | } 37 | 38 | // Upload image. 39 | return DiskManagement::upload($fileRoute, $options); 40 | } 41 | 42 | /** 43 | * Delete image from disk. 44 | * 45 | * @param src string 46 | * @return boolean 47 | */ 48 | public static function delete($src) { 49 | // Delete image. 50 | return DiskManagement::delete($src); 51 | } 52 | 53 | /** 54 | * List images from disk 55 | * 56 | * @param folderPath string 57 | * 58 | * @return array of image properties 59 | * - on success : [{url: 'url', thumb: 'thumb', name: 'name'}, ...] 60 | * - on error : {error: 'error message'} 61 | */ 62 | public static function getList($folderPath, $thumbPath = null) { 63 | 64 | if (empty($thumbPath)) { 65 | $thumbPath = $folderPath; 66 | } 67 | 68 | // Array of image objects to return. 69 | $response = array(); 70 | 71 | $absoluteFolderPath = $_SERVER['DOCUMENT_ROOT'] . $folderPath; 72 | 73 | // Image types. 74 | $image_types = Image::$defaultUploadOptions['validation']['allowedMimeTypes']; 75 | 76 | // Filenames in the uploads folder. 77 | $fnames = scandir($absoluteFolderPath); 78 | 79 | // Check if folder exists. 80 | if ($fnames) { 81 | // Go through all the filenames in the folder. 82 | foreach ($fnames as $name) { 83 | // Filename must not be a folder. 84 | if (!is_dir($name)) { 85 | // Check if file is an image. 86 | 87 | if (in_array(mime_content_type($absoluteFolderPath . $name), $image_types)) { 88 | // Build the image. 89 | $img = new \StdClass; 90 | $img->url = $folderPath . $name; 91 | $img->thumb = $thumbPath . $name; 92 | $img->name = $name; 93 | 94 | // Add to the array of image. 95 | array_push($response, $img); 96 | } 97 | } 98 | } 99 | } 100 | 101 | // Folder does not exist, respond with a JSON to throw error. 102 | else { 103 | throw new Exception('Images folder does not exist!'); 104 | } 105 | 106 | return $response; 107 | } 108 | } 109 | 110 | class_alias('FroalaEditor\Image', 'FroalaEditor_Image'); 111 | ?> 112 | -------------------------------------------------------------------------------- /lib/FroalaEditor/S3.php: -------------------------------------------------------------------------------- 1 | 'Europe/Bucharest', 12 | * bucket => 'bucketName', 13 | * 14 | * //http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region 15 | * region => 's3', 16 | * keyStart => 'editor/', 17 | * acl => 'public-read', 18 | * accessKey => 'YOUR-AMAZON-S3-PUBLIC-ACCESS-KEY', 19 | * secretKey => 'YOUR-AMAZON-S3-SECRET-ACCESS-KEY' 20 | * ) 21 | * 22 | * @return: 23 | * { 24 | * bucket: bucket, 25 | * region: region, 26 | * keyStart: keyStart, 27 | * params: { 28 | * acl: acl, 29 | * policy: policy, 30 | * 'x-amz-algorithm': 'AWS4-HMAC-SHA256', 31 | * 'x-amz-credential': xAmzCredential, 32 | * 'x-amz-date': xAmzDate, 33 | * 'x-amz-signature': signature 34 | * } 35 | * } 36 | */ 37 | 38 | public static function getHash($config) { 39 | 40 | // Check default region. 41 | $config['region'] = !empty($config['region']) ? $config['region'] : 'us-east-1'; 42 | $config['region'] = $config['region'] == 's3' ? 'us-east-1' : $config['region']; 43 | 44 | if (empty($config['conditions'])) { 45 | $config['conditions'] = array(); 46 | } 47 | 48 | // Set date timezone. 49 | date_default_timezone_set($config['timezone']); 50 | 51 | // Important variables that will be used throughout this example. 52 | $bucket = $config['bucket']; 53 | $region = $config['region']; 54 | $keyStart = $config['keyStart']; 55 | $acl = $config['acl']; 56 | 57 | // These can be found on your Account page, under Security Credentials > Access Keys. 58 | $accessKeyId = $config['accessKey']; 59 | $secret = $config['secretKey']; 60 | 61 | $dateString = date('Ymd'); 62 | 63 | $credential = implode("/", array($accessKeyId, $dateString, $region, 's3/aws4_request')); 64 | $xAmzDate = $dateString . 'T000000Z'; 65 | 66 | // Build policy. 67 | $policy = base64_encode(json_encode(array( 68 | // ISO 8601 - date('c'); generates uncompatible date, so better do it manually. 69 | 'expiration' => date('Y-m-d\TH:i:s.000\Z', strtotime('+10 hours')), // 10 hours into the future. 70 | 'conditions' => array_merge(array( 71 | array('bucket' => $bucket), 72 | array('acl' => $acl), 73 | array('success_action_status' => '201'), 74 | array('x-requested-with' => 'xhr'), 75 | // Optionally control content type and file size 76 | // array('Content-Type' => 'application/pdf'), 77 | array('x-amz-algorithm' => 'AWS4-HMAC-SHA256'), 78 | array('x-amz-credential' => $credential), 79 | array('x-amz-date' => $xAmzDate), 80 | array('starts-with', '$key', $keyStart), 81 | array('starts-with', '$Content-Type', '') // Accept all files. 82 | ), $config['conditions']) 83 | ))); 84 | 85 | // Generate signature. 86 | $dateKey = hash_hmac('sha256', $dateString, 'AWS4' . $secret, true); 87 | $dateRegionKey = hash_hmac('sha256', $region, $dateKey, true); 88 | $dateRegionServiceKey = hash_hmac('sha256', 's3', $dateRegionKey, true); 89 | $signingKey = hash_hmac('sha256', 'aws4_request', $dateRegionServiceKey, true); 90 | $signature = hash_hmac('sha256', $policy, $signingKey, false); 91 | 92 | // Prepare response. 93 | $response = new \StdClass; 94 | $response->bucket = $bucket; 95 | $response->region = $region != 'us-east-1' ? 's3.' . $region : 's3'; 96 | $response->keyStart = $keyStart; 97 | 98 | // Prepare params. 99 | $params = new \StdClass; 100 | $params->acl = $acl; 101 | $params->policy = $policy; 102 | $params->{'x-amz-algorithm'} = 'AWS4-HMAC-SHA256'; 103 | $params->{'x-amz-credential'} = $credential; 104 | $params->{'x-amz-date'} = $xAmzDate; 105 | $params->{'x-amz-signature'} = $signature; 106 | 107 | foreach ($config['conditions'] as $value) { 108 | foreach ($value as $k => $v) { 109 | $params->{$k} = $v; 110 | } 111 | } 112 | 113 | // Set params in response. 114 | $response->params = $params; 115 | 116 | return json_encode($response); 117 | } 118 | } 119 | 120 | // Define alias. 121 | class_alias('FroalaEditor\S3', 'FroalaEditor_S3'); -------------------------------------------------------------------------------- /lib/FroalaEditor/Utils/DiskManagement.php: -------------------------------------------------------------------------------- 1 | string 14 | * validation => array OR function 15 | * resize: => array [only for images] 16 | * ) 17 | * 18 | * @return {link: 'linkPath'} or error string 19 | */ 20 | public static function upload($fileRoute, $options) { 21 | 22 | $fieldname = $options['fieldname']; 23 | 24 | if (empty($fieldname) || empty($_FILES[$fieldname])) { 25 | throw new \Exception('Fieldname is not correct. It must be: ' . $fieldname); 26 | } 27 | 28 | if ( 29 | isset($options['validation']) && 30 | !Utils::isValid($options['validation'], $fieldname) 31 | ) { 32 | throw new \Exception('File does not meet the validation.'); 33 | } 34 | 35 | // Get filename. 36 | $temp = explode(".", $_FILES[$fieldname]["name"]); 37 | 38 | // Get extension. 39 | $extension = end($temp); 40 | 41 | // Generate new random name. 42 | $name = sha1(microtime()) . "." . $extension; 43 | 44 | $fullNamePath = $_SERVER['DOCUMENT_ROOT'] . $fileRoute . $name; 45 | 46 | $mimeType = Utils::getMimeType($_FILES[$fieldname]["tmp_name"]); 47 | 48 | if (isset($options['resize']) && $mimeType != 'image/svg+xml') { 49 | // Resize image. 50 | $resize = $options['resize']; 51 | 52 | // Parse the resize params. 53 | $columns = $resize['columns']; 54 | $rows = $resize['rows']; 55 | $filter = isset($resize['filter']) ? $resize['filter'] : \Imagick::FILTER_UNDEFINED; 56 | $blur = isset($resize['blur']) ? $resize['blur'] : 1; 57 | $bestfit = isset($resize['bestfit']) ? $resize['bestfit'] : false; 58 | 59 | $imagick = new \Imagick($_FILES[$fieldname]["tmp_name"]); 60 | 61 | $imagick->resizeImage($columns, $rows, $filter, $blur, $bestfit); 62 | $imagick->writeImage($fullNamePath); 63 | $imagick->destroy(); 64 | } else { 65 | // Save file in the uploads folder. 66 | move_uploaded_file($_FILES[$fieldname]["tmp_name"], $fullNamePath); 67 | } 68 | 69 | // Generate response. 70 | $response = new \StdClass; 71 | $response->link = $fileRoute . $name; 72 | 73 | return $response; 74 | } 75 | 76 | 77 | /** 78 | * Delete file from disk. 79 | * 80 | * @param src string 81 | * @return boolean 82 | */ 83 | public static function delete($src) { 84 | 85 | $filePath = $_SERVER['DOCUMENT_ROOT'] . $src; 86 | // Check if file exists. 87 | if (file_exists($filePath)) { 88 | // Delete file. 89 | return unlink($filePath); 90 | } 91 | 92 | return true; 93 | } 94 | } 95 | 96 | // Define alias. 97 | class_alias('FroalaEditor\Utils\DiskManagement', 'FroalaEditor_DiskManagement'); -------------------------------------------------------------------------------- /lib/FroalaEditor/Utils/Utils.php: -------------------------------------------------------------------------------- 1 | 'file', 10 | 'validation' => array( 11 | 'allowedExts' => array('mp4', 'webm', 'ogg'), 12 | 'allowedMimeTypes' => array('video/mp4','video/webm', 'video/ogg') 13 | ), 14 | 'resize' => NULL 15 | ); 16 | 17 | /** 18 | * Video upload to disk. 19 | * 20 | * @param fileRoute string 21 | * @param options [optional] 22 | * ( 23 | * fieldname => string 24 | * validation => array OR function 25 | * ) 26 | * @return {link: 'linkPath'} or error string 27 | */ 28 | public static function upload($fileRoute, $options = NULL) { 29 | if (is_null($options)) { 30 | $options = Video::$defaultUploadOptions; 31 | } else { 32 | $options = array_merge(Video::$defaultUploadOptions, $options); 33 | } 34 | return DiskManagement::upload($fileRoute, $options); 35 | } 36 | 37 | /** 38 | * Delete file from disk. 39 | * 40 | * @param src string 41 | * @return boolean 42 | */ 43 | public static function delete($src) { 44 | 45 | return DiskManagement::delete($src); 46 | } 47 | } 48 | 49 | class_alias('FroalaEditor\Video', 'FroalaEditor_Video'); 50 | ?> -------------------------------------------------------------------------------- /lib/autoload.php: -------------------------------------------------------------------------------- 1 |