1: <?php
2: 3: 4: 5: 6: 7: 8: 9:
10:
11: namespace Kotchasan;
12:
13: 14: 15: 16: 17: 18: 19:
20: class Htmldoc
21: {
22: 23: 24: 25: 26:
27: private $docFile;
28: 29: 30: 31: 32:
33: private $htmlBody;
34: 35: 36: 37: 38:
39: private $htmlHead;
40: 41: 42: 43: 44:
45: private $title;
46:
47: 48: 49:
50: public function __construct()
51: {
52: $this->title = 'Untitled';
53: $this->htmlHead = '';
54: $this->htmlBody = '';
55: $this->docFile = '';
56: }
57:
58: 59: 60: 61: 62: 63:
64: public function createDoc($html, $file = '')
65: {
66:
67: $this->parseHtml($html, $file);
68:
69: $response = new \Kotchasan\Http\Response();
70: $response->withHeaders(array(
71: 'Content-type' => 'application/vnd.ms-word',
72: 'Content-Disposition' => 'attachment;Filename='.$this->docFile,
73: ))
74: ->withContent($this->render())
75: ->send();
76: }
77:
78: 79: 80: 81: 82:
83: public function setDocFileName($docfile)
84: {
85: $this->docFile = $docfile;
86: if (!preg_match('/\.doc$/i', $this->docFile)) {
87: $this->docFile .= '.doc';
88: }
89:
90: return $this;
91: }
92:
93: 94: 95: 96: 97: 98:
99: private function parseHtml($html, $file)
100: {
101:
102: $html = preg_replace('/<script((.|\n)*?)>((.|\n)*?)<\/script>/ims', '', $html);
103:
104: if (preg_match('/<head>(.*)<\/head>/isU', $html, $matches)) {
105: $this->htmlHead = preg_replace('/<title>(.*)<\/title>/isU', '', $matches[1]);
106: }
107:
108: if ($file == '' && preg_match('/<title>(.*)<\/title>/isU', $html, $matches)) {
109: $this->setDocFileName($matches[1].'.doc');
110: }
111:
112: if (preg_match('/<body[^>]+>(.*)<\/body>/isU', $html, $matches)) {
113:
114: $this->htmlBody = preg_replace_callback('/<span[^>]+class="line([0-9]{0,})">([^>]+)<\/span>/isuU', function ($items) {
115: $datas = array(0 => 20, 1 => 40, 2 => 60, 3 => 80, 4 => 100);
116: $text = trim(str_replace(' ', ' ', $items[2]));
117: $len = ($datas[(int) $items[1]] - mb_strlen($text)) / 2;
118: for ($i = 0; $i < $len; ++$i) {
119: $text = '.'.$text.'.';
120: }
121:
122: return ' <span> '.$text.' </span> ';
123: }, $matches[1]);
124: }
125: }
126:
127: 128: 129: 130: 131:
132: private function render()
133: {
134: return <<<EOH
135: <html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
136: <head>
137: <style>
138: v\:* {behavior:url(#default#VML);}
139: o\:* {behavior:url(#default#VML);}
140: w\:* {behavior:url(#default#VML);}
141: .shape {behavior:url(#default#VML);}
142: </style>
143: <style>
144: @page {
145: size: 21cm 29.7cm;
146: margin: 1cm 1cm 1cm 1cm;
147: mso-page-orientation: portrait;
148: }
149: @page WordSection1 {
150: mso-title-page: no;
151: mso-paper-source:0;
152: mso-header-margin: 0;
153: mso-footer-margin: 0;
154: }
155: div.WordSection1 {
156: page:WordSection1;
157: mso-header-margin: 0;
158: mso-footer-margin: 0;
159: }
160: </style>
161: $this->htmlHead
162: </head>
163: <body>
164: $this->htmlBody
165: </body>
166: </html>
167: EOH;
168: }
169: }
170: