// 5 START: Action — Generate Folder Images (overwrite) with GD/TTF, auto-detect size, text = Post Name “{Folder} Media”, refresh thumbnails function gmm_temp_action_generate_folder_images() { if (!current_user_can('manage_options')) { return 'Not allowed.'; } check_admin_referer('gmm_temp_gen_folder_images'); if (!extension_loaded('gd')) { return 'PHP GD extension is not available. Please enable GD or ask hosting support.'; } $root = get_option(GMM_TEMP_OPT_ROOT, ''); $real = $root ? realpath($root) : false; if (!$real || !is_dir($real)) { return 'Root path is not valid. Set it and save first.'; } $real = wp_normalize_path($real); // --- Detect target size (featured > large > fallback) --- $W = 0; $H = 0; if (isset($GLOBALS['_wp_additional_image_sizes']['post-thumbnail'])) { $sz = $GLOBALS['_wp_additional_image_sizes']['post-thumbnail']; $W = !empty($sz['width']) ? (int)$sz['width'] : 0; $H = !empty($sz['height']) ? (int)$sz['height'] : 0; } if ($W <= 0 || $H <= 0) { $W = (int) get_option('large_size_w', 0); $H = (int) get_option('large_size_h', 0); } if ($W <= 0 || $H <= 0) { $W = 1200; $H = 630; } // last resort // --- Find a TTF font (fallback to bitmap if none) --- $font_candidates = [ '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', '/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf', '/usr/share/fonts/truetype/freefont/FreeSansBold.ttf', '/Library/Fonts/Arial Bold.ttf', '/System/Library/Fonts/Supplemental/Arial Bold.ttf', 'C:\\Windows\\Fonts\\arialbd.ttf', ]; $FONT = ''; foreach ($font_candidates as $f) { if (is_file($f)) { $FONT = $f; break; } } $has_ttf = $FONT && function_exists('imagettfbbox') && function_exists('imagettftext'); // Helpers $draw_gradient = function(&$im, $w, $h, $hexTop, $hexBot) { $hex_to_rgb = function($hex){ $hex = ltrim($hex, '#'); return [hexdec(substr($hex,0,2)),hexdec(substr($hex,2,2)),hexdec(substr($hex,4,2))]; }; list($r1,$g1,$b1) = $hex_to_rgb($hexTop); list($r2,$g2,$b2) = $hex_to_rgb($hexBot); for ($y=0; $y<$h; $y++) { $t = $h>1 ? $y/($h-1) : 0; $r = (int) round($r1 + ($r2-$r1)*$t); $g = (int) round($g1 + ($g2-$g1)*$t); $b = (int) round($b1 + ($b2-$b1)*$t); $col = imagecolorallocate($im, $r, $g, $b); imageline($im, 0, $y, $w, $y, $col); } imagefilledrectangle($im, 0, (int)($h*0.72), $w, $h, imagecolorallocatealpha($im, 0,0,0,100)); }; $fit_text = function($title, $w, $h, $fontPath) { $padX = (int) round($w * 0.08); $padY = (int) round($h * 0.08); $boxW = $w - 2*$padX; $boxH = $h - 2*$padY; $measure = function($size, $txt) use ($fontPath) { $bb = imagettfbbox($size, 0, $fontPath, $txt); $width = abs($bb[2]-$bb[0]); $height = abs($bb[7]-$bb[1]); return [$width, $height]; }; $text = trim($title); $lines = [$text]; $maxSize = (int) max(18, min($boxH * 0.45, $boxW * 0.20)); $minSize = 14; $bestSize = $minSize; for ($s=$maxSize; $s>=$minSize; $s-=2) { list($tw,$th) = $measure($s, $text); if ($tw <= $boxW && $th <= $boxH*0.6) { $bestSize=$s; break; } } list($tw,$th) = $measure($bestSize, $text); if ($tw > $boxW && strpos($text,' ') !== false) { $parts = preg_split('~\s+~', $text); $N = count($parts); $mid = (int) floor($N/2); $candidates = []; for ($i=max(1,$mid-2); $i<=min($N-1,$mid+2); $i++) { $candidates[] = [implode(' ', array_slice($parts,0,$i)), implode(' ', array_slice($parts,$i))]; } $best = $candidates[0]; $bestDiff = PHP_INT_MAX; foreach ($candidates as $cand) { $d = abs(strlen($cand[0]) - strlen($cand[1])); if ($d < $bestDiff) { $bestDiff=$d; $best=$cand; } } $lines = [$best[0], $best[1]]; $maxSize2 = (int) max(18, min($boxH * 0.60, $boxW * 0.22)); $bestSize = $minSize; for ($s=$maxSize2; $s>=$minSize; $s-=2) { list($w1,$h1) = $measure($s, $lines[0]); list($w2,$h2) = $measure($s, $lines[1]); $totalH = $h1 + (int)($s*0.35) + $h2; if (max($w1,$w2) <= $boxW && $totalH <= $boxH) { $bestSize=$s; break; } } } return [$lines, $bestSize]; }; $created = 0; $refreshed = 0; $thumbs_set = 0; $errors = 0; $list = @scandir($real); if (!is_array($list)) { return 'Unable to read the root folder.'; } foreach ($list as $base) { if ($base === '.' || $base === '..' || $base[0] === '.') { continue; } $abs = wp_normalize_path($real.'/'.$base); if (!is_dir($abs)) { continue; } $slug = sanitize_title($base); $folder_title = ucwords(trim(preg_replace('~[_\-]+~', ' ', pathinfo($base, PATHINFO_FILENAME)))); $post_title = $folder_title . ' Media'; // <- use Post Name text $target_jpg = $abs.'/'.$slug.'.jpg'; // always (re)write .jpg // --- (Re)generate image file (overwrite) --- $im = imagecreatetruecolor($W, $H); if (!$im) { $errors++; continue; } // Gradient per folder (stable, varied) $seed = crc32($slug); $hue = $seed % 360; $toRgb = function($h,$s,$l){ $c = (1 - abs(2*$l - 1)) * $s; $x = $c * (1 - abs(fmod($h/60,2) - 1)); $m = $l - $c/2; switch (true) { case $h<60: list($r,$g,$b)=[$c,$x,0]; break; case $h<120: list($r,$g,$b)=[$x,$c,0]; break; case $h<180: list($r,$g,$b)=[0,$c,$x]; break; case $h<240: list($r,$g,$b)=[0,$x,$c]; break; case $h<300: list($r,$g,$b)=[$x,0,$c]; break; default: list($r,$g,$b)=[$c,0,$x]; break; } return [ (int)(($r+$m)*255), (int)(($g+$m)*255), (int)(($b+$m)*255) ]; }; list($r1,$g1,$b1) = $toRgb($hue, 0.55, 0.35); list($r2,$g2,$b2) = $toRgb(($hue+20)%360, 0.55, 0.55); $hexTop = sprintf('#%02x%02x%02x',$r1,$g1,$b1); $hexBot = sprintf('#%02x%02x%02x',$r2,$g2,$b2); $draw_gradient($im, $W, $H, $hexTop, $hexBot); if ($has_ttf) { list($lines, $size) = $fit_text($post_title, $W, $H, $FONT); $shadow = imagecolorallocatealpha($im, 0,0,0,60); $white = imagecolorallocate($im, 255,255,255); $measure = function($s,$t) use ($FONT) { $bb=imagettfbbox($s,0,$FONT,$t); return [abs($bb[2]-$bb[0]), abs($bb[7]-$bb[1])]; }; $gap = (int) ($size * 0.35); $heights = []; $widths = []; foreach ($lines as $ln) { list($w1,$h1) = $measure($size,$ln); $widths[]=$w1; $heights[]=$h1; } $totalH = array_sum($heights) + $gap * (count($lines)-1); $xCenter = (int) ($W / 2); $y = (int) (($H - $totalH) / 2); foreach ($lines as $idx => $ln) { list($wLine,$hLine) = $measure($size,$ln); $x = $xCenter - (int)($wLine/2); $y += $hLine; imagettftext($im, $size, 0, $x+2, $y+2, $shadow, $FONT, $ln); imagettftext($im, $size, 0, $x, $y, $white, $FONT, $ln); $y += $gap; } } else { // Bitmap fallback with contrast bar $barH = (int) max(24, $H * 0.18); $barY = (int) (($H - $barH) / 2); $bar = imagecolorallocatealpha($im, 0,0,0,80); imagefilledrectangle($im, 0, $barY, $W, $barY+$barH, $bar); $white = imagecolorallocate($im,255,255,255); $font = 5; $fw = imagefontwidth($font); $fh = imagefontheight($font); $tw = $fw * strlen($post_title); $x = max(6, (int)(($W - $tw) / 2)); $y = (int)(($H - $fh) / 2); imagestring($im, $font, $x, $y, $post_title, $white); } if (!@imagejpeg($im, $target_jpg, 88)) { $errors++; imagedestroy($im); continue; } @chmod($target_jpg, 0644); imagedestroy($im); $created++; // --- Refresh Media Library attachment & featured image --- // Find a post for this folder (if any) $meta_path = trailingslashit($abs); $existing_post = get_posts([ 'post_type' => 'post', 'post_status' => 'any', 'meta_key' => 'gmm_path', 'meta_value' => $meta_path, 'fields' => 'ids', 'posts_per_page' => 1, 'no_found_rows' => true, 'suppress_filters' => true, ]); if (!empty($existing_post)) { $post_id = (int)$existing_post[0]; // If we already have an attachment for this source abs, update its file in uploads; else import new $reuse = function_exists('gmm_temp_find_attachment_by_source_abs') ? gmm_temp_find_attachment_by_source_abs($target_jpg) : 0; if ($reuse) { $dest = get_attached_file($reuse); if ($dest && @copy($target_jpg, $dest)) { if (function_exists('wp_update_image_subsizes')) { @wp_update_image_subsizes($reuse); } else { $meta = @wp_generate_attachment_metadata($reuse, $dest); if ($meta) { @wp_update_attachment_metadata($reuse, $meta); } } set_post_thumbnail($post_id, $reuse); $thumbs_set++; } else { // fallback: re-import if (function_exists('gmm_temp_attach_local_image')) { $att_id = gmm_temp_attach_local_image($post_id, $target_jpg, $post_title); if ($att_id) { $thumbs_set++; } } } } else { if (function_exists('gmm_temp_attach_local_image')) { $att_id = gmm_temp_attach_local_image($post_id, $target_jpg, $post_title); if ($att_id) { $thumbs_set++; } } } $refreshed++; } } $msg = 'Folder Images: regenerated '.$created; $msg .= ', refreshed posts '.$refreshed; $msg .= ', set thumbnails '.$thumbs_set; $msg .= $errors ? ', errors '.$errors : ''; $msg .= '. Generated at '.$W.'×'.$H.( $has_ttf ? ' using TTF anti-aliased text.' : ' (fallback bitmap text).' ).''; return $msg; } // 5 STOP: Action — Generate Folder Images (overwrite) with GD/TTF, auto-detect size, text = Post Name “{Folder} Media”, refresh thumbnails Activity – Demonstoned – Gameznet Creators Hub
Profile Photo

