1010
1111namespace chillerlan \QRCode \Output ;
1212
13- use chillerlan \QRCode \Data \QRMatrix ;
14- use chillerlan \QRCode \QRCode ;
15-
16- use function implode , is_string , sprintf , strip_tags , trim ;
13+ use function is_string , strip_tags , trim ;
1714
1815/**
19- * Converts the matrix into markup types: HTML, SVG, ...
16+ * Abstract for markup types: HTML, SVG, ... XML anyone?
2017 */
21- class QRMarkup extends QROutputAbstract{
18+ abstract class QRMarkup extends QROutputAbstract{
2219
2320 /**
2421 * @inheritDoc
@@ -44,18 +41,11 @@ protected function getDefaultModuleValue(bool $isDark):string{
4441 /**
4542 * @inheritDoc
4643 */
47- public function dump (string $ file = null ){
44+ public function dump (string $ file = null ): string {
4845 $ file ??= $ this ->options ->cachefile ;
4946 $ saveToFile = $ file !== null ;
5047
51- switch ($ this ->options ->outputType ){
52- case QRCode::OUTPUT_MARKUP_HTML :
53- $ data = $ this ->html ($ saveToFile );
54- break ;
55- case QRCode::OUTPUT_MARKUP_SVG :
56- default :
57- $ data = $ this ->svg ($ saveToFile );
58- }
48+ $ data = $ this ->createMarkup ($ saveToFile );
5949
6050 if ($ saveToFile ){
6151 $ this ->saveToFile ($ data , $ file );
@@ -65,143 +55,7 @@ public function dump(string $file = null){
6555 }
6656
6757 /**
68- * HTML output
69- */
70- protected function html (bool $ saveToFile ):string {
71-
72- $ html = empty ($ this ->options ->cssClass )
73- ? '<div> '
74- : sprintf ('<div class="%s"> ' , $ this ->options ->cssClass );
75-
76- $ html .= $ this ->options ->eol ;
77-
78- foreach ($ this ->matrix ->matrix () as $ row ){
79- $ html .= '<div> ' ;
80-
81- foreach ($ row as $ M_TYPE ){
82- $ html .= sprintf ('<span style="background: %s;"></span> ' , $ this ->moduleValues [$ M_TYPE ]);
83- }
84-
85- $ html .= '</div> ' .$ this ->options ->eol ;
86- }
87-
88- $ html .= '</div> ' .$ this ->options ->eol ;
89-
90- if ($ saveToFile ){
91- return sprintf (
92- '<!DOCTYPE html><head><meta charset="UTF-8"><title>QR Code</title></head><body>%s</body> ' ,
93- $ this ->options ->eol .$ html
94- );
95- }
96-
97- return $ html ;
98- }
99-
100- /**
101- * SVG output
10258 *
103- * @see https://github.com/codemasher/php-qrcode/pull/5
104- * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg
105- * @see https://www.sarasoueidan.com/demos/interactive-svg-coordinate-system/
106- */
107- protected function svg (bool $ saveToFile ):string {
108- $ svg = $ this ->svgHeader ();
109-
110- if (!empty ($ this ->options ->svgDefs )){
111- $ svg .= sprintf ('<defs>%1$s%2$s</defs>%2$s ' , $ this ->options ->svgDefs , $ this ->options ->eol );
112- }
113-
114- $ svg .= $ this ->svgPaths ();
115-
116- // close svg
117- $ svg .= sprintf ('%1$s</svg>%1$s ' , $ this ->options ->eol );
118-
119- // transform to data URI only when not saving to file
120- if (!$ saveToFile && $ this ->options ->imageBase64 ){
121- $ svg = $ this ->base64encode ($ svg , 'image/svg+xml ' );
122- }
123-
124- return $ svg ;
125- }
126-
127- /**
128- * returns the <svg> header with the given options parsed
12959 */
130- protected function svgHeader ():string {
131- $ width = $ this ->options ->svgWidth !== null ? sprintf (' width="%s" ' , $ this ->options ->svgWidth ) : '' ;
132- $ height = $ this ->options ->svgHeight !== null ? sprintf (' height="%s" ' , $ this ->options ->svgHeight ) : '' ;
133-
134- /** @noinspection HtmlUnknownAttribute */
135- return sprintf (
136- '<?xml version="1.0" encoding="UTF-8"?>%6$s ' .
137- '<svg xmlns="http://www.w3.org/2000/svg" class="qr-svg %1$s" viewBox="0 0 %2$s %2$s" preserveAspectRatio="%3$s"%4$s%5$s>%6$s ' ,
138- $ this ->options ->cssClass ,
139- $ this ->options ->svgViewBoxSize ?? $ this ->moduleCount ,
140- $ this ->options ->svgPreserveAspectRatio ,
141- $ width ,
142- $ height ,
143- $ this ->options ->eol
144- );
145- }
146-
147- /**
148- * returns one or more SVG <path> elements
149- *
150- * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path
151- */
152- protected function svgPaths ():string {
153- $ paths = $ this ->collectModules (fn (int $ x , int $ y ):string => $ this ->svgModule ($ x , $ y ));
154- $ svg = [];
155-
156- // create the path elements
157- foreach ($ paths as $ M_TYPE => $ path ){
158- $ path = trim (implode (' ' , $ path ));
159-
160- if (empty ($ path )){
161- continue ;
162- }
163-
164- $ cssClass = implode (' ' , [
165- 'qr- ' .$ M_TYPE ,
166- ($ M_TYPE & QRMatrix::IS_DARK ) === QRMatrix::IS_DARK ? 'dark ' : 'light ' ,
167- $ this ->options ->cssClass ,
168- ]);
169-
170- $ format = empty ($ this ->moduleValues [$ M_TYPE ])
171- ? '<path class="%1$s" d="%2$s"/> '
172- : '<path class="%1$s" fill="%3$s" fill-opacity="%4$s" d="%2$s"/> ' ;
173-
174- $ svg [] = sprintf ($ format , $ cssClass , $ path , $ this ->moduleValues [$ M_TYPE ], $ this ->options ->svgOpacity );
175- }
176-
177- return implode ($ this ->options ->eol , $ svg );
178- }
179-
180- /**
181- * returns a path segment for a single module
182- *
183- * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d
184- */
185- protected function svgModule (int $ x , int $ y ):string {
186-
187- if ($ this ->options ->imageTransparent && !$ this ->matrix ->check ($ x , $ y )){
188- return '' ;
189- }
190-
191- if ($ this ->options ->drawCircularModules && $ this ->matrix ->checkTypeNotIn ($ x , $ y , $ this ->options ->keepAsSquare )){
192- $ r = $ this ->options ->circleRadius ;
193-
194- return sprintf (
195- 'M%1$s %2$s a%3$s %3$s 0 1 0 %4$s 0 a%3$s %3$s 0 1 0 -%4$s 0Z ' ,
196- ($ x + 0.5 - $ r ),
197- ($ y + 0.5 ),
198- $ r ,
199- ($ r * 2 )
200- );
201-
202- }
203-
204- return sprintf ('M%1$s %2$s h%3$s v1 h-%4$sZ ' , $ x , $ y , 1 , 1 );
205- }
206-
60+ abstract protected function createMarkup (bool $ saveToFile ):string ;
20761}
0 commit comments