Your IP : 216.73.216.240


Current Path : /home/juvelize/saulnois/tmp/install_695d2cf0b4957/src/
Upload File :
Current File : /home/juvelize/saulnois/tmp/install_695d2cf0b4957/src/TPdf.php

<?php
/*
* @package		Tech Fry Library
* @license		https://www.gnu.org/licenses/gpl-3.0.en.html
*/

namespace TechFry\Library;

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;

require(JPATH_LIBRARIES . '/techfry/lib/fpdf/fpdf.php');

// Class for managing FPDF - v1.86 (https://www.fpdf.org/)
class TPdf extends \FPDF
{
    // Styles - Text Color, Font Type, Font Size
    // Cell (inline), MultiCell (block), Write (without formatting)
    
    public $config;

    public $title;

    public $main;
    
    public $font;

    public $primary_font;
    
    public $secondary_font;
    
    public $font_size;

    public $color;

    public $page_width;

    public $page_height;

    public $side_margin;

    public $top_margin;

    public $y_after_main;

    public $primary_color;
    
    public $secondary_color;

    public $ignore_write = false;

    public $table;
    public $column_widths;
    public $row_count;
    public $col_count;
    public $cell_content;

    public $href;

    public $list_type;
    public $list_count;

    // align, border, color, bg_color, font, font_size, font_weight
    public $styles;

    public function __construct($config = [])
    {
        // $config - left_margin, top_margin, text_color, font, font_size
        //    title_align, title_font, title_border, title_color, file_name
        
        if (!\is_array($config))
        {
            $config = (array) $config;
        }

        $this->config = $config;

        $orientation = $this->config['orientation'] ?? 'P';
        $unit = $this->config['unit'] ?? 'mm';
        $size = $this->config['size'] ?? 'A4';
        
        parent::__construct($orientation, $unit, $size);

        $this->add_meta();

        // 1. Set Page Margins - Sides and Top
        $this->side_margin = $config['left_margin'] ?? 10;
        $this->SetLeftMargin($this->side_margin);
        $this->SetRightMargin($this->side_margin);

        $this->top_margin = $config['top_margin'] ?? 10;
        $this->SetTopMargin($this->top_margin);

        // 2. Set Text Color
        $this->color = $config['text_color'] ?? '#000000';
        $this->set_text_color($this->color);

        // 3. Set Font
        $this->font = $config['font'] ?? 'Arial';
        $this->SetFont($this->font); // Mandatory
        $this->primary_font = $this->font;
        $this->secondary_font = $config['secondary_font'] ?? 'Times';

        // 4. Set Font Size
        $this->font_size = $config['font_size'] ?? 12;
        $this->SetFontSize($this->font_size);

        // 5. Colors
        $this->primary_color = $config['primary_color'] ?? '#0275d8';
        $this->secondary_color = $config['secondary_color'] ?? '#d284ff';

        $this->page_width = floor($this->GetPageWidth());
        $this->page_height = floor($this->GetPageHeight());

        // Defaults
        $this->styles['border'] = 0;
        $this->styles['align'] = 'L';
        $this->styles['fill'] = 0;
    }
    
    public function generate_pdf($content = array())
    {
        // $content - title, main, pages

        $this->title = $content['title'] ?? '';
        $this->main = $content['main'] ?? '';

        $this->AliasNbPages();
        $this->AddPage();

        // 1. Title
        if ($this->title && $this->config['show_title'])
        {
            $this->add_title();
        }

        // 2. Main Content
        if ($this->main)
        {
            $this->write_html($this->main);
        }

        // 3. Pages
        if (isset($content['pages']) && !empty($content['pages']))
        {
            foreach ($content['pages'] as $page)
            {
                $this->AddPage();
                if (isset($page['title']) && $page['title'])
                {
                    $this->title = $page['title'];
                    $this->add_title();
                }
                if (isset($page['main']) && $page['main'])
                {
                    $this->write_html($page['main']);
                }
            }
        }

        $file_name = $this->config['file_name'] ?? 'file.pdf';
        $this->force_download($file_name);
    }

