Skip to content

Commit

Permalink
Updated to AppGini 24.13
Browse files Browse the repository at this point in the history
  • Loading branch information
bigprof committed May 20, 2024
1 parent 57b46bc commit c5e1cf5
Show file tree
Hide file tree
Showing 23 changed files with 687 additions and 250 deletions.
131 changes: 13 additions & 118 deletions app/admin/incFunctions.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,121 +231,14 @@ function getThumbnailSpecs($tableName, $fieldName, $view) {
return FALSE;
}
########################################################################
/**
* Alias for `Thumbnail::create()`. Create a thumbnail of an image. The thumbnail is saved in the same directory as the original image, with the same name, suffixed with `$specs['identifier']`
* @param string $img - path to image file
* @param array $specs - array with thumbnail specs as returned by getThumbnailSpecs()
* @return bool - true on success, false on failure
*/
function createThumbnail($img, $specs) {
$w = $specs['width'];
$h = $specs['height'];
$id = $specs['identifier'];
$path = dirname($img);

// image doesn't exist or inaccessible?
// known issue: for webp files, requires PHP 7.1+
if(!$size = @getimagesize($img)) return false;

// calculate thumbnail size to maintain aspect ratio
$ow = $size[0]; // original image width
$oh = $size[1]; // original image height
$twbh = $h / $oh * $ow; // calculated thumbnail width based on given height
$thbw = $w / $ow * $oh; // calculated thumbnail height based on given width
if($w && $h) {
if($twbh > $w) $h = $thbw;
if($thbw > $h) $w = $twbh;
} elseif($w) {
$h = $thbw;
} elseif($h) {
$w = $twbh;
} else {
return false;
}

// dir not writeable?
if(!is_writable($path)) return false;

// GD lib not loaded?
if(!function_exists('gd_info')) return false;
$gd = gd_info();

// GD lib older than 2.0?
preg_match('/\d/', $gd['GD Version'], $gdm);
if($gdm[0] < 2) return false;

// get file extension
preg_match('/\.[a-zA-Z]{3,4}$/U', $img, $matches);
$ext = strtolower($matches[0]);

// check if supplied image is supported and specify actions based on file type
if($ext == '.gif') {
if(!$gd['GIF Create Support']) return false;
$thumbFunc = 'imagegif';
} elseif($ext == '.png') {
if(!$gd['PNG Support']) return false;
$thumbFunc = 'imagepng';
} elseif($ext == '.webp') {
if(!$gd['WebP Support'] && !$gd['WEBP Support']) return false;
$thumbFunc = 'imagewebp';
} elseif($ext == '.jpg' || $ext == '.jpe' || $ext == '.jpeg') {
if(!$gd['JPG Support'] && !$gd['JPEG Support']) return false;
$thumbFunc = 'imagejpeg';
} else {
return false;
}

// determine thumbnail file name
$ext = $matches[0];
$thumb = substr($img, 0, -5) . str_replace($ext, $id . $ext, substr($img, -5));

// if the original image smaller than thumb, then just copy it to thumb
if($h > $oh && $w > $ow) {
return (@copy($img, $thumb) ? true : false);
}

// get image data
if(
$thumbFunc == 'imagewebp'
&& !$imgData = imagecreatefromwebp($img)
)
return false;
elseif(!$imgData = imagecreatefromstring(file_get_contents($img)))
return false;

// finally, create thumbnail
$thumbData = imagecreatetruecolor($w, $h);

//preserve transparency of png and gif images
$transIndex = null;
if($thumbFunc == 'imagepng' || $thumbFunc == 'imagewebp') {
if(($clr = @imagecolorallocate($thumbData, 0, 0, 0)) != -1) {
@imagecolortransparent($thumbData, $clr);
@imagealphablending($thumbData, false);
@imagesavealpha($thumbData, true);
}
} elseif($thumbFunc == 'imagegif') {
@imagealphablending($thumbData, false);
$transIndex = imagecolortransparent($imgData);
if($transIndex >= 0) {
$transClr = imagecolorsforindex($imgData, $transIndex);
$transIndex = imagecolorallocatealpha($thumbData, $transClr['red'], $transClr['green'], $transClr['blue'], 127);
imagefill($thumbData, 0, 0, $transIndex);
}
}

// resize original image into thumbnail
if(!imagecopyresampled($thumbData, $imgData, 0, 0 , 0, 0, $w, $h, $ow, $oh)) return false;
unset($imgData);

// gif transparency
if($thumbFunc == 'imagegif' && $transIndex >= 0) {
imagecolortransparent($thumbData, $transIndex);
for($y = 0; $y < $h; ++$y)
for($x = 0; $x < $w; ++$x)
if(((imagecolorat($thumbData, $x, $y) >> 24) & 0x7F) >= 100) imagesetpixel($thumbData, $x, $y, $transIndex);
imagetruecolortopalette($thumbData, true, 255);
imagesavealpha($thumbData, false);
}

if(!$thumbFunc($thumbData, $thumb)) return false;
unset($thumbData);

return true;
return Thumbnail::create($img, $specs);
}
########################################################################
function formatUri($uri) {
Expand Down Expand Up @@ -414,6 +307,8 @@ function openDBConnection(&$o) {

if($connected) return $db_link;

global $Translation;

/****** Check that MySQL module is enabled ******/
if(!extension_loaded('mysql') && !extension_loaded('mysqli')) {
$o['error'] = 'PHP is not configured to connect to MySQL on this machine. Please see <a href="https://www.php.net/manual/en/ref.mysql.php">this page</a> for help on how to configure MySQL.';
Expand All @@ -427,15 +322,15 @@ function openDBConnection(&$o) {
$o['error'] = db_error($db_link, true);
if(!empty($o['silentErrors'])) return false;

dieErrorPage($o['error']);
dieErrorPage($o['error'] ? $o['error'] : $Translation['no db connection']);
}

/****** Select DB ********/
if(!db_select_db($dbDatabase, $db_link)) {
$o['error'] = db_error($db_link);
if(!empty($o['silentErrors'])) return false;

dieErrorPage($o['error']);
dieErrorPage(str_replace('<DBName>', '****', $Translation['no db name']));
}

$connected = true;
Expand Down Expand Up @@ -1536,7 +1431,7 @@ function get_table_fields($tn = null) {
'appgini' => "VARCHAR(40) NULL",
'info' => [
'caption' => 'Cover photo',
'description' => 'Maximum file size allowed: 2000 KB.<br>Allowed file types: jpg, jpeg, gif, png',
'description' => 'Maximum file size allowed: 2000 KB.<br>Allowed file types: jpg, jpeg, gif, png, webp',
],
],
'type' => [
Expand Down Expand Up @@ -2612,7 +2507,7 @@ function get_group_id($user = null) {
*
* @param [in] $set_array Assoc array of field names => values
* @param [in] $glue optional glue. Set to ' AND ' or ' OR ' if preparing a WHERE clause, or to ',' (default) for a SET clause
* @return SET string
* @return string containing the prepared SET or WHERE clause
*/
function prepare_sql_set($set_array, $glue = ', ') {
$fnvs = [];
Expand Down
2 changes: 2 additions & 0 deletions app/admin/pageInstallPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,8 @@ function missingDependencies() {
'cURL extension not enabled' => function_exists('curl_init'),
// 'plugins' folder is writable
'Plugins folder not writable' => is_writable($pluginsFolder),
// allow_url_fopen is enabled
'allow_url_fopen is disabled in php.ini' => ini_get('allow_url_fopen') == 1,
];

// if all dependencies are met, return false
Expand Down
33 changes: 22 additions & 11 deletions app/admin/pageServerStatus.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
$appgini_version = '24.11.1591';
$generated_ts = '24/03/2024 16:10:47';
$appgini_version = '24.13.1629';
$generated_ts = '20/05/2024 21:55:41';

require(__DIR__ . '/incCommon.php');

Expand Down Expand Up @@ -89,7 +89,7 @@
<hr>

<div class="row">
<div class="col-lg-4">
<div class="col-lg-3">
<h3><?php echo $Translation['uploads info']; ?></h3>
<span class="label label-info big-number">
<?php echo $num_uploads; ?>
Expand Down Expand Up @@ -125,8 +125,8 @@
<hr>
</div>

<div class="col-lg-4">
<h3><?php echo $Translation['db status']; ?></h3>
<div class="col-lg-3">
<h3><?php echo $Translation['db server status']; ?></h3>
<div class="db-status scrollable">
<pre>SHOW STATUS; SHOW VARIABLES;</pre>
<table class="table table-striped table-hover table-bordered">
Expand All @@ -141,7 +141,18 @@
<hr>
</div>

<div class="col-lg-4" id="phpinfo">
<div class="col-lg-3">
<h3><?php echo $Translation['db client status']; ?></h3>
<div class="db-status scrollable">
<pre><?php print_r(db_link()); ?></pre>
</div>
<h3><?php echo $Translation['date and time info']; ?></h3>
<div class="db-status scrollable">
<pre><?php echo date('Y-m-d H:i:s T') . "\n" . gmdate('Y-m-d H:i:s T'); ?></pre>
</div>
</div>

<div class="col-lg-3" id="phpinfo">
<h3><?php echo $Translation['php info']; ?></h3>
<div class="db-status scrollable">
<?php echo $phpinfo[0]; ?>
Expand Down Expand Up @@ -182,10 +193,10 @@
<script>
$j(function() {
// apply a zoom-in button to each grid cell
$j('<i class="glyphicon glyphicon-zoom-in resizer text-primary hspacer-sm cursor-pointer"></i>').prependTo('.col-lg-4 > h3:first-child');
$j('<i class="glyphicon glyphicon-zoom-in resizer text-primary hspacer-sm cursor-pointer"></i>').prependTo('.col-lg-3 > h3:first-child');

// and for every zoom-in button, add a class 'zoomable-cell' to its grid cell
$j('.resizer').parents('.col-lg-4').addClass('zoomable-cell');
$j('.resizer').parents('.col-lg-3').addClass('zoomable-cell');

// on clicking a zoom button, maximize/restore its parent grid cell
$j('.row').on('click', '.resizer', function() {
Expand All @@ -194,15 +205,15 @@
maximized = cell.hasClass('col-lg-12');

toggler.toggleClass('glyphicon-zoom-in glyphicon-zoom-out');
cell.toggleClass('col-lg-12 col-lg-4');
cell.toggleClass('col-lg-12 col-lg-3');
cell.children('.db-status').toggleClass('scrollable')

if(maximized) {
// restore default size
cell.parents('.row').children('.col-lg-4').removeClass('hidden');
cell.parents('.row').children('.col-lg-3').removeClass('hidden');
} else {
// otherwise, maximize
cell.parents('.row').children('.col-lg-4').addClass('hidden');
cell.parents('.row').children('.col-lg-3').addClass('hidden');
}
})
})
Expand Down
53 changes: 38 additions & 15 deletions app/common.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var AppGini = AppGini || {};

AppGini.version = 24.11;
AppGini.version = 24.13;

/* initials and fixes */
jQuery(function() {
Expand Down Expand Up @@ -157,21 +157,9 @@ jQuery(function() {
// format .locale-int and .locale-float numbers
// to stop it, set AppGini.noLocaleFormatting to true in a hook script in footer-extras.php, .. etc
if(!AppGini.noLocaleFormatting) setInterval(() => {
$j('.locale-int').each(function() {
$j('.locale-int, .locale-float').each(function() {
let i = $j(this).text().trim();
if(!/^\d+(\.\d+)?$/.test(i)) return; // already formatted or invalid number

$j(this).text(parseInt(i).toLocaleString());
})

$j('.locale-float').each(function() {
let f = $j(this).text().trim();
if(!/^\d+(\.\d+)?$/.test(f)) return; // already formatted or invalid number

// preserve decimals
const countDecimals = (f.split('.')[1] || '').length;

$j(this).text(parseFloat(f).toLocaleString(undefined, {minimumFractionDigits: countDecimals, maximumFractionDigits: countDecimals}));
$j(this).text(AppGini.localeFormat(i, $j(this).hasClass('locale-int')));
})
}, 100);

Expand Down Expand Up @@ -2597,3 +2585,38 @@ AppGini.htmlEntitiesToText = (html) => {
txt.innerHTML = html;
return txt.value;
}

AppGini.localeFormat = (num, isInt, locale) => {
// ensure num is a string
num = num.toString();

// if num has no digits, return it as is
if (!num.match(/\d/)) {
return num;
}

// if isInt is not provided or not true, set as false
isInt = isInt === true;

// if locale not provided, default to current locale
locale = locale || navigator.language;

// decimal separator based on locale
const decimalSeparator = new Intl.NumberFormat(locale).format(1.1).replace(/\d/g, '');
// thousands separator based on locale
const thousandsSeparator = new Intl.NumberFormat(locale).format(11111).replace(/\d/g, '');

// if number is a raw number (e.g. 1234.5 or 12.34), format it based on locale
if (!isInt && num.indexOf(decimalSeparator) === -1) {
let lfn = new Intl.NumberFormat(locale).format(num);
return lfn === 'NaN' ? num : lfn;
}

// if number is already formatted in the locale, return it as is
if (num.indexOf(thousandsSeparator) !== -1) {
return num;
}

// return the number formatted in the locale
return new Intl.NumberFormat(locale).format(parseFloat(num.replace(decimalSeparator, '.')));
}
2 changes: 1 addition & 1 deletion app/datalist.php
Original file line number Diff line number Diff line change
Expand Up @@ -1148,7 +1148,7 @@ function Render() {
$this->HTML .= "</table></div>\n";

/* highlight quick search matches */
if(strlen($SearchString) && $RecordCount) $this->HTML .= '<script>$j(function() { $j(".table-responsive td:not([colspan])").mark("' . html_attr($SearchString) . '", { className: "text-bold bg-warning", diacritics: false }); })</script>';
if(strlen($SearchString) && $RecordCount) $this->HTML .= '<script>$j(function() { $j(".table_view .table-responsive td").mark("' . html_attr($SearchString) . '", { className: "text-bold bg-warning", diacritics: false }); })</script>';

if($Print_x == '' && $i) { // TV
$this->HTML .= '<div class="row pagination-section">';
Expand Down
5 changes: 5 additions & 0 deletions app/defaultLang.php
Original file line number Diff line number Diff line change
Expand Up @@ -875,4 +875,9 @@
'SQL' => 'SQL',
'click to copy' => 'Click to copy',
'copied' => 'Copied!',

// Added in 24.13
'db server status' => 'Database server status',
'db client status' => 'Database client status',
'date and time info' => 'Date and time info',
];
2 changes: 1 addition & 1 deletion app/definitions.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@define('SESSION_NAME', 'Rental_property_manager');
@define('APP_TITLE', 'Rental Property Manager');
@define('APP_DIR', __DIR__);
@define('APP_VERSION', '24.11');
@define('APP_VERSION', '24.13');
@define('maxSortBy', 4);
@define('empty_lookup_value', '{empty_value}');
@define('MULTIPLE_SUPER_ADMINS', false);
Expand Down
Loading

0 comments on commit c5e1cf5

Please sign in to comment.