Passed
Push — master ( fa68f7...dc9099 )
by Peter
08:47
created

PhpOutlookSignature   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Importance

Changes 4
Bugs 1 Features 1
Metric Value
eloc 90
dl 0
loc 149
rs 10
c 4
b 1
f 1
wmc 27

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 20 5
A prepare_script() 0 6 2
A create_filelist() 0 14 2
B create() 0 35 9
A analyze_template_text() 0 19 3
A check_template_files() 0 22 4
A get_assets() 0 3 1
A get_keywords() 0 3 1
1
<?php
2
3
namespace Pforret\PhpOutlookSignature;
4
5
use Exception;
6
7
class PhpOutlookSignature
8
{
9
    private string $default_template = '';
10
    private string $template_folder = '';    //<template>
11
    private string $template_file = '';      //<template>/<message>.htm
12
    private string $assets_folder = '';      //<template>/<message>_files/
13
    private string $assets_local = '';       //<message>_files
14
    private array $keywords = [];
15
    private array $included_files = [];
16
    private bool $is_ready = false;
17
18
    public function __construct(string $folder = '')
19
    {
20
        $this->is_ready = false;
21
        $this->default_template = __DIR__ . '/templates/default';
22
        if (!file_exists($this->default_template)) {
23
            throw new Exception(sprintf("Default template folder [%s] does not exist", $this->default_template));
24
        }
25
        if (!$folder) {
26
            $folder = $this->default_template;
27
        }
28
        if (!file_exists($folder)) {
29
            throw new Exception(sprintf("Template folder [%s] does not exist", $folder));
30
        }
31
        $this->template_folder = $folder;
32
        $this->check_template_files($this->template_folder);
33
        if (!file_exists($this->assets_folder."/filelist.xml")) {
34
            $this->create_filelist();
35
        }
36
        $this->analyze_template_text();
37
        $this->is_ready = true;
38
    }
39
40
    public function create(string $output_file, array $values, bool $ignore_errors = false): bool
41
    {
42
        $output_folder = dirname($output_file);
43
        $output_name = pathinfo($output_file, PATHINFO_FILENAME);
44
        $assets_folder_name = "${output_name}_files";
45
        $assets_folder = "$output_folder/$assets_folder_name";
46
        if (!file_exists($output_folder)) {
47
            mkdir($output_folder, 0777, true);
48
        }
49
        if (!file_exists($assets_folder)) {
50
            mkdir($assets_folder, 0777);
51
        }
52
        if (!isset($values['assets'])) {
53
            $values['assets'] = $assets_folder_name;
54
        }
55
        // fill in template
56
57
        $text = file_get_contents($this->template_file);
58
        foreach ($this->keywords as $keyword) {
59
            if (!$ignore_errors && !isset($values[$keyword])) {
60
                throw new Exception("Template expects [$keyword] but none was given");
61
            }
62
            $value = isset($values[$keyword]) ? $values[$keyword] : "";
63
            $text = str_replace('{' . $keyword . '}', $value, $text);
64
        }
65
        // save files
66
        file_put_contents($output_file, $text);
67
        foreach ($this->included_files as $file) {
68
            $file = str_replace('{assets}', $values['assets'], $file);
69
            $copy_file = "$assets_folder/" . basename($file);
70
            copy($file, $copy_file);
71
        }
72
        $this->prepare_script($this->template_folder.'/install_windows.cmd',$output_folder,'%APPDATA%\Microsoft\Signatures');
73
        // TODO: install script for MacOS
74
        return true;
75
    }
76
77
    // ---------------------------- PRIVATE METHODS
78
79
    private function prepare_script($input_file,$output_folder,$destination){
80
        if(!file_exists($input_file)) return false;
81
        $install_script = $output_folder."/".basename($input_file);
82
        $script = file_get_contents($input_file);
83
        $script = str_replace('{destin}', $destination, $script);
84
        file_put_contents($install_script, $script);
85
    }
86
87
    private function check_template_files(string $folder): bool
88
    {
89
        $html_files = glob("$folder/*.htm");
90
        if (count($html_files) === 0) {
0 ignored issues
show
Bug introduced by
It seems like $html_files can also be of type false; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

90
        if (count(/** @scrutinizer ignore-type */ $html_files) === 0) {
Loading history...
91
            throw new Exception(sprintf("Template folder [%s] does not contain a .htm file", $this->template_folder));
92
        }
93
        if (count($html_files) > 1) {
94
            throw new Exception(sprintf("Template folder [%s] should only contain 1 .htm file (now: %d)", $this->template_folder, count($html_files)));
95
        }
96
97
        $this->template_file = $html_files[0];
98
        $template_name = basename($this->template_file, '.htm');
99
        $assets_folder = sprintf("%s/%s", $this->template_folder, "${template_name}_files");
100
        if (!is_dir($assets_folder)) {
101
            // TODO: look for alternative folder name in template
102
            throw new Exception(sprintf("Template assets folder [%s] cannot be found", $assets_folder));
103
            // most probable
104
        }
105
        $this->assets_folder = $assets_folder;
106
        $this->assets_local = basename($assets_folder);
107
108
        return true;
109
    }
110
111
    private function analyze_template_text(): bool
112
    {
113
        $this->keywords = [];
114
        $this->included_files = [];
115
        $text = file_get_contents($this->template_file);
116
        $text = str_replace($this->assets_local.'/', '{assets}/', $text);
117
        preg_match_all('|\{(\w+)\}|', $text, $matches, PREG_SET_ORDER);
118
        foreach ($matches as $match) {
119
            $keyword = $match[1];
120
            $this->keywords[$keyword] = $keyword;
121
        }
122
        preg_match_all('|({assets}/\w+\.\w+)|', $text, $matches, PREG_SET_ORDER);
123
        foreach ($matches as $match) {
124
            $file = $match[1];
125
            $file = str_replace('{assets}', $this->assets_folder, $file);
126
            $this->included_files[$file] = $file;
127
        }
128
129
        return true;
130
    }
131
132
    public function get_keywords(): array
133
    {
134
        return array_keys($this->keywords);
135
    }
136
137
    public function get_assets(): array
138
    {
139
        return array_keys($this->included_files);
140
    }
141
142
    private function create_filelist(): bool
143
    {
144
        $xml = '<xml xmlns:o="urn:schemas-microsoft-com:office:office">' . PHP_EOL;
145
        $xml .= sprintf(' <o:MainFile HRef="../%s"/>', basename($this->template_file)) . PHP_EOL;
146
        $assets = glob($this->assets_folder . "/*");
147
        foreach ($assets as $asset) {
148
            $xml .= sprintf(' <o:File HRef="%s"/>', basename($asset)) . PHP_EOL;
149
        }
150
        $xml .= '</xml>' . PHP_EOL;
151
        $filelist = "$this->assets_folder/filelist.xml";
152
        file_put_contents($filelist, $xml);
153
        $this->included_files[$filelist] = $filelist;
154
155
        return true;
156
    }
157
}
158