    // Print text and move to next line
    public function add_line($text)
    {
        $text = iconv('UTF-8', 'ISO-8859-1//IGNORE', $text);
        if ($text)
        {
            // width, height, text, border, align, fill
            $height = ceil($this->styles['font_size'] * 0.35);

            //$this->MultiCell(0, $height, $text, $this->styles['border'], $this->styles['align'], $this->styles['fill']);

            // MutiCell adds space below, so use Cell
            $this->Cell(0, $height, $text, $this->styles['border'], 0, $this->styles['align'], $this->styles['fill']);
            
            // width is in mm, font size is in pt
            // 48 pt = 0.35 * 48 mm
        }

        $this->reset_style();
    }

    // Use Cell()
    public function add_text($text)
    {        
        $text = iconv('UTF-8', 'ISO-8859-1//IGNORE', $text);
        if ($text)
        {
            $w = $this->GetStringWidth($text);
            $this->Cell($w, 8, $text, $this->styles['border'], 0, $this->styles['align'], $this->styles['fill']);
        }

        $this->reset_style();
    }

    public function add_title()
    {
        $class = $this->config['title_class'] ?? '';
        $this->get_styles_from_class($class);

        $style = $this->config['title_style'] ?? '';
        $this->get_styles_from_style($style);
        
        $this->styles['font_size'] = 36;

        $this->apply_styles();

        $this->add_line($this->title);
        $this->Ln(4);

        $this->reset_style();
    }

    public function Header()
    {
        if (isset($this->config['header_content']) && $this->config['header_content'])
        {
            $this->write_html($this->config['header_content']);
        }

        if (isset($this->config['logo']) && $this->config['logo'])
        {
            $logo_width = $this->config['logo_width'] ?? 30;
            $logo_align = $this->config['logo_align'] ?? 'L';

            if ($logo_align == 'L')
            {
                $x = $this->side_margin;
            }
            elseif ($logo_align == 'C')
            {
                $x = floor(($this->page_width - $logo_width)/2);
            }
            elseif ($logo_align == 'R')
            {
                $x = $this->page_width - $this->side_margin - $logo_width;
            }
            
            $y = $this->top_margin;

            $img = HTMLHelper::cleanImageURL($this->config['logo']);
            $this->Image($img->url, $x, $y, $logo_width);
        }

        // Line break
        if (isset($this->config['header_gap']) && $this->config['header_gap'])
        {
            $this->Ln($this->config['header_gap']);
        }
    }

    public function Footer()
    {
        $this->SetY(-15);
        
        if (isset($this->config['footer_content']) && $this->config['footer_content'])
        {
            $this->config['footer_content'] = str_replace('{page}', $this->PageNo(), $this->config['footer_content']);
            
            $this->write_html($this->config['footer_content']);
        }
    }

    // HTML Parser
    public function write_html($html)
    {
        // Convert HTML content to PDF
        
        $this->SetY($this->get_y());
        
        // Remove all tags except recognized ones
        $html = strip_tags($html, '<strong><b><u><i><a><img><p><br><em><table><tr><td><th><blockquote><ul><ol><li><h1><h2><h3><h4><h5><h6><div><span><hr><a>');
        
        // HTML parser
        $a = preg_split('/<(.*)>/U', $html, -1, PREG_SPLIT_DELIM_CAPTURE);

        foreach ($a as $i => $e)
        {
            if ($i % 2 == 0) // Even Index contains Text
            {
                $this->cell_content = $e;
                if (!$this->ignore_write)
                {
                    $this->Write(5, $e);
                }
            }
            else
            {
                // Closing Tag Tag
                if ($e[0] == '/')
                {
                    $this->close_tag(strtoupper(substr($e, 1)));
                }
                else
                {
                    // Opening Tag - Extract attributes
                    $a2 = explode(' ', $e);

                    $tag = strtoupper(array_shift($a2));
                    $attr = [];
                    foreach ($a2 as $v)
                    {
                        if (preg_match('/([^=]*)=["\']?([^"\']*)/', $v, $a3))
                        {
                            $attr[strtoupper($a3[1])] = $a3[2];
                        }
                    }

                    $this->open_tag($tag, $attr);
                }
            }
        }

        // Reset Margins
        $this->SetLeftMargin($this->side_margin);
        $this->SetRightMargin($this->side_margin);
    }

