PluginProbe
JCH Optimize / trunk
JCH Optimize vtrunk
6.0.2 6.0.1 trunk 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.1.0 2.10.0 2.2.0 2.2.1 All 58 releases
jch-optimize / src / Platform / Html.php

Html.php in JCH Optimize trunk, at src/Platform/Html.php

211 lines 5.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * JCH Optimize - Performs several front-end optimizations for fast downloads
4 *
5 * @package jchoptimize/wordpress-platform
6 * @author Samuel Marshall <samuel@jch-optimize.net>
7 * @copyright Copyright (c) 2020 Samuel Marshall / JCH Optimize
8 * @license GNU/GPLv3, or later. See LICENSE file
9 *
10 * If LICENSE file missing, see <http://www.gnu.org/licenses/>.
11 */
12
13 namespace JchOptimize\WordPress\Platform;
14
15 defined('_WP_EXEC') or die('Restricted access');
16
17 use _JchOptimizeVendor\V91\GuzzleHttp\Exception\GuzzleException;
18 use _JchOptimizeVendor\V91\GuzzleHttp\RequestOptions;
19 use _JchOptimizeVendor\V91\Psr\Http\Client\ClientInterface;
20 use _JchOptimizeVendor\V91\Psr\Log\LoggerAwareInterface;
21 use _JchOptimizeVendor\V91\Psr\Log\LoggerAwareTrait;
22 use JchOptimize\Core\Exception;
23 use JchOptimize\Core\Platform\HtmlInterface;
24 use JchOptimize\Core\Platform\ProfilerInterface;
25 use JchOptimize\Core\Platform\UtilityInterface;
26 use JchOptimize\Core\Uri\Uri;
27 use JchOptimize\Core\Uri\UriComparator;
28 use JchOptimize\Core\Uri\Utils;
29
30 use function __;
31 use function array_merge;
32 use function array_slice;
33 use function get_nav_menu_locations;
34 use function get_registered_nav_menus;
35 use function home_url;
36 use function microtime;
37 use function parse_str;
38 use function rtrim;
39 use function wp_get_nav_menu_items;
40 use function wp_get_nav_menus;
41
42 class Html implements HtmlInterface, LoggerAwareInterface
43 {
44 use LoggerAwareTrait;
45
46 public function __construct(
47 private ClientInterface $http,
48 private ProfilerInterface $profiler,
49 private UtilityInterface $utility
50 ) {
51 }
52
53 /**
54 * @throws GuzzleException
55 */
56 public function getHomePageHtml(): string
57 {
58 JCH_DEBUG ? $this->profiler->mark('beforeGetHtml') : null;
59
60 $url = home_url() . '/?jchbackend=1';
61
62 try {
63
64
65 $response = $this->http->get($url, ['Accept-Encoding' => 'identity;q=0']);
66
67 if ($response->getStatusCode() != 200) {
68 throw new Exception\RuntimeException(
69 __(
70 'Failed fetching front end HTML with response code ' . $response->getStatusCode(),
71 'jch-optimize'
72 )
73 );
74 }
75
76 JCH_DEBUG ? $this->profiler->mark('afterGetHtml') : null;
77
78
79 $body = $response->getBody();
80 //Set pointer to beginning of stream.
81 $body->rewind();
82
83 return $body->getContents();
84 } catch (\Exception $e) {
85 $this->logger?->error($url . ': ' . $e->getMessage());
86
87 JCH_DEBUG ? $this->profiler->mark('afterGetHtml)') : null;
88
89 throw new Exception\RuntimeException(
90 __(
91 'Load or refresh the front-end site first then refresh this page '
92 . 'to populate the multi select exclude lists.',
93 'jch-optimize'
94 )
95 );
96 }
97 }
98
99 public function getMainMenuItemsHtmls($iLimit = 5, $bIncludeUrls = false): array
100 {
101 $aMenuUrls = $this->getMenuUrls();
102 $aMenuUrls = array_slice($aMenuUrls, 0, $iLimit);
103
104 $aHtmls = [];
105
106 //Limit the time spent on this
107 $iTimer = microtime(true);
108
109 foreach ($aMenuUrls as $menuUrl) {
110 try {
111 if ($bIncludeUrls) {
112 $aHtmls[] = [
113 'url' => $menuUrl,
114 'html' => $this->getHtml($menuUrl)
115 ];
116 } else {
117 $aHtmls[] = $this->getHtml($menuUrl);
118 }
119 } catch (Exception\ExceptionInterface $e) {
120 $this->logger?->error((string)$e);
121 }
122
123 if (microtime(true) > $iTimer + 10.0) {
124 break;
125 }
126 }
127
128 return $aHtmls;
129 }
130
131 protected function getMenuUrls(): array
132 {
133 $homeUrl = rtrim(home_url(), '/\\');
134 //Start array of oMenu urls with home page
135 $aMenuUrls = [$homeUrl];
136
137 $aMenus = wp_get_nav_menus();
138 //If nothing just work with the home url
139 if (! $aMenus) {
140 return $aMenuUrls;
141 }
142
143 $locations = get_registered_nav_menus();
144 $aMenuLocations = get_nav_menu_locations();
145
146 //Iterate through menus to find primary
147 foreach ($aMenus as $oMenu) {
148 if ($oMenu->term_id == $aMenuLocations['menu-primary']) {
149 break;
150 }
151 }
152
153 $aMenuItems = wp_get_nav_menu_items($oMenu);
154
155 foreach ($aMenuItems as $oMenuItem) {
156 if (rtrim($oMenuItem->url, '/\\') == $homeUrl) {
157 continue;
158 }
159
160 if (! $cleanUrl = $this->cleanUrl($oMenuItem->url)) {
161 continue;
162 }
163
164 if (!UriComparator::isCrossOrigin(Utils::uriFor($cleanUrl))) {
165 $aMenuUrls[] = $cleanUrl;
166 }
167 }
168
169 return $aMenuUrls;
170 }
171
172 private function cleanUrl(string $oMenuItem): string
173 {
174 $oUri = Utils::uriFor($oMenuItem);
175
176 return (string)$oUri;
177 }
178
179 /**
180 * @throws Exception\RuntimeException
181 * @throws GuzzleException
182 */
183 protected function getHtml(string $url): string
184 {
185 $oUri = Utils::uriFor($url);
186 $sQuery = $oUri->getQuery();
187 parse_str($sQuery, $aQuery);
188 $aNewQuery = array_merge($aQuery, array('jchbackend' => '1'));
189 $oUri = Uri::withQueryValues($oUri, $aNewQuery);
190
191 $options = [
192 RequestOptions::HEADERS => [
193 'Accept-Enconding' => 'identity;q=0'
194 ]
195 ];
196
197 $response = $this->http->get($oUri, $options);
198
199 if ($response->getStatusCode() != 200) {
200 throw new Exception\RuntimeException(
201 'Failed fetching HTML: ' . $url . ' - Response code: ' . $response->getStatusCode()
202 );
203 }
204
205 $body = $response->getBody();
206 $body->rewind();
207
208 return $body->getContents();
209 }
210 }
211