@@ -1003,8 +1003,8 @@ |
||
1003 | 1003 | } |
1004 | 1004 | if ($this->searchFieldsForDuplicates) { |
1005 | 1005 | $duplicateCheckClause = []; |
1006 | - $queryGenerator = new self($this->moduleName, $this->user->getId()); |
|
1007 | - $queryGenerator->setStateCondition($this->getState()); |
|
1006 | + $queryGenerator = new self($this->moduleName, $this->user->getId()); |
|
1007 | + $queryGenerator->setStateCondition($this->getState()); |
|
1008 | 1008 | $queryGenerator->permissions = $this->permissions; |
1009 | 1009 | $queryGenerator->setFields(array_keys($this->searchFieldsForDuplicates)); |
1010 | 1010 | foreach ($this->searchFieldsForDuplicates as $fieldName => $ignoreEmptyValue) { |
@@ -19,52 +19,52 @@ |
||
19 | 19 | */ |
20 | 20 | class YetiForce extends Base |
21 | 21 | { |
22 | - /** {@inheritdoc} */ |
|
23 | - public function getCoordinates(array $addressInfo) |
|
24 | - { |
|
25 | - $product = \App\YetiForce\Register::getProduct('YetiForceMap'); |
|
26 | - if (empty($addressInfo) || !\App\RequestUtil::isNetConnection() || ((empty($product['params']['login']) || empty($product['params']['pass'])) && empty($product['params']['token']))) { |
|
27 | - return false; |
|
28 | - } |
|
29 | - $params = array_merge([ |
|
30 | - 'version' => 2.0, |
|
31 | - 'format' => 'json', |
|
32 | - 'addressdetails' => 1, |
|
33 | - 'limit' => 1, |
|
34 | - 'accept-language' => \App\Language::getLanguage() . ',' . \App\Config::main('default_language') . ',en-US', |
|
35 | - ], $addressInfo); |
|
36 | - $options = [ |
|
37 | - 'timeout' => 60, |
|
38 | - 'headers' => ['InsKey' => \App\YetiForce\Register::getInstanceKey()], |
|
39 | - ]; |
|
40 | - if (isset($product['params']['token'])) { |
|
41 | - $params['yf_token'] = $product['params']['token']; |
|
42 | - } else { |
|
43 | - $options['auth'] = [$product['params']['login'], $product['params']['pass']]; |
|
44 | - } |
|
45 | - $coordinates = false; |
|
46 | - try { |
|
47 | - $url = 'https://osm-search.yetiforce.eu/?' . \http_build_query($params); |
|
48 | - \App\Log::beginProfile("GET|YetiForce::getCoordinates|{$url}", __NAMESPACE__); |
|
49 | - $response = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->request('GET', $url, $options); |
|
50 | - \App\Log::endProfile("GET|YetiForce::getCoordinates|{$url}", __NAMESPACE__); |
|
51 | - if (200 === $response->getStatusCode()) { |
|
52 | - $coordinates = \App\Json::decode($response->getBody()); |
|
53 | - } else { |
|
54 | - throw new \App\Exceptions\AppException('Error with connection |' . $response->getReasonPhrase() . '|' . $response->getBody()); |
|
55 | - } |
|
56 | - } catch (\Exception $ex) { |
|
57 | - \App\Log::error('Error - ' . $ex->getMessage(), __CLASS__); |
|
58 | - } |
|
59 | - return $coordinates; |
|
60 | - } |
|
22 | + /** {@inheritdoc} */ |
|
23 | + public function getCoordinates(array $addressInfo) |
|
24 | + { |
|
25 | + $product = \App\YetiForce\Register::getProduct('YetiForceMap'); |
|
26 | + if (empty($addressInfo) || !\App\RequestUtil::isNetConnection() || ((empty($product['params']['login']) || empty($product['params']['pass'])) && empty($product['params']['token']))) { |
|
27 | + return false; |
|
28 | + } |
|
29 | + $params = array_merge([ |
|
30 | + 'version' => 2.0, |
|
31 | + 'format' => 'json', |
|
32 | + 'addressdetails' => 1, |
|
33 | + 'limit' => 1, |
|
34 | + 'accept-language' => \App\Language::getLanguage() . ',' . \App\Config::main('default_language') . ',en-US', |
|
35 | + ], $addressInfo); |
|
36 | + $options = [ |
|
37 | + 'timeout' => 60, |
|
38 | + 'headers' => ['InsKey' => \App\YetiForce\Register::getInstanceKey()], |
|
39 | + ]; |
|
40 | + if (isset($product['params']['token'])) { |
|
41 | + $params['yf_token'] = $product['params']['token']; |
|
42 | + } else { |
|
43 | + $options['auth'] = [$product['params']['login'], $product['params']['pass']]; |
|
44 | + } |
|
45 | + $coordinates = false; |
|
46 | + try { |
|
47 | + $url = 'https://osm-search.yetiforce.eu/?' . \http_build_query($params); |
|
48 | + \App\Log::beginProfile("GET|YetiForce::getCoordinates|{$url}", __NAMESPACE__); |
|
49 | + $response = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->request('GET', $url, $options); |
|
50 | + \App\Log::endProfile("GET|YetiForce::getCoordinates|{$url}", __NAMESPACE__); |
|
51 | + if (200 === $response->getStatusCode()) { |
|
52 | + $coordinates = \App\Json::decode($response->getBody()); |
|
53 | + } else { |
|
54 | + throw new \App\Exceptions\AppException('Error with connection |' . $response->getReasonPhrase() . '|' . $response->getBody()); |
|
55 | + } |
|
56 | + } catch (\Exception $ex) { |
|
57 | + \App\Log::error('Error - ' . $ex->getMessage(), __CLASS__); |
|
58 | + } |
|
59 | + return $coordinates; |
|
60 | + } |
|
61 | 61 | |
62 | - /** {@inheritdoc} */ |
|
63 | - public function getCoordinatesByValue(string $value): array |
|
64 | - { |
|
65 | - if (($coordinatesDetails = $this->getCoordinates(['q' => $value])) && ($coordinates = reset($coordinatesDetails)) && !empty($coordinates)) { |
|
66 | - return ['lat' => $coordinates['lat'], 'lon' => $coordinates['lon']]; |
|
67 | - } |
|
68 | - return []; |
|
69 | - } |
|
62 | + /** {@inheritdoc} */ |
|
63 | + public function getCoordinatesByValue(string $value): array |
|
64 | + { |
|
65 | + if (($coordinatesDetails = $this->getCoordinates(['q' => $value])) && ($coordinates = reset($coordinatesDetails)) && !empty($coordinates)) { |
|
66 | + return ['lat' => $coordinates['lat'], 'lon' => $coordinates['lon']]; |
|
67 | + } |
|
68 | + return []; |
|
69 | + } |
|
70 | 70 | } |
@@ -17,50 +17,50 @@ |
||
17 | 17 | */ |
18 | 18 | class YetiForce extends Base |
19 | 19 | { |
20 | - /** {@inheritdoc} */ |
|
21 | - public $url = 'YetiForce'; |
|
22 | - /** {@inheritdoc} */ |
|
23 | - public $infoUrl = 'index.php?module=YetiForce&parent=Settings&view=Shop&product=YetiForcePassword&mode=showProductModal'; |
|
20 | + /** {@inheritdoc} */ |
|
21 | + public $url = 'YetiForce'; |
|
22 | + /** {@inheritdoc} */ |
|
23 | + public $infoUrl = 'index.php?module=YetiForce&parent=Settings&view=Shop&product=YetiForcePassword&mode=showProductModal'; |
|
24 | 24 | |
25 | - /** {@inheritdoc} */ |
|
26 | - public function check(string $password): array |
|
27 | - { |
|
28 | - $status = ['status' => true]; |
|
29 | - $product = \App\YetiForce\Register::getProduct('YetiForcePassword'); |
|
30 | - if (empty($password) || !\App\RequestUtil::isNetConnection() || empty($product['params']['login']) || empty($product['params']['pass'])) { |
|
31 | - return $status; |
|
32 | - } |
|
33 | - try { |
|
34 | - $url = 'https://passwords.yetiforce.eu/pwned'; |
|
35 | - \App\Log::beginProfile("POST|YetiForce::check|{$url}", __NAMESPACE__); |
|
36 | - $request = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->request( |
|
37 | - 'POST', |
|
38 | - $url, |
|
39 | - ['json' => ['sha1' => sha1($password)], 'timeout' => 2, 'http_errors' => false, 'auth' => [$product['params']['login'], $product['params']['pass']], 'headers' => ['InsKey' => \App\YetiForce\Register::getInstanceKey()]] |
|
40 | - ); |
|
41 | - \App\Log::endProfile("POST|YetiForce::check|{$url}", __NAMESPACE__); |
|
42 | - if (200 === $request->getStatusCode()) { |
|
43 | - $response = \App\Json::decode($request->getBody()); |
|
44 | - if (isset($response['count'])) { |
|
45 | - $status = [ |
|
46 | - 'message' => \App\Language::translate('LBL_ALERT_PWNED_PASSWORD', 'Settings:Password'), |
|
47 | - 'status' => 0 === (int) $response['count'], |
|
48 | - ]; |
|
49 | - } elseif ($response['error']) { |
|
50 | - throw new \App\Exceptions\AppException('Error with response |' . $response['error']); |
|
51 | - } |
|
52 | - } else { |
|
53 | - throw new \App\Exceptions\AppException('Error with connection |' . $request->getReasonPhrase()); |
|
54 | - } |
|
55 | - } catch (\Exception $ex) { |
|
56 | - \App\Log::error($ex->getMessage(), __CLASS__); |
|
57 | - } |
|
58 | - return $status; |
|
59 | - } |
|
25 | + /** {@inheritdoc} */ |
|
26 | + public function check(string $password): array |
|
27 | + { |
|
28 | + $status = ['status' => true]; |
|
29 | + $product = \App\YetiForce\Register::getProduct('YetiForcePassword'); |
|
30 | + if (empty($password) || !\App\RequestUtil::isNetConnection() || empty($product['params']['login']) || empty($product['params']['pass'])) { |
|
31 | + return $status; |
|
32 | + } |
|
33 | + try { |
|
34 | + $url = 'https://passwords.yetiforce.eu/pwned'; |
|
35 | + \App\Log::beginProfile("POST|YetiForce::check|{$url}", __NAMESPACE__); |
|
36 | + $request = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->request( |
|
37 | + 'POST', |
|
38 | + $url, |
|
39 | + ['json' => ['sha1' => sha1($password)], 'timeout' => 2, 'http_errors' => false, 'auth' => [$product['params']['login'], $product['params']['pass']], 'headers' => ['InsKey' => \App\YetiForce\Register::getInstanceKey()]] |
|
40 | + ); |
|
41 | + \App\Log::endProfile("POST|YetiForce::check|{$url}", __NAMESPACE__); |
|
42 | + if (200 === $request->getStatusCode()) { |
|
43 | + $response = \App\Json::decode($request->getBody()); |
|
44 | + if (isset($response['count'])) { |
|
45 | + $status = [ |
|
46 | + 'message' => \App\Language::translate('LBL_ALERT_PWNED_PASSWORD', 'Settings:Password'), |
|
47 | + 'status' => 0 === (int) $response['count'], |
|
48 | + ]; |
|
49 | + } elseif ($response['error']) { |
|
50 | + throw new \App\Exceptions\AppException('Error with response |' . $response['error']); |
|
51 | + } |
|
52 | + } else { |
|
53 | + throw new \App\Exceptions\AppException('Error with connection |' . $request->getReasonPhrase()); |
|
54 | + } |
|
55 | + } catch (\Exception $ex) { |
|
56 | + \App\Log::error($ex->getMessage(), __CLASS__); |
|
57 | + } |
|
58 | + return $status; |
|
59 | + } |
|
60 | 60 | |
61 | - /** {@inheritdoc} */ |
|
62 | - public function isActive(): bool |
|
63 | - { |
|
64 | - return \App\YetiForce\Shop::check('YetiForcePassword'); |
|
65 | - } |
|
61 | + /** {@inheritdoc} */ |
|
62 | + public function isActive(): bool |
|
63 | + { |
|
64 | + return \App\YetiForce\Shop::check('YetiForcePassword'); |
|
65 | + } |
|
66 | 66 | } |
@@ -24,10 +24,10 @@ discard block |
||
24 | 24 | */ |
25 | 25 | public $listFields = [ |
26 | 26 | 'name' => 'LBL_NAME', |
27 | - 'email' => 'LBL_EMAIL', |
|
28 | - 'vat_id' => 'LBL_VAT_ID', |
|
29 | - 'country' => 'LBL_COUNTRY', |
|
30 | - 'industry' => 'LBL_INDUSTRY', |
|
27 | + 'email' => 'LBL_EMAIL', |
|
28 | + 'vat_id' => 'LBL_VAT_ID', |
|
29 | + 'country' => 'LBL_COUNTRY', |
|
30 | + 'industry' => 'LBL_INDUSTRY', |
|
31 | 31 | 'website' => 'LBL_WEBSITE', |
32 | 32 | ]; |
33 | 33 | |
@@ -38,7 +38,7 @@ discard block |
||
38 | 38 | */ |
39 | 39 | public static array $formFields = [ |
40 | 40 | 'name' => [], |
41 | - 'email' => [], |
|
41 | + 'email' => [], |
|
42 | 42 | 'vat_id' => [ |
43 | 43 | 'infoText' => 'LBL_VAT_ID_INFO', |
44 | 44 | ], |
@@ -17,28 +17,28 @@ |
||
17 | 17 | */ |
18 | 18 | class Settings_Magento_Edit_View extends Settings_Vtiger_Index_View |
19 | 19 | { |
20 | - /** {@inheritdoc} */ |
|
21 | - public function checkPermission(Request $request) |
|
22 | - { |
|
23 | - parent::checkPermission($request); |
|
24 | - if(!\App\YetiForce\Register::getProduct('YetiForceMagento')) { |
|
25 | - throw new \App\Exceptions\NoPermittedForAdmin('LBL_PERMISSION_DENIED'); |
|
26 | - } |
|
27 | - } |
|
28 | - /** {@inheritdoc} */ |
|
29 | - public function process(App\Request $request) |
|
30 | - { |
|
31 | - $moduleName = $request->getModule(false); |
|
32 | - $viewer = $this->getViewer($request); |
|
33 | - $record = !$request->isEmpty('record') ? $request->getInteger('record') : ''; |
|
34 | - if ($record) { |
|
35 | - $recordModel = Settings_Magento_Record_Model::getInstanceById($record); |
|
36 | - } else { |
|
37 | - $recordModel = Settings_Magento_Record_Model::getCleanInstance(); |
|
38 | - } |
|
39 | - $viewer->assign('RECORD_MODEL', $recordModel); |
|
40 | - $viewer->assign('RECORD_ID', $record); |
|
41 | - $viewer->assign('QUALIFIED_MODULE', $moduleName); |
|
42 | - $viewer->view('Edit.tpl', $moduleName); |
|
43 | - } |
|
20 | + /** {@inheritdoc} */ |
|
21 | + public function checkPermission(Request $request) |
|
22 | + { |
|
23 | + parent::checkPermission($request); |
|
24 | + if(!\App\YetiForce\Register::getProduct('YetiForceMagento')) { |
|
25 | + throw new \App\Exceptions\NoPermittedForAdmin('LBL_PERMISSION_DENIED'); |
|
26 | + } |
|
27 | + } |
|
28 | + /** {@inheritdoc} */ |
|
29 | + public function process(App\Request $request) |
|
30 | + { |
|
31 | + $moduleName = $request->getModule(false); |
|
32 | + $viewer = $this->getViewer($request); |
|
33 | + $record = !$request->isEmpty('record') ? $request->getInteger('record') : ''; |
|
34 | + if ($record) { |
|
35 | + $recordModel = Settings_Magento_Record_Model::getInstanceById($record); |
|
36 | + } else { |
|
37 | + $recordModel = Settings_Magento_Record_Model::getCleanInstance(); |
|
38 | + } |
|
39 | + $viewer->assign('RECORD_MODEL', $recordModel); |
|
40 | + $viewer->assign('RECORD_ID', $record); |
|
41 | + $viewer->assign('QUALIFIED_MODULE', $moduleName); |
|
42 | + $viewer->view('Edit.tpl', $moduleName); |
|
43 | + } |
|
44 | 44 | } |
@@ -12,88 +12,88 @@ |
||
12 | 12 | */ |
13 | 13 | class OpenStreetMap_TileLayer_File extends Vtiger_Basic_File |
14 | 14 | { |
15 | - /** {@inheritdoc} */ |
|
16 | - public function getCheckPermission(App\Request $request) |
|
17 | - { |
|
18 | - if (!\App\Privilege::isPermitted('OpenStreetMap')) { |
|
19 | - throw new \App\Exceptions\NoPermitted('LBL_PERMISSION_DENIED', 406); |
|
20 | - } |
|
21 | - return true; |
|
22 | - } |
|
15 | + /** {@inheritdoc} */ |
|
16 | + public function getCheckPermission(App\Request $request) |
|
17 | + { |
|
18 | + if (!\App\Privilege::isPermitted('OpenStreetMap')) { |
|
19 | + throw new \App\Exceptions\NoPermitted('LBL_PERMISSION_DENIED', 406); |
|
20 | + } |
|
21 | + return true; |
|
22 | + } |
|
23 | 23 | |
24 | - /** |
|
25 | - * Download layer and show. |
|
26 | - * |
|
27 | - * @param \App\Request $request |
|
28 | - * |
|
29 | - * @return bool |
|
30 | - */ |
|
31 | - public function get(App\Request $request) |
|
32 | - { |
|
33 | - if (!\App\RequestUtil::isNetConnection()) { |
|
34 | - $this->error(); |
|
35 | - return false; |
|
36 | - } |
|
37 | - $product = \App\YetiForce\Register::getProduct('YetiForceMap'); |
|
38 | - if ((empty($product['params']['login']) || empty($product['params']['pass'])) && empty($product['params']['token'])) { |
|
39 | - $this->error('map_server_not_purchased'); |
|
40 | - return false; |
|
41 | - } |
|
42 | - $url = str_replace(['{z}', '{x}', '{y}'], [ |
|
43 | - $request->getByType('z', 'Integer'), |
|
44 | - $request->getByType('x', 'Integer'), |
|
45 | - $request->getByType('y', 'Integer'), |
|
46 | - ], 'https://osm-tile.yetiforce.eu/tile/{z}/{x}/{y}.png'); |
|
47 | - $options = [ |
|
48 | - 'timeout' => 60, |
|
49 | - 'headers' => [ |
|
50 | - 'InsKey' => \App\YetiForce\Register::getInstanceKey() |
|
51 | - ] |
|
52 | - ]; |
|
53 | - if (isset($product['params']['token'])) { |
|
54 | - $url += '?yf_token=' . $product['params']['token']; |
|
55 | - } else { |
|
56 | - $options['auth'] = [$product['params']['login'], $product['params']['pass']]; |
|
57 | - } |
|
58 | - try { |
|
59 | - \App\Log::beginProfile("GET|TileLayer::get|{$url}", __NAMESPACE__); |
|
60 | - $response = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->request('GET', $url, $options); |
|
61 | - \App\Log::endProfile("GET|TileLayer::get|{$url}", __NAMESPACE__); |
|
62 | - if (200 !== $response->getStatusCode()) { |
|
63 | - \App\Log::error($url . ' | Error: ' . $response->getReasonPhrase(), __CLASS__); |
|
64 | - $this->error(); |
|
65 | - return false; |
|
66 | - } |
|
67 | - $body = $response->getBody(); |
|
68 | - header('pragma: public'); |
|
69 | - header('cache-control: max-age=86400, public'); |
|
70 | - header('expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 86400)); |
|
71 | - header('content-type: image/png'); |
|
72 | - header('content-transfer-encoding: binary'); |
|
73 | - header('content-length: ' . $body->getSize()); |
|
74 | - echo $body->getContents(); |
|
75 | - } catch (\Throwable $ex) { |
|
76 | - \App\Log::error($url . ' | Error: ' . $ex->getMessage(), __CLASS__); |
|
77 | - $this->error(); |
|
78 | - } |
|
79 | - } |
|
24 | + /** |
|
25 | + * Download layer and show. |
|
26 | + * |
|
27 | + * @param \App\Request $request |
|
28 | + * |
|
29 | + * @return bool |
|
30 | + */ |
|
31 | + public function get(App\Request $request) |
|
32 | + { |
|
33 | + if (!\App\RequestUtil::isNetConnection()) { |
|
34 | + $this->error(); |
|
35 | + return false; |
|
36 | + } |
|
37 | + $product = \App\YetiForce\Register::getProduct('YetiForceMap'); |
|
38 | + if ((empty($product['params']['login']) || empty($product['params']['pass'])) && empty($product['params']['token'])) { |
|
39 | + $this->error('map_server_not_purchased'); |
|
40 | + return false; |
|
41 | + } |
|
42 | + $url = str_replace(['{z}', '{x}', '{y}'], [ |
|
43 | + $request->getByType('z', 'Integer'), |
|
44 | + $request->getByType('x', 'Integer'), |
|
45 | + $request->getByType('y', 'Integer'), |
|
46 | + ], 'https://osm-tile.yetiforce.eu/tile/{z}/{x}/{y}.png'); |
|
47 | + $options = [ |
|
48 | + 'timeout' => 60, |
|
49 | + 'headers' => [ |
|
50 | + 'InsKey' => \App\YetiForce\Register::getInstanceKey() |
|
51 | + ] |
|
52 | + ]; |
|
53 | + if (isset($product['params']['token'])) { |
|
54 | + $url += '?yf_token=' . $product['params']['token']; |
|
55 | + } else { |
|
56 | + $options['auth'] = [$product['params']['login'], $product['params']['pass']]; |
|
57 | + } |
|
58 | + try { |
|
59 | + \App\Log::beginProfile("GET|TileLayer::get|{$url}", __NAMESPACE__); |
|
60 | + $response = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->request('GET', $url, $options); |
|
61 | + \App\Log::endProfile("GET|TileLayer::get|{$url}", __NAMESPACE__); |
|
62 | + if (200 !== $response->getStatusCode()) { |
|
63 | + \App\Log::error($url . ' | Error: ' . $response->getReasonPhrase(), __CLASS__); |
|
64 | + $this->error(); |
|
65 | + return false; |
|
66 | + } |
|
67 | + $body = $response->getBody(); |
|
68 | + header('pragma: public'); |
|
69 | + header('cache-control: max-age=86400, public'); |
|
70 | + header('expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 86400)); |
|
71 | + header('content-type: image/png'); |
|
72 | + header('content-transfer-encoding: binary'); |
|
73 | + header('content-length: ' . $body->getSize()); |
|
74 | + echo $body->getContents(); |
|
75 | + } catch (\Throwable $ex) { |
|
76 | + \App\Log::error($url . ' | Error: ' . $ex->getMessage(), __CLASS__); |
|
77 | + $this->error(); |
|
78 | + } |
|
79 | + } |
|
80 | 80 | |
81 | - /** |
|
82 | - * Error function. |
|
83 | - * |
|
84 | - * @param string $type |
|
85 | - * |
|
86 | - * @return void |
|
87 | - */ |
|
88 | - public function error(string $type = 'map_server_unavailable'): void |
|
89 | - { |
|
90 | - $fileName = ROOT_DIRECTORY . "/public_html/layouts/basic/images/{$type}.png"; |
|
91 | - header('pragma: public'); |
|
92 | - header('cache-control: max-age=86400, public'); |
|
93 | - header('expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 86400)); |
|
94 | - header('content-type: ' . \App\Fields\File::getMimeContentType($fileName)); |
|
95 | - header('content-transfer-encoding: binary'); |
|
96 | - header('content-length: ' . filesize($fileName)); |
|
97 | - readfile($fileName); |
|
98 | - } |
|
81 | + /** |
|
82 | + * Error function. |
|
83 | + * |
|
84 | + * @param string $type |
|
85 | + * |
|
86 | + * @return void |
|
87 | + */ |
|
88 | + public function error(string $type = 'map_server_unavailable'): void |
|
89 | + { |
|
90 | + $fileName = ROOT_DIRECTORY . "/public_html/layouts/basic/images/{$type}.png"; |
|
91 | + header('pragma: public'); |
|
92 | + header('cache-control: max-age=86400, public'); |
|
93 | + header('expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 86400)); |
|
94 | + header('content-type: ' . \App\Fields\File::getMimeContentType($fileName)); |
|
95 | + header('content-transfer-encoding: binary'); |
|
96 | + header('content-length: ' . filesize($fileName)); |
|
97 | + readfile($fileName); |
|
98 | + } |
|
99 | 99 | } |