    public function open_tag($tag, $attr)
    {
        // CLASS and STYLE attributes are common for all

        $class = $attr['CLASS'] ?? '';
        $this->get_styles_from_class($class);

        $style = $attr['STYLE'] ?? '';
        $this->get_styles_from_style($style);
        
        if ($tag == 'STRONG' || $tag == 'B')
        {
            $this->styles['font_weight'] = 'B';
        }
        elseif ($tag == 'U')
        {
            $this->styles['font_weight'] = 'U';
        }
        elseif ($tag == 'I' || $tag == 'EM')
        {
            $this->styles['font_weight'] = 'I';
        }
        elseif ($tag == 'BR')
        {
            $this->Ln(5);
        }
        elseif ($tag == 'TABLE')
        {
            $column_widths = $attr['DATA-COL-WIDTHS'] ?? '';
            if ($column_widths)
            {
                $this->column_widths = explode(',', $column_widths);
            }
            
            $this->table = true;
            $this->ignore_write = true;
            //$this->Ln(5);
        }
        elseif ($tag == 'TR' && $this->table)
        {
            $this->Ln(8);
            $this->col_count = 0;
        }
        elseif ($tag == 'UL')
        {
            $this->list_type = 'ul';
            //$this->Ln(4);
        }
        elseif ($tag == 'OL')
        {
            $this->list_type = 'ol';
            $this->list_count = 1;
            //$this->Ln(4);
        }
        elseif ($tag == 'LI')
        {
            if ($this->list_type == 'ul')
            {
                $this->Write(5, chr(149) . ' ');
            } 
            elseif ($this->list_type == 'ol') 
            {
                $this->Write(5, $this->list_count . '. ');
                $this->list_count++;
            }

            //$this->SetX($this->GetX() + $this->listIndent);
        }
        elseif (preg_match('/H([1-6])/', $tag, $matches))
        {   
            $heading_level = (int) $matches[1];

            $font_size = 24 - ($heading_level - 1) * 3;
            $this->styles['font_size'] = $font_size;

            //$this->Ln(4);

            $this->ignore_write = true;
        }
        elseif ($tag == 'IMG')
        {
            $src = isset($attr['SRC']) ? $attr['SRC'] : '';
            $width = isset($attr['WIDTH']) ? (float)$attr['WIDTH'] : 0;
            $height = isset($attr['HEIGHT']) ? (float)$attr['HEIGHT'] : 0;

            $img = HTMLHelper::cleanImageURL($src);

            if ($width > 0 && $height > 0)
            {
                $this->Image($img->url, null, null, $width, $height);
            } 
            else 
            {
                $this->Image($img->url, null, null, 50, 50);
            }

            $this->Ln(5);
        }
        elseif ($tag == 'HR')
        {
            if ($class == 'system-pagebreak')
            {
                $this->AddPage();
            }
            else
            {
                $x1 = $this->side_margin;
                $y1 = $this->GetY();
                $x2 = $this->page_width - $this->side_margin;
                $y2 = $y1;

                $this->SetDrawColor(200);

                $this->Line($x1, $y1, $x2, $y2);
            }
        }
        elseif ($tag == 'A')
        {
            $this->href = $attr['HREF'] ?? '';
            $this->ignore_write = true;
        }

        $this->apply_styles();
    }

