Merge 72dca22ebd
into 578339dddb
This commit is contained in:
commit
56f3c086c2
6 changed files with 203 additions and 85 deletions
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
//
|
||||
// SimpleImage v3.6.3
|
||||
// SimpleImage
|
||||
//
|
||||
// A PHP class that makes working with images as simple as possible.
|
||||
//
|
||||
|
@ -31,7 +31,8 @@ class SimpleImage {
|
|||
ERR_LIB_NOT_LOADED = 8,
|
||||
ERR_UNSUPPORTED_FORMAT = 9,
|
||||
ERR_WEBP_NOT_ENABLED = 10,
|
||||
ERR_WRITE = 11;
|
||||
ERR_WRITE = 11,
|
||||
ERR_INVALID_FLAG = 12;
|
||||
|
||||
|
||||
protected $image;
|
||||
|
@ -46,9 +47,10 @@ class SimpleImage {
|
|||
* Creates a new SimpleImage object.
|
||||
*
|
||||
* @param string $image An image file or a data URI to load.
|
||||
* @param array $flags Optional override of default flags.
|
||||
* @throws \Exception Thrown if the GD library is not found; file|URI or image data is invalid.
|
||||
*/
|
||||
public function __construct($image = null) {
|
||||
public function __construct($image = '', $flags = []) {
|
||||
// Check for the required GD extension
|
||||
if(extension_loaded('gd')) {
|
||||
// Ignore JPEG warnings that cause imagecreatefromjpeg() to fail
|
||||
|
@ -57,6 +59,16 @@ class SimpleImage {
|
|||
throw new \Exception('Required extension GD is not loaded.', self::ERR_GD_NOT_ENABLED);
|
||||
}
|
||||
|
||||
// Associative array of flags.
|
||||
$this->flags = [
|
||||
"sslVerify" => true // Skip SSL peer validation
|
||||
];
|
||||
|
||||
// Override default flag values.
|
||||
foreach($flags as $flag => $value) {
|
||||
$this->setFlag($flag, $value);
|
||||
}
|
||||
|
||||
// Load an image through the constructor
|
||||
if(preg_match('/^data:(.*?);/', $image)) {
|
||||
$this->fromDataUri($image);
|
||||
|
@ -77,6 +89,37 @@ class SimpleImage {
|
|||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper functions
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Set flag value.
|
||||
*
|
||||
* @param string $flag Name of the flag to set.
|
||||
* @param boolean $value State of the flag.
|
||||
* @throws \Exception Thrown if flag does not exist (no default value).
|
||||
*/
|
||||
public function setFlag($flag, $value) {
|
||||
// Throw if flag does not exist
|
||||
if(!in_array($flag, array_keys($this->flags))) {
|
||||
throw new \Exception('Invalid flag.', self::ERR_INVALID_FLAG);
|
||||
}
|
||||
|
||||
// Set flag value by name
|
||||
$this->flags[$flag] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get flag value.
|
||||
*
|
||||
* @param string $flag Name of the flag to get.
|
||||
* @return boolean|null
|
||||
*/
|
||||
public function getFlag($flag) {
|
||||
return in_array($flag, array_keys($this->flags)) ? $this->flags[$flag] : null;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Loaders
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -118,70 +161,66 @@ class SimpleImage {
|
|||
* Loads an image from a file.
|
||||
*
|
||||
* @param string $file The image file to load.
|
||||
* @param boolean $sslVerify Set to false to skip SSL validation.
|
||||
* @throws \Exception Thrown if file or image data is invalid.
|
||||
* @return \claviska\SimpleImage
|
||||
*/
|
||||
public function fromFile($file) {
|
||||
// Check if the file exists and is readable. We're using fopen() instead of file_exists()
|
||||
// because not all URL wrappers support the latter.
|
||||
$handle = @fopen($file, 'r');
|
||||
if($handle === false) {
|
||||
// Set fopen options.
|
||||
$sslVerify = $this->getFlag("sslVerify"); // Don't perform peer validation when true
|
||||
$opts = [
|
||||
"ssl" => [
|
||||
"verify_peer" => $sslVerify,
|
||||
"verify_peer_name" => $sslVerify
|
||||
]
|
||||
];
|
||||
|
||||
// Check if the file exists and is readable.
|
||||
$file = @file_get_contents($file, false, stream_context_create($opts));
|
||||
if($file === false) {
|
||||
throw new \Exception("File not found: $file", self::ERR_FILE_NOT_FOUND);
|
||||
}
|
||||
fclose($handle);
|
||||
|
||||
// Create image object from string
|
||||
$this->image = imagecreatefromstring($file);
|
||||
|
||||
// Get image info
|
||||
$info = @getimagesize($file);
|
||||
$info = @getimagesizefromstring($file);
|
||||
if($info === false) {
|
||||
throw new \Exception("Invalid image file: $file", self::ERR_INVALID_IMAGE);
|
||||
}
|
||||
$this->mimeType = $info['mime'];
|
||||
|
||||
// Create image object from file
|
||||
switch($this->mimeType) {
|
||||
case 'image/gif':
|
||||
// Load the gif
|
||||
$gif = imagecreatefromgif($file);
|
||||
if($gif) {
|
||||
// Copy the gif over to a true color image to preserve its transparency. This is a
|
||||
// workaround to prevent imagepalettetruecolor() from borking transparency.
|
||||
$width = imagesx($gif);
|
||||
$height = imagesy($gif);
|
||||
$this->image = imagecreatetruecolor($width, $height);
|
||||
$transparentColor = imagecolorallocatealpha($this->image, 0, 0, 0, 127);
|
||||
imagecolortransparent($this->image, $transparentColor);
|
||||
imagefill($this->image, 0, 0, $transparentColor);
|
||||
imagecopy($this->image, $gif, 0, 0, 0, 0, $width, $height);
|
||||
imagedestroy($gif);
|
||||
}
|
||||
break;
|
||||
case 'image/jpeg':
|
||||
$this->image = imagecreatefromjpeg($file);
|
||||
break;
|
||||
case 'image/png':
|
||||
$this->image = imagecreatefrompng($file);
|
||||
break;
|
||||
case 'image/webp':
|
||||
$this->image = imagecreatefromwebp($file);
|
||||
break;
|
||||
case 'image/bmp':
|
||||
case 'image/x-ms-bmp':
|
||||
case 'image/x-windows-bmp':
|
||||
$this->image = imagecreatefrombmp($file);
|
||||
break;
|
||||
}
|
||||
if(!$this->image) {
|
||||
throw new \Exception("Unsupported format: " . $this->mimeType, self::ERR_UNSUPPORTED_FORMAT);
|
||||
}
|
||||
|
||||
switch($this->mimeType) {
|
||||
case 'image/gif':
|
||||
// Copy the gif over to a true color image to preserve its transparency. This is a
|
||||
// workaround to prevent imagepalettetotruecolor() from borking transparency.
|
||||
$width = imagesx($this->image);
|
||||
$height = imagesx($this->image);
|
||||
|
||||
$gif = imagecreatetruecolor((int) $width, (int) $height);
|
||||
$alpha = imagecolorallocatealpha($gif, 0, 0, 0, 127);
|
||||
imagecolortransparent($gif, $alpha);
|
||||
imagefill($gif, 0, 0, $alpha);
|
||||
|
||||
imagecopy($this->image, $gif, 0, 0, 0, 0, $width, $height);
|
||||
imagedestroy($gif);
|
||||
break;
|
||||
case 'image/jpeg':
|
||||
// Load exif data from JPEG images
|
||||
if(function_exists('exif_read_data')) {
|
||||
$this->exif = @exif_read_data("data://image/jpeg;base64," . base64_encode($file));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Convert pallete images to true color images
|
||||
imagepalettetotruecolor($this->image);
|
||||
|
||||
// Load exif data from JPEG images
|
||||
if($this->mimeType === 'image/jpeg' && function_exists('exif_read_data')) {
|
||||
$this->exif = @exif_read_data($file);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -194,7 +233,7 @@ class SimpleImage {
|
|||
* @return \claviska\SimpleImage
|
||||
*/
|
||||
public function fromNew($width, $height, $color = 'transparent') {
|
||||
$this->image = imagecreatetruecolor($width, $height);
|
||||
$this->image = imagecreatetruecolor((int) $width, (int) $height);
|
||||
|
||||
// Use PNG for dynamically created images because it's lossless and supports transparency
|
||||
$this->mimeType = 'image/png';
|
||||
|
@ -490,7 +529,7 @@ class SimpleImage {
|
|||
imagefilter($srcIm, IMG_FILTER_COLORIZE, 0, 0, 0, 127 * ((100 - $pct) / 100));
|
||||
}
|
||||
|
||||
imagecopy($dstIm, $srcIm, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH);
|
||||
imagecopy($dstIm, $srcIm, (int) $dstX, (int) $dstY, (int) $srcX, (int) $srcY, (int) $srcW, (int) $srcH);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -593,7 +632,7 @@ class SimpleImage {
|
|||
// Avoid using native imagecrop() because of a bug with PNG transparency
|
||||
$dstW = abs($x2 - $x1);
|
||||
$dstH = abs($y2 - $y1);
|
||||
$newImage = imagecreatetruecolor($dstW, $dstH);
|
||||
$newImage = imagecreatetruecolor((int) $dstW, (int) $dstH);
|
||||
$transparentColor = imagecolorallocatealpha($newImage, 0, 0, 0, 127);
|
||||
imagecolortransparent($newImage, $transparentColor);
|
||||
imagefill($newImage, 0, 0, $transparentColor);
|
||||
|
@ -603,10 +642,10 @@ class SimpleImage {
|
|||
$newImage,
|
||||
$this->image,
|
||||
0, 0, min($x1, $x2), min($y1, $y2),
|
||||
$dstW,
|
||||
$dstH,
|
||||
$dstW,
|
||||
$dstH
|
||||
(int) $dstW,
|
||||
(int) $dstH,
|
||||
(int) $dstW,
|
||||
(int) $dstH
|
||||
);
|
||||
|
||||
// Swap out the new image
|
||||
|
@ -802,7 +841,7 @@ class SimpleImage {
|
|||
// We can't use imagescale because it doesn't seem to preserve transparency properly. The
|
||||
// workaround is to create a new truecolor image, allocate a transparent color, and copy the
|
||||
// image over to it using imagecopyresampled.
|
||||
$newImage = imagecreatetruecolor($width, $height);
|
||||
$newImage = imagecreatetruecolor((int) $width, (int) $height);
|
||||
$transparentColor = imagecolorallocatealpha($newImage, 0, 0, 0, 127);
|
||||
imagecolortransparent($newImage, $transparentColor);
|
||||
imagefill($newImage, 0, 0, $transparentColor);
|
||||
|
@ -810,8 +849,8 @@ class SimpleImage {
|
|||
$newImage,
|
||||
$this->image,
|
||||
0, 0, 0, 0,
|
||||
$width,
|
||||
$height,
|
||||
(int) $width,
|
||||
(int) $height,
|
||||
$this->getWidth(),
|
||||
$this->getHeight()
|
||||
);
|
||||
|
@ -1885,7 +1924,7 @@ class SimpleImage {
|
|||
$color['red'],
|
||||
$color['green'],
|
||||
$color['blue'],
|
||||
127 - ($color['alpha'] * 127)
|
||||
(int) (127 - ($color['alpha'] * 127))
|
||||
);
|
||||
if($index > -1) {
|
||||
// Yes, return this color index
|
||||
|
|
13
bl-plugins/twitter-cards/languages/cs_CZ.json
Normal file
13
bl-plugins/twitter-cards/languages/cs_CZ.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"plugin-data":
|
||||
{
|
||||
"name": "Twitter Cards",
|
||||
"description": "With Twitter Cards, you can attach rich photos, videos and media experiences to Tweets, helping to drive traffic to your website."
|
||||
},
|
||||
"default-image": "Výchozí obrázek",
|
||||
"twitter-site-profile": "Profil stránky na Twitteru",
|
||||
"twitter-author-profile": "Profil autora příspěvku na Twitteru",
|
||||
"minimum-image-dimensions": "Minimální rozměry obrázku jsou 300x157px a maximum 4096x4096px.",
|
||||
"image-must-be-less": "Obrázek musí být menší než 5MB.",
|
||||
"formats-are-supported": "Jsou podporovány formáty pouze JPG, PNG, WEBP a GIF."
|
||||
}
|
|
@ -4,5 +4,10 @@
|
|||
"name": "Twitter Cards",
|
||||
"description": "With Twitter Cards, you can attach rich photos, videos and media experiences to Tweets, helping to drive traffic to your website."
|
||||
},
|
||||
"default-image": "Default image"
|
||||
}
|
||||
"default-image": "Default image",
|
||||
"twitter-site-profile": "Twitter site profile",
|
||||
"twitter-author-profile": "Twitter author profile",
|
||||
"minimum-image-dimensions": "The minimum image dimensions are 300x157px and the maximum 4096x4096px.",
|
||||
"image-must-be-less": "Image must be less than 5MB in size.",
|
||||
"formats-are-supported": "JPG, PNG, WEBP and GIF formats are supported."
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
"email": "",
|
||||
"website": "https://plugins.bludit.com",
|
||||
"version": "4.0.0",
|
||||
"releaseDate": "2021-05-23",
|
||||
"releaseDate": "2022-10-01",
|
||||
"license": "MIT",
|
||||
"compatible": "4.0.0",
|
||||
"notes": ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@ class pluginTwitterCards extends Plugin {
|
|||
{
|
||||
// Fields and default values for the database of this plugin
|
||||
$this->dbFields = array(
|
||||
'defaultImage'=>''
|
||||
'defaultImage' => '',
|
||||
'twitterSite' => '',
|
||||
'twitterCreator' => ''
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -14,9 +16,24 @@ class pluginTwitterCards extends Plugin {
|
|||
{
|
||||
global $L;
|
||||
|
||||
$html = '<div>';
|
||||
$html = '<div class="alert alert-primary" role="alert">';
|
||||
$html .= $this->description();
|
||||
$html .= '</div>';
|
||||
|
||||
$html .= '<div>';
|
||||
$html .= '<label>'.$L->get('Default image').'</label>';
|
||||
$html .= '<input id="jsdefaultImage" name="defaultImage" type="text" value="'.$this->getValue('defaultImage').'" placeholder="https://">';
|
||||
$html .= '<p class="text-muted small">' . $L->get('minimum-image-dimensions') . ' ' . $L->get('image-must-be-less') . ' ' . $L->get('formats-are-supported') . '</p>';
|
||||
$html .= '</div>';
|
||||
|
||||
$html .= '<div>';
|
||||
$html .= '<label>'.$L->get('Twitter site profile').'</label>';
|
||||
$html .= '<input id="jstwitterSite" name="twitterSite" type="text" value="'.$this->getValue('twitterSite').'" placeholder="@yourSiteProfile">';
|
||||
$html .= '</div>';
|
||||
|
||||
$html .= '<div>';
|
||||
$html .= '<label>'.$L->get('Twitter author profile').'</label>';
|
||||
$html .= '<input id="jstwitterCreator" name="twitterCreator" type="text" value="'.$this->getValue('twitterCreator').'" placeholder="@authorProfile">';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
|
@ -31,19 +48,20 @@ class pluginTwitterCards extends Plugin {
|
|||
global $page;
|
||||
|
||||
$data = array(
|
||||
'card' =>'summary',
|
||||
'site' =>'',
|
||||
'title' =>$site->title(),
|
||||
'description' =>$site->description(),
|
||||
'image' =>''
|
||||
'card' => 'summary_large_image',
|
||||
'twitterSite' => $this->getValue('twitterSite'),
|
||||
'twitterCreator' => $this->getValue('twitterCreator'),
|
||||
'title' => $site->title(),
|
||||
'description' => $site->description(),
|
||||
'image' => ''
|
||||
);
|
||||
|
||||
switch($WHERE_AM_I) {
|
||||
switch( $WHERE_AM_I ) {
|
||||
// The user filter by page
|
||||
case 'page':
|
||||
$data['title'] = $page->title();
|
||||
$data['description'] = $page->description();
|
||||
$data['image'] = $page->coverImage($absolute=true);
|
||||
$data['title'] = $page->title();
|
||||
$data['description'] = $page->description();
|
||||
$data['image'] = $page->coverImage( $absolute = true );
|
||||
|
||||
$pageContent = $page->content();
|
||||
break;
|
||||
|
@ -53,32 +71,75 @@ class pluginTwitterCards extends Plugin {
|
|||
$pageContent = '';
|
||||
// The image it's from the first page
|
||||
if(isset($content[0]) ) {
|
||||
$data['image'] = $content[0]->coverImage($absolute=true);
|
||||
$data['image'] = $content[0]->coverImage( $absolute = true );
|
||||
$pageContent = $content[0]->content();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$html = PHP_EOL.'<!-- Twitter Cards -->'.PHP_EOL;
|
||||
$html .= '<meta property="twitter:card" content="'.$data['card'].'">'.PHP_EOL;
|
||||
$html .= '<meta property="twitter:site" content="'.$data['site'].'">'.PHP_EOL;
|
||||
$html .= '<meta property="twitter:title" content="'.$data['title'].'">'.PHP_EOL;
|
||||
$html .= '<meta property="twitter:description" content="'.$data['description'].'">'.PHP_EOL;
|
||||
$html .= '<meta name="twitter:card" content="' . $data['card'] . '">'.PHP_EOL;
|
||||
$html .= '<meta name="twitter:site" content="' . $data['site'] . '">'.PHP_EOL;
|
||||
$html .= '<meta name="twitter:title" content="' . $data['title'] . '">'.PHP_EOL;
|
||||
$html .= '<meta name="twitter:creator" content="' . $data['twitterCreator'] . '">'.PHP_EOL;
|
||||
// If the page doesn't have a description try to get excerpt from content
|
||||
if( empty( $data['description'] ) )
|
||||
{
|
||||
$data['description'] = $this->content_excerpt( $pageContent , 150, '...');
|
||||
}
|
||||
$html .= '<meta name="twitter:description" content="' . $data['description'] . '">'.PHP_EOL;
|
||||
|
||||
// If the page doesn't have a coverImage try to get an image from the HTML content
|
||||
if( empty($data['image']) ) {
|
||||
if( empty( $data['image'] ) ) {
|
||||
// Get the image from the content
|
||||
$src = DOM::getFirstImage($pageContent);
|
||||
if ($src!==false) {
|
||||
$src = DOM::getFirstImage( $pageContent );
|
||||
if ( $src !== false ) {
|
||||
$data['image'] = $src;
|
||||
} else {
|
||||
if (Text::isNotEmpty($this->getValue('defaultImage'))) {
|
||||
if ( Text::isNotEmpty( $this->getValue('defaultImage') ) ) {
|
||||
$data['image'] = $this->getValue('defaultImage');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$html .= '<meta property="twitter:image" content="'.$data['image'].'">'.PHP_EOL;
|
||||
$html .= '<meta name="twitter:image" content="'.$data['image'].'">'.PHP_EOL;
|
||||
$html .= '<!-- /Twitter Cards -->'.PHP_EOL.PHP_EOL;
|
||||
|
||||
unset( $pageContent );
|
||||
unset( $data );
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
/** Return excerpt from full content of post
|
||||
*
|
||||
* @param string $str Post content
|
||||
* @param int $n Number of characters
|
||||
* @param string $endChar End char append to after excerpt (default "...")
|
||||
* @return string
|
||||
*/
|
||||
private function content_excerpt( string $str, int $n = 500, string $endChar = '…' ): string
|
||||
{
|
||||
$str = strip_tags( $str );
|
||||
if ( mb_strlen( $str ) < $n )
|
||||
{
|
||||
return $str;
|
||||
}
|
||||
$str = preg_replace('/ {2,}/', ' ', str_replace(["\r", "\n", "\t", "\x0B", "\x0C"], ' ', $str));
|
||||
if ( mb_strlen( $str ) <= $n )
|
||||
{
|
||||
return $str;
|
||||
}
|
||||
$out = '';
|
||||
foreach ( explode( ' ', trim( $str ) ) as $val )
|
||||
{
|
||||
$out .= $val . ' ';
|
||||
if ( mb_strlen( $out ) >= $n )
|
||||
{
|
||||
$out = trim( $out );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ( mb_strlen( $out ) === mb_strlen( $str ) ) ? $out : $out . $endChar;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -724,7 +724,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
|||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>' . $error . '</th>
|
||||
<th>' . $L->get( $error ) . '</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
Loading…
Add table
Reference in a new issue