DemonstonedOffline

0 out of 5
0 Ratings
  • Profile picture of Demonstoned

    Demonstoned wrote a new post

    Adventure Joystick Are you ready to accompany him in the adventure of joystick, who is a cute adventurer? Be careful, no matter how simple it may […]

    Adventure Joystick

    Are you ready to accompany him in the adventure of joystick, who is a cute adventurer? Be careful, no matter how simple it may seem, there are walls you have to go through, obstacles you have to overcome. You'll...

    Read More
  • Profile picture of Demonstoned

    Demonstoned wrote a new post

    Acorn Bot 2 Acorn Bot 2 is a 2D platformer where you have to collect all of the ice cream cones while avoiding the enemy bots, flying robots, […]

    Acorn Bot 2

    Acorn Bot 2 is a 2D platformer where you have to collect all of the ice cream cones while avoiding the enemy bots, flying robots, ground saws, spikes and reach the Exit door in order to go to the...

    Read More
  • Profile picture of Demonstoned

    Demonstoned wrote a new post

    Acorn Bot Acorn Bot is a 2D platformer where you have to collect all of the ice cream cones while avoiding enemy bots, spikes, ground saws, and […]

    Acorn Bot

    Acorn Bot is a 2D platformer where you have to collect all of the ice cream cones while avoiding enemy bots, spikes, ground saws, and rotating lasers and reach the Exit door in order to go to the next...

    Read More
  • Profile picture of Demonstoned

    Demonstoned wrote a new post

    AIM Shooter, arcade, puzzle game. How well can you aim and calculate your shot? It’shard to hit two objects with a single hit thanks to the ricochet. […]

    AIM

    Shooter, arcade, puzzle game. How well can you aim and calculate your shot? It'shard to hit two objects with a single hit thanks to the ricochet. The new project"AIM", will teach you to hit the target precisely. Play Now for...

    Read More
  • Profile picture of Demonstoned

    Demonstoned wrote a new post

    A Mole in a Hole Help a forgetful mole to find his way home!Look at the map and choose the right path!Go home to your wife before dinner is ready! […]

    A Mole in a Hole

    Help a forgetful mole to find his way home!Look at the map and choose the right path!Go home to your wife before dinner is ready! She'is waiting for you!Features:-20 Levels to dig-10 Achievements to unlock- Many different ways to...

    Read More
  • Profile picture of Demonstoned

    Demonstoned wrote a new post

    A Long Cargo stack the objects and make the biggest cargo ever! Play Now for Free!

    A Long Cargo

    stack the objects and make the biggest cargo ever! Play Now for Free!

    Read More
  • Profile picture of Demonstoned

    Demonstoned wrote a new post

    8Bit Venom A black super scary hero jumping from wall to wall, a super powerful hero, has to escape from the universe full of wheels. Help him escape […]

    8Bit Venom

    A black super scary hero jumping from wall to wall, a super powerful hero, has to escape from the universe full of wheels. Help him escape without touching the wheels! You must not die, you must jump, jump, jump...

    Read More
  • Profile picture of Demonstoned

    Demonstoned wrote a new post

    8-bit Console Tank It is very classic game since 80s, nearly no one never played before.This game contains many stages, it is enough for you to play a whole year day by day.It is a very classical tank battle game Play Now for Free!

    8-bit Console Tank

    It is very classic game since 80s, nearly no one never played before.This game contains many stages, it is enough for you to play a whole year day by day.It is a very classical tank battle game Play Now for...

    Read More
  • Profile picture of Demonstoned

    Demonstoned wrote a new post

    8 Ball Pool Multiplayer 8 Ball Pool has introduced a new level system to keep you entertained. With this new system, you’ll always face a challenge […]

    8 Ball Pool Multiplayer

    8 Ball Pool has introduced a new level system to keep you entertained. With this new system, you'll always face a challenge and get access to more exclusive match locations, where you play against only the best Pool players....

    Read More
  • Profile picture of Demonstoned

    Demonstoned wrote a new post

    7 Errors 7 Errors is a game where you have to find the 7 mistakes before time runs out. Can you find all 7? Have fun looking. Play Now for Free!

    7 Errors

    7 Errors is a game where you have to find the 7 mistakes before time runs out. Can you find all 7? Have fun looking. Play Now for Free!

    Read More
  • Load More Posts

User Balance

User Balance 12,710 / Points
Pro

User Badges

My Latest Media

Where To Find Me

Groups

Group logo of Games
Games
Public Group

Reward User

Please Log in to view this