    // Close Tag
    public function close_tag($tag)
    {
        if ($tag == 'P')
        {
            // Add space after closing tag
            $this->Ln(5);
        }
        elseif ($tag == 'TABLE')
        {
            $this->table = false;
            $this->ignore_write = false;
            $this->column_widths = '';
            $this->Ln(5);
        }
        elseif ($tag == 'TD' || $tag == 'TH')
        {
            // Column width
            if ($this->column_widths)
            {
                $index = $this->col_count;
                $col_width = $this->column_widths[$index];
            }
            else
            {
                $col_width = 40;
            }

            // Make table headings as bold
            if ($tag == 'TH')
            {
                $this->styles['font_weight'] = 'B';
                $this->apply_styles();
            }

            if ($col_width)
            {
                $this->Cell($col_width, 8, $this->cell_content, 1);
                $this->cell_content = '';
            }

            $this->col_count++;
        }
        elseif ($tag == 'UL' || $tag == 'OL')
        {
            $this->list_type = '';
            //$this->Ln(4);
        }
        elseif ($tag == 'LI')
        {
            $this->Ln(2);
        }
        elseif (preg_match('/H([1-6])/', $tag, $matches)) 
        {
            $this->add_line($this->cell_content);
            $this->cell_content = '';

            $this->ignore_write = false;
        }
        elseif ($tag == 'A')
        {
            $this->SetFont('', 'U');
            $this->Write(5, $this->cell_content, $this->href);

            $this->href = '';
            $this->ignore_write = false;
        }

        $this->reset_style();
    }

    // Apply syles for text
    public function apply_styles()
    {
        // $this->styles - color, bg_color, font, font_size, font_weight
        // border and align are set in Cell() and MultiCell()
        
        if (isset($this->styles['color']) && $this->styles['color'])
        {
            $this->set_text_color($this->styles['color']);
        }

        if (isset($this->styles['bg_color']) && $this->styles['bg_color'])
        {
            $this->styles['fill'] = true;
            $this->set_fill_color($this->styles['bg_color']);
        }
        else
        {
            $this->styles['fill'] = false;
        }

        $font_family = $this->styles['font'] ?? $this->font;
        $font_weight = $this->styles['font_weight'] ?? '';
        $this->SetFont($font_family, $font_weight);

        if (isset($this->styles['font_size']) && $this->styles['font_size'])
        {
            $this->SetFontSize($this->styles['font_size']);
        }
    }

    // Apply base style
    public function reset_style()
    {
        $this->styles = array(
            'align' => 'L',
            'border' => 0,
            'fill' => false,
            'font_size' => $this->font_size,
        );
        
        $this->set_text_color($this->color);
        
        $this->SetFont($this->font, '', $this->font_size);
    }

    // Set Text Color
    public function set_text_color($color = '#000000')
    {
        $colors = $this->hex2dec($color);
        $this->SetTextColor($colors['R'], $colors['G'], $colors['B']);
    }

    // Set Fill or Background Color
    public function set_fill_color($color = '#FFFFFF')
    {
        $colors = $this->hex2dec($color);
        $this->SetFillColor($colors['R'], $colors['G'], $colors['B']);
    }

    // Set Border Color
    public function set_draw_color($color = '#CCCCCC')
    {
        $colors = $this->hex2dec($color);
        $this->SetDrawColor($colors['R'], $colors['G'], $colors['B']);
    }

    public function hex2dec($color = "#000000")
    {
        $colors = array();

        $colors['R'] = hexdec(substr($color, 1, 2));
        $colors['G'] = hexdec(substr($color, 3, 2));
        $colors['B'] = hexdec(substr($color, 5, 2));
        
        return $colors;
    }

    public function force_download($name = 'file.pdf')
    {
        $this->Output('D', $name);

        exit;
    }

    public function open_browser()
    {
        $this->Output();

        exit;
    }

    public function save_file($path)
    {
        $this->Output('F', $path);
    }

    public function get_x()
    {
        return floor($this->GetX());
    }

    public function get_y()
    {
        return floor($this->GetY());
    }

