CRM-19132 add html type to contribution_recur fields
[civicrm-core.git] / Civi / Core / Paths.php
CommitLineData
e3d28c74
TO
1<?php
2namespace Civi\Core;
3
4/**
5 * Class Paths
6 * @package Civi\Core
7 *
8 * This paths class translates path-expressions into local file paths and
9 * URLs. Path-expressions may take a few forms:
10 *
11 * - Paths and URLs may use a variable prefix. For example, '[civicrm.files]/upload'
12 * - Paths and URLS may be absolute.
13 * - Paths may be relative (base dir: [civicrm.files]).
14 * - URLs may be relative (base dir: [cms.root]).
15 */
16class Paths {
17
18 const DEFAULT_URL = 'cms.root';
19 const DEFAULT_PATH = 'civicrm.files';
20
21 /**
22 * @var array
23 * Array(string $name => array(url => $, path => $)).
24 */
b698e2d5 25 private $variables = array();
e3d28c74 26
b698e2d5 27 private $variableFactory = array();
e3d28c74 28
e8e8f3ad 29 /**
30 * Class constructor.
31 */
e3d28c74
TO
32 public function __construct() {
33 $this
e3d28c74
TO
34 ->register('civicrm.root', function () {
35 return \CRM_Core_Config::singleton()->userSystem->getCiviSourceStorage();
36 })
37 ->register('civicrm.files', function () {
38 return \CRM_Core_Config::singleton()->userSystem->getDefaultFileStorage();
39 })
40 ->register('cms', function () {
41 return array(
42 'path' => \CRM_Core_Config::singleton()->userSystem->cmsRootPath(),
43 'url' => \CRM_Utils_System::baseCMSURL(),
44 );
45 })
46 ->register('cms.root', function () {
47 return array(
48 'path' => \CRM_Core_Config::singleton()->userSystem->cmsRootPath(),
49 // Misleading: this *removes* the language part of the URL, producing a pristine base URL.
50 'url' => \CRM_Utils_System::languageNegotiationURL(\CRM_Utils_System::baseCMSURL(), FALSE, TRUE),
51 );
52 });
53 }
54
55 /**
56 * Register a new URL/file path mapping.
57 *
58 * @param string $name
b698e2d5 59 * The name of the variable.
e3d28c74
TO
60 * @param callable $factory
61 * Function which returns an array with keys:
62 * - path: string.
63 * - url: string.
64 * @return $this
65 */
66 public function register($name, $factory) {
b698e2d5 67 $this->variableFactory[$name] = $factory;
e3d28c74
TO
68 return $this;
69 }
70
b698e2d5
TO
71 /**
72 * @param string $name
73 * Ex: 'civicrm.root'.
74 * @param string $attr
75 * Ex: 'url', 'path'.
76 * @return mixed
77 */
78 public function getVariable($name, $attr) {
79 if (!isset($this->variables[$name])) {
80 $this->variables[$name] = call_user_func($this->variableFactory[$name]);
e3d28c74 81 }
b698e2d5 82 if (!isset($this->variables[$name][$attr])) {
e3d28c74
TO
83 throw new \RuntimeException("Cannot resolve path using \"$name.$attr\"");
84 }
b698e2d5
TO
85 return $this->variables[$name][$attr];
86 }
87
e8e8f3ad 88 /**
89 * Does the variable exist.
90 *
91 * @param string $name
92 *
93 * @return bool
94 */
b698e2d5
TO
95 public function hasVariable($name) {
96 return isset($this->variableFactory[$name]);
e3d28c74
TO
97 }
98
99 /**
100 * Determine the absolute path to a file, given that the file is most likely
b698e2d5 101 * in a given particular variable.
e3d28c74
TO
102 *
103 * @param string $value
b698e2d5
TO
104 * The file path.
105 * Use "." to reference to default file root.
106 * Values may begin with a variable, e.g. "[civicrm.files]/upload".
e3d28c74
TO
107 * @return mixed|string
108 */
109 public function getPath($value) {
110 $defaultContainer = self::DEFAULT_PATH;
111 if ($value && $value{0} == '[' && preg_match(';^\[([a-zA-Z0-9\._]+)\]/(.*);', $value, $matches)) {
112 $defaultContainer = $matches[1];
113 $value = $matches[2];
114 }
115 if (empty($value)) {
116 return FALSE;
117 }
118 if ($value === '.') {
119 $value = '';
120 }
b698e2d5 121 return \CRM_Utils_File::absoluteDirectory($value, $this->getVariable($defaultContainer, 'path'));
e3d28c74
TO
122 }
123
124 /**
b698e2d5 125 * Determine the URL to a file.
e3d28c74
TO
126 *
127 * @param string $value
b698e2d5 128 * The file path. The path may begin with a variable, e.g. "[civicrm.files]/upload".
e3d28c74
TO
129 * @param string $preferFormat
130 * The preferred format ('absolute', 'relative').
131 * The result data may not meet the preference -- if the setting
132 * refers to an external domain, then the result will be
133 * absolute (regardless of preference).
134 * @param bool|NULL $ssl
135 * NULL to autodetect. TRUE to force to SSL.
136 * @return mixed|string
137 */
138 public function getUrl($value, $preferFormat = 'relative', $ssl = NULL) {
139 $defaultContainer = self::DEFAULT_URL;
ac47f7ca 140 if ($value && $value{0} == '[' && preg_match(';^\[([a-zA-Z0-9\._]+)\](/(.*))$;', $value, $matches)) {
e3d28c74 141 $defaultContainer = $matches[1];
ac47f7ca 142 $value = empty($matches[3]) ? '.' : $matches[3];
e3d28c74
TO
143 }
144
145 if (empty($value)) {
146 return FALSE;
147 }
148 if ($value === '.') {
149 $value = '';
150 }
151 if (substr($value, 0, 4) == 'http') {
152 return $value;
153 }
154
b698e2d5 155 $value = $this->getVariable($defaultContainer, 'url') . $value;
e3d28c74
TO
156
157 if ($preferFormat === 'relative') {
158 $parsed = parse_url($value);
159 if (isset($_SERVER['HTTP_HOST']) && isset($parsed['host']) && $_SERVER['HTTP_HOST'] == $parsed['host']) {
160 $value = $parsed['path'];
161 }
162 }
163
164 if ($ssl || ($ssl === NULL && \CRM_Utils_System::isSSL())) {
165 $value = str_replace('http://', 'https://', $value);
166 }
167
168 return $value;
169 }
170
171}