Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

+16 -158
View File
@@ -11,7 +11,7 @@
namespace IPS\Member;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,98 +23,19 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
class _LetterPhoto
{
/**
* @brief File storage class to use
* @brief Member name
*/
protected $fileStorageClass = 'core_Profile';
/**
* @brief Member object
*/
protected $member = NULL;
/**
* @brief Text size
*/
protected $textSize = 75;
protected $memberName = NULL;
/**
* Create a new photo object
*
* @param \IPS\Member $member Member object
* @param string $name Member name
* @return void
*/
public function __construct( $member )
public function __construct( $name )
{
$this->member = $member;
}
/**
* Create the photo
*
* @param int $maxWidth Max width
* @param int $maxHeight Max height
* @param int $letterCount How many letters to use
* @return \IPS\Http\Url|NULL
*/
public function create( $maxWidth, $maxHeight, $letterCount=1 )
{
/* If we don't have any sizes, we can't generate a proper image */
if( !$maxWidth OR !$maxHeight )
{
return NULL;
}
/* Set the font size to 1/2 of the $maxWidth and $maxHeight (which should be the same value) */
$this->textSize = ( ( $maxWidth / 2 ) / $letterCount );
/* If we don't have a name, there's nothing to create */
if( !$this->member->name )
{
return NULL;
}
/* Get the first character of the name...if we can't detect it, there's again nothing to convert */
$letters = $this->getLetters( $letterCount );
if( $letters === NULL )
{
return NULL;
}
/* Now we have to generate the background color we will be using */
$rgbColor = $this->generateColorCode();
/* Create the image */
$image = \IPS\Image::newImageCanvas( $maxWidth, $maxHeight, $rgbColor );
/* Draw the text on the image */
$image->write( $letters, $this->getFont( $letters ), $this->textSize );
/* Save the image and return it */
try
{
return \IPS\File::create( $this->fileStorageClass, $letters . '_member_' . $this->member->member_id . '.png', (string) $image, NULL, TRUE, NULL, FALSE );
}
catch( \Exception $e )
{
\IPS\Log::debug( $e, 'letter_photo' );
return NULL;
}
}
/**
* Return the first X non-punctuation characters of the name
*
* @param int $letters Number of letters to return
* @return string|NULL
*/
protected function getLetters( $letters=1 )
{
$name = str_replace( array( '<', '>', '=', '-', '+', '"', "'" ), '', $this->member->name );
$name = preg_replace( "/(\pP)+/u", '', trim( $name ) );
return $name ? mb_strtoupper( mb_substr( $name, 0, $letters ) ) : NULL;
$this->memberName = $name;
}
/**
@@ -133,9 +54,9 @@ class _LetterPhoto
protected static $lastHue = NULL;
/**
* Return a unique color code based on the name.
* Return a unique hex color code based on the name.
*
* @return array (RGB value)
* @return string
*/
public function generateColorCode()
{
@@ -151,16 +72,16 @@ class _LetterPhoto
static::$lastHue = $hue;
return $this->convertHsvToRgb( $hue, $this->colorCodeSaturation, $this->colorCodeValue );
return $this->convertRgbToHex( $this->convertHsvToRgb( $hue, $this->colorCodeSaturation, $this->colorCodeValue ) );
}
$hue = ( ( ord( \mb_strtolower( $this->member->name ) ) - 97 ) / 25.0 ) + 0.25;
$hue = ( ( \ord( \mb_strtolower( $this->memberName ) ) - 97 ) / 25.0 ) + 0.25;
$hue *= 1.61803398875;
$hue *= (float) ( '1.' . rand() ) / 1;
if( rand( 0, 1 ) )
{
$float = (float) ( "1." . ord( array_rand( range( 'a', 'z' ) ) ) );
$float = (float) ( "1." . \ord( array_rand( range( 'a', 'z' ) ) ) );
$hue = abs( $float - $hue );
}
@@ -171,7 +92,7 @@ class _LetterPhoto
static::$lastHue = $hue;
return $this->convertHsvToRgb( $hue, $this->colorCodeSaturation, $this->colorCodeValue );
return $this->convertRgbToHex( $this->convertHsvToRgb( $hue, $this->colorCodeSaturation, $this->colorCodeValue ) );
}
/**
@@ -229,76 +150,13 @@ class _LetterPhoto
}
/**
* Return a font file path to use
* Convert an RGB color value to hex
*
* @param string $string String we are going to write
* @param array $rgb RGB color values
* @return string
*/
protected function getFont( $string='' )
protected function convertRgbToHex( array $rgb )
{
$codePointMap = array(
'NotoSansArmenian-Regular.ttf' => array( 0x0530, 0x058F ),
'NotoSansHebrew-Regular.ttf' => array( 0x0590, 0x05FF ),
'NotoNaskhArabic-Regular.ttf' => array( 0x0600, 0x06FF ),
'NotoSansGeorgian-Regular.ttf' => array( 0x10A0, 0x10FF ),
'NotoSansThai-Regular.ttf' => array( 0x0E00, 0x0E7F ),
'NotoSansDevanagari-Regular.ttf' => array( 0x0900, 0x097F ),
'BMDOHYEON.ttf' => array(
array( 0xAC00, 0xD7A3 ),
array( 0x1100, 0x11FF ),
array( 0x3130, 0x318F ),
array( 0xA960, 0xA97F ),
array( 0xD7B0, 0xD7FF )
),
'HanaMinA.ttf' => array(
array( 0x4E00, 0x9FFF ),
array( 0x3400, 0x4DB5 ),
array( 0x3040, 0x309F ),
array( 0x30A0, 0x30FF ),
array( 0xFF00, 0xFFEF ),
array( 0xF900, 0xFAD9 ),
array( 0x20000, 0x2A6D6 ),
array( 0x2A700, 0x2B734 ),
array( 0x2B740, 0x2B81D ),
array( 0x2B820, 0x2CEA1 ),
array( 0x2F800, 0x2FA1D )
),
);
/* Get all characters */
$characters = preg_split( '//u', $string, null, PREG_SPLIT_NO_EMPTY );
/* Loop over all characters. If any character is in a range defined above, use that font.
Technically you could have a Korean character and an Arabic character in the same string, but the probability of that occurring
is sufficiently rare that we will use the first font defined above which support latin ranges already */
foreach( $characters as $character )
{
$decValue = unpack( 'N', mb_convert_encoding( $character, 'UCS-4BE', 'UTF-8' ) );
$decValue = $decValue[1];
foreach( $codePointMap as $fontFile => $range )
{
if( is_array( $range[0] ) )
{
foreach( $range as $subRange )
{
if( $decValue > ( $subRange[0] ) AND $decValue < ( $subRange[1] ) )
{
return \IPS\ROOT_PATH . '/system/3rd_party/Fonts/' . $fontFile;
}
}
}
else
{
if( $decValue > ( $range[0] ) AND $decValue < ( $range[1] ) )
{
return \IPS\ROOT_PATH . '/system/3rd_party/Fonts/' . $fontFile;
}
}
}
}
/* Fallback for the majority of languages */
return \IPS\ROOT_PATH . '/system/3rd_party/Fonts/NotoSans-Regular.ttf';
return sprintf( "%02x%02x%02x", $rgb[0], $rgb[1], $rgb[2] );
}
}