    public function get_styles_from_class($class)
    {
        $classes = explode(' ', $class);

        // 1. Align
        if (\in_array('text-center', $classes))
        {
            $this->styles['align'] = 'C';
        }
        elseif (\in_array('text-end', $classes))
        {
            $this->styles['align'] = 'R';
        }
        elseif (\in_array('text-start', $classes))
        {
            $this->styles['align'] = 'L';
        }

        // 2. Border
        if (\in_array('border', $classes))
        {
            $this->styles['border'] = 1;
        }

        // 3. Color
        if (\in_array('text-primary', $classes))
        {
            $this->styles['color'] = $this->primary_color;
        }
        elseif (\in_array('text-secondary', $classes))
        {
            $this->styles['color'] = $this->secondary_color;
        }
        elseif (\in_array('text-success', $classes))
        {
            $this->styles['color'] = '#5bc0de';
        }
        elseif (\in_array('text-danger', $classes))
        {
            $this->styles['color'] = '#d9534f';
        }
        elseif (\in_array('text-light', $classes))
        {
            $this->styles['color'] = '#dcdcdc';
        }
        elseif (\in_array('text-white', $classes))
        {
            $this->styles['color'] = '#FFFFFF';
        }

        // 4. Background Color
        if (\in_array('bg-primary', $classes))
        {
            $this->styles['bg_color'] = $this->primary_color;
        }
        elseif (\in_array('bg-secondary', $classes))
        {
            $this->styles['bg_color'] = $this->secondary_color;
        }
        elseif (\in_array('bg-light', $classes))
        {
            $this->styles['bg_color'] = '#dcdcdc';
        }
        elseif (\in_array('bg-dark', $classes))
        {
            $this->styles['bg_color'] = '#444444';
        }

        // 5. Font
        if (\in_array('font-primary', $classes))
        {
            $this->styles['font'] = $this->primary_font;
        }
        elseif (\in_array('font-secondary', $classes))
        {
            $this->styles['font'] = $this->secondary_font;
        }

        // 6. Font Size
        if (\in_array('fs-1', $classes))
        {
            $this->styles['font_size'] = floor($this->font_size * 2);
        }
        elseif (\in_array('fs-2', $classes))
        {
            $this->styles['font_size'] = floor($this->font_size * 1.7);
        }
        elseif (\in_array('fs-3', $classes))
        {
            $this->styles['font_size'] = floor($this->font_size * 1.4);
        }

        // 7. Font Weight
        if (\in_array('fw-bold', $classes))
        {
            $this->styles['font_weight'] = 'B';
        }
    }

    // Get Styles from CSS style attribute
    public function get_styles_from_style($style)
    {
        $styles = [];
        
        $declarations = explode(';', $style);
        foreach ($declarations as $declaration) 
        {
            $parts = explode(':', $declaration, 2);

            if (count($parts) == 2) 
            {
                $property = trim($parts[0]);
                $value = trim($parts[1]);
            
                $styles[$property] = $value;
            }
        }

        // 1. Align
        if (\array_key_exists('text-align', $styles))
        {
            if ($styles['text-align'] == 'center')
            {
                $this->styles['align'] = 'C';
            }
            elseif ($styles['text-align'] == 'right')
            {
                $this->styles['align'] = 'R';
            }
            elseif ($styles['text-align'] == 'left')
            {
                $this->styles['align'] = 'L';
            }
        }

        // 2. Border
        if (\array_key_exists('border', $styles))
        {
            $this->styles['border'] = 1;
        }

        // 3. Color
        if (\array_key_exists('color', $styles))
        {
            $this->styles['color'] = $styles['color'];
        }

        // 4. Background Color
        if (\array_key_exists('background-color', $styles))
        {
            $this->styles['bg_color'] = $styles['background-color'];
        }

        // 5. Font Size
        if (\array_key_exists('font-size', $styles))
        {
            $this->styles['font_size'] = (int) filter_var($styles['font-size'], FILTER_SANITIZE_NUMBER_INT);
        }

        // 6. Font Weight
        if (\array_key_exists('font-weight', $styles))
        {
            $this->styles['font_weight'] = 'B';
        }
    }

    public function add_meta()
    {
        if (isset($this->config['pdf_title']) && $this->config['pdf_title'])
        {
            $this->SetTitle($this->config['pdf_title']);
        }

        if (isset($this->config['pdf_author']) && $this->config['pdf_author'])
        {
            $this->SetAuthor($this->config['pdf_author']);
        }
    }
}