]> BookStack Code Mirror - bookstack/blob - app/helpers.php
Update entities.php
[bookstack] / app / helpers.php
1 <?php
2
3 use BookStack\Auth\Permissions\PermissionService;
4 use BookStack\Entities\Entity;
5 use BookStack\Ownable;
6
7 /**
8  * Get the path to a versioned file.
9  *
10  * @param  string $file
11  * @return string
12  * @throws Exception
13  */
14 function versioned_asset($file = '')
15 {
16     static $version = null;
17
18     if (is_null($version)) {
19         $versionFile = base_path('version');
20         $version = trim(file_get_contents($versionFile));
21     }
22
23     $additional = '';
24     if (config('app.env') === 'development') {
25         $additional = sha1_file(public_path($file));
26     }
27
28     $path = $file . '?version=' . urlencode($version) . $additional;
29     return baseUrl($path);
30 }
31
32 /**
33  * Helper method to get the current User.
34  * Defaults to public 'Guest' user if not logged in.
35  * @return \BookStack\Auth\User
36  */
37 function user()
38 {
39     return auth()->user() ?: \BookStack\Auth\User::getDefault();
40 }
41
42 /**
43  * Check if current user is a signed in user.
44  * @return bool
45  */
46 function signedInUser() : bool
47 {
48     return auth()->user() && !auth()->user()->isDefault();
49 }
50
51 /**
52  * Check if the current user has general access.
53  * @return bool
54  */
55 function hasAppAccess() : bool
56 {
57     return !auth()->guest() || setting('app-public');
58 }
59
60 /**
61  * Check if the current user has a permission.
62  * If an ownable element is passed in the jointPermissions are checked against
63  * that particular item.
64  * @param string $permission
65  * @param Ownable $ownable
66  * @return mixed
67  */
68 function userCan(string $permission, Ownable $ownable = null)
69 {
70     if ($ownable === null) {
71         return user() && user()->can($permission);
72     }
73
74     // Check permission on ownable item
75     $permissionService = app(PermissionService::class);
76     return $permissionService->checkOwnableUserAccess($ownable, $permission);
77 }
78
79 /**
80  * Check if the current user has the given permission
81  * on any item in the system.
82  * @param string $permission
83  * @param string|null $entityClass
84  * @return bool
85  */
86 function userCanOnAny(string $permission, string $entityClass = null)
87 {
88     $permissionService = app(PermissionService::class);
89     return $permissionService->checkUserHasPermissionOnAnything($permission, $entityClass);
90 }
91
92 /**
93  * Helper to access system settings.
94  * @param $key
95  * @param bool $default
96  * @return bool|string|\BookStack\Settings\SettingService
97  */
98 function setting($key = null, $default = false)
99 {
100     $settingService = resolve(\BookStack\Settings\SettingService::class);
101     if (is_null($key)) {
102         return $settingService;
103     }
104     return $settingService->get($key, $default);
105 }
106
107 /**
108  * Helper to create url's relative to the applications root path.
109  * @param string $path
110  * @param bool $forceAppDomain
111  * @return string
112  */
113 function baseUrl($path, $forceAppDomain = false)
114 {
115     $isFullUrl = strpos($path, 'http') === 0;
116     if ($isFullUrl && !$forceAppDomain) {
117         return $path;
118     }
119
120     $path = trim($path, '/');
121     $base = rtrim(config('app.url'), '/');
122
123     // Remove non-specified domain if forced and we have a domain
124     if ($isFullUrl && $forceAppDomain) {
125         if (!empty($base) && strpos($path, $base) === 0) {
126             $path = trim(substr($path, strlen($base) - 1));
127         }
128         $explodedPath = explode('/', $path);
129         $path = implode('/', array_splice($explodedPath, 3));
130     }
131
132     // Return normal url path if not specified in config
133     if (config('app.url') === '') {
134         return url($path);
135     }
136
137     return $base . '/' . $path;
138 }
139
140 /**
141  * Get an instance of the redirector.
142  * Overrides the default laravel redirect helper.
143  * Ensures it redirects even when the app is in a subdirectory.
144  *
145  * @param  string|null  $to
146  * @param  int     $status
147  * @param  array   $headers
148  * @param  bool    $secure
149  * @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
150  */
151 function redirect($to = null, $status = 302, $headers = [], $secure = null)
152 {
153     if (is_null($to)) {
154         return app('redirect');
155     }
156
157     $to = baseUrl($to);
158
159     return app('redirect')->to($to, $status, $headers, $secure);
160 }
161
162 /**
163  * Get a path to a theme resource.
164  * @param string $path
165  * @return string|boolean
166  */
167 function theme_path($path = '')
168 {
169     $theme = config('view.theme');
170     if (!$theme) {
171         return false;
172     }
173
174     return base_path('themes/' . $theme .($path ? DIRECTORY_SEPARATOR.$path : $path));
175 }
176
177 /**
178  * Get fetch an SVG icon as a string.
179  * Checks for icons defined within a custom theme before defaulting back
180  * to the 'resources/assets/icons' folder.
181  *
182  * Returns an empty string if icon file not found.
183  * @param $name
184  * @param array $attrs
185  * @return mixed
186  */
187 function icon($name, $attrs = [])
188 {
189     $attrs = array_merge([
190         'class' => 'svg-icon',
191         'data-icon' => $name
192     ], $attrs);
193     $attrString = ' ';
194     foreach ($attrs as $attrName => $attr) {
195         $attrString .=  $attrName . '="' . $attr . '" ';
196     }
197
198     $iconPath = resource_path('assets/icons/' . $name . '.svg');
199     $themeIconPath = theme_path('icons/' . $name . '.svg');
200     if ($themeIconPath && file_exists($themeIconPath)) {
201         $iconPath = $themeIconPath;
202     } else if (!file_exists($iconPath)) {
203         return '';
204     }
205
206     $fileContents = file_get_contents($iconPath);
207     return  str_replace('<svg', '<svg' . $attrString, $fileContents);
208 }
209
210 /**
211  * Generate a url with multiple parameters for sorting purposes.
212  * Works out the logic to set the correct sorting direction
213  * Discards empty parameters and allows overriding.
214  * @param $path
215  * @param array $data
216  * @param array $overrideData
217  * @return string
218  */
219 function sortUrl($path, $data, $overrideData = [])
220 {
221     $queryStringSections = [];
222     $queryData = array_merge($data, $overrideData);
223
224     // Change sorting direction is already sorted on current attribute
225     if (isset($overrideData['sort']) && $overrideData['sort'] === $data['sort']) {
226         $queryData['order'] = ($data['order'] === 'asc') ? 'desc' : 'asc';
227     } else {
228         $queryData['order'] = 'asc';
229     }
230
231     foreach ($queryData as $name => $value) {
232         $trimmedVal = trim($value);
233         if ($trimmedVal === '') {
234             continue;
235         }
236         $queryStringSections[] = urlencode($name) . '=' . urlencode($trimmedVal);
237     }
238
239     if (count($queryStringSections) === 0) {
240         return $path;
241     }
242
243     return baseUrl($path . '?' . implode('&', $queryStringSections));
244 }