GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — develop (#163)
by
unknown
09:22
created
myth/Docs/Builder.php 1 patch
Indentation   +718 added lines, -718 removed lines patch added patch discarded remove patch
@@ -60,725 +60,725 @@
 block discarded – undo
60 60
 class Builder implements DocBuilderInterface
61 61
 {
62 62
 
63
-    protected $docs_ext = '.md';
64
-
65
-    protected $ignore_files = ['_404.md'];
66
-
67
-    protected $doc_folders = [];
68
-
69
-    /**
70
-     * Stores the current folder alias,
71
-     * once the file has been found.
72
-     *
73
-     * @var null
74
-     */
75
-    protected $current_folder = null;
76
-
77
-    protected $table_classes = 'table table-hover';
78
-
79
-    protected $apppath = '';
80
-
81
-    protected $formatters = [];
82
-
83
-    protected $page_title = null;
84
-
85
-    //--------------------------------------------------------------------
86
-
87
-    public function __construct($config = array())
88
-    {
89
-        $this->apppath = ! empty($config['apppath']) ? rtrim($config['apppath'], '/') . '/' : '';
90
-    }
91
-
92
-    //--------------------------------------------------------------------
93
-
94
-    public function pageTitle()
95
-    {
96
-        return $this->page_title;
97
-    }
98
-
99
-    //--------------------------------------------------------------------
100
-
101
-
102
-
103
-    /**
104
-     * Does the actual work of reading in and parsing the help file.
105
-     * If a folder Nickname (see addDocFolder() ) is passed as the second parameter,
106
-     * it will limit it's search to that single folder. If nothing is passed, it will
107
-     * search through all of the folders in the order they were given to the library,
108
-     * until it finds the first one.
109
-     *
110
-     * @param string $path The 'path' of the file (relative to the docs
111
-     *                                 folder. Usually from the URI)
112
-     * @param string $restrictToFolder (Optional) The folder nickname
113
-     *
114
-     * @return string
115
-     */
116
-    public function readPage($path, $restrictToFolder = null)
117
-    {
118
-        // Clean up our path
119
-        $path = trim($path, '/ ');
120
-
121
-        $content = $this->locateAndReadFile($path, $restrictToFolder);
122
-
123
-        $content = $this->parse($content);
124
-
125
-        return $content;
126
-    }
127
-
128
-    //--------------------------------------------------------------------
129
-
130
-    /**
131
-     * Parses the contents. Currently runs through the Markdown Extended
132
-     * parser to convert to HTML.
133
-     *
134
-     * @param $str
135
-     * @return mixed
136
-     */
137
-    public function parse($str)
138
-    {
139
-        return $this->format($str);
140
-    }
141
-
142
-    //--------------------------------------------------------------------
143
-
144
-    /**
145
-     * Perform a few housekeeping tasks on a page, like rewriting URLs to full
146
-     * URLs, not relative, ensuring they link correctly, etc.
147
-     *
148
-     * @param      $content
149
-     * @param null $site_url
150
-     * @param null $current_url
151
-     * @return string   The post-processed HTML.
152
-     */
153
-    public function postProcess($content, $site_url = null, $current_url = null)
154
-    {
155
-        if (empty($content)) {
156
-            return $content;
157
-        }
158
-
159
-        try {
160
-            $xml = new \SimpleXMLElement('<?xml version="1.0" standalone="yes"?><div>' . $content . '</div>');
161
-        } catch (\Exception $e) {
162
-            // SimpleXML barfed on us, so send back the un-modified content
163
-            return $content;
164
-        }
165
-
166
-        // Prepare some things and cleanup others
167
-        $groups = array_keys($this->doc_folders);
168
-        $site_url = rtrim($site_url, '/') . '/';
169
-        $current_url = rtrim($current_url, '#/');
170
-
171
-        // Try to determine the current_url if one isn't set.
172
-        if (empty($this->current_folder)) {
173
-            $this->current_folder = $this->detectCurrentFolder($current_url, $groups);
174
-        }
175
-
176
-        /*
63
+	protected $docs_ext = '.md';
64
+
65
+	protected $ignore_files = ['_404.md'];
66
+
67
+	protected $doc_folders = [];
68
+
69
+	/**
70
+	 * Stores the current folder alias,
71
+	 * once the file has been found.
72
+	 *
73
+	 * @var null
74
+	 */
75
+	protected $current_folder = null;
76
+
77
+	protected $table_classes = 'table table-hover';
78
+
79
+	protected $apppath = '';
80
+
81
+	protected $formatters = [];
82
+
83
+	protected $page_title = null;
84
+
85
+	//--------------------------------------------------------------------
86
+
87
+	public function __construct($config = array())
88
+	{
89
+		$this->apppath = ! empty($config['apppath']) ? rtrim($config['apppath'], '/') . '/' : '';
90
+	}
91
+
92
+	//--------------------------------------------------------------------
93
+
94
+	public function pageTitle()
95
+	{
96
+		return $this->page_title;
97
+	}
98
+
99
+	//--------------------------------------------------------------------
100
+
101
+
102
+
103
+	/**
104
+	 * Does the actual work of reading in and parsing the help file.
105
+	 * If a folder Nickname (see addDocFolder() ) is passed as the second parameter,
106
+	 * it will limit it's search to that single folder. If nothing is passed, it will
107
+	 * search through all of the folders in the order they were given to the library,
108
+	 * until it finds the first one.
109
+	 *
110
+	 * @param string $path The 'path' of the file (relative to the docs
111
+	 *                                 folder. Usually from the URI)
112
+	 * @param string $restrictToFolder (Optional) The folder nickname
113
+	 *
114
+	 * @return string
115
+	 */
116
+	public function readPage($path, $restrictToFolder = null)
117
+	{
118
+		// Clean up our path
119
+		$path = trim($path, '/ ');
120
+
121
+		$content = $this->locateAndReadFile($path, $restrictToFolder);
122
+
123
+		$content = $this->parse($content);
124
+
125
+		return $content;
126
+	}
127
+
128
+	//--------------------------------------------------------------------
129
+
130
+	/**
131
+	 * Parses the contents. Currently runs through the Markdown Extended
132
+	 * parser to convert to HTML.
133
+	 *
134
+	 * @param $str
135
+	 * @return mixed
136
+	 */
137
+	public function parse($str)
138
+	{
139
+		return $this->format($str);
140
+	}
141
+
142
+	//--------------------------------------------------------------------
143
+
144
+	/**
145
+	 * Perform a few housekeeping tasks on a page, like rewriting URLs to full
146
+	 * URLs, not relative, ensuring they link correctly, etc.
147
+	 *
148
+	 * @param      $content
149
+	 * @param null $site_url
150
+	 * @param null $current_url
151
+	 * @return string   The post-processed HTML.
152
+	 */
153
+	public function postProcess($content, $site_url = null, $current_url = null)
154
+	{
155
+		if (empty($content)) {
156
+			return $content;
157
+		}
158
+
159
+		try {
160
+			$xml = new \SimpleXMLElement('<?xml version="1.0" standalone="yes"?><div>' . $content . '</div>');
161
+		} catch (\Exception $e) {
162
+			// SimpleXML barfed on us, so send back the un-modified content
163
+			return $content;
164
+		}
165
+
166
+		// Prepare some things and cleanup others
167
+		$groups = array_keys($this->doc_folders);
168
+		$site_url = rtrim($site_url, '/') . '/';
169
+		$current_url = rtrim($current_url, '#/');
170
+
171
+		// Try to determine the current_url if one isn't set.
172
+		if (empty($this->current_folder)) {
173
+			$this->current_folder = $this->detectCurrentFolder($current_url, $groups);
174
+		}
175
+
176
+		/*
177 177
          * Rewrite the URLs
178 178
          */
179
-        foreach ($xml->xpath('//a') as $link) {
180
-            $link = $this->reformatAnchor($link, $groups, $current_url, $site_url);
181
-        }
182
-
183
-        $content = $xml->asXML();
184
-        $content = trim(str_replace('<?xml version="1.0" standalone="yes"?>', '', $content));
185
-
186
-        // Clean up and style the tables
187
-        $content = str_replace('<table>', '<table class="' . $this->table_classes . '">', $content);
188
-
189
-        return $content;
190
-    }
191
-    //--------------------------------------------------------------------
192
-
193
-    /**
194
-     * Allows users to define the classes that are attached to
195
-     * generated tables.
196
-     *
197
-     * @param null $classes
198
-     * @return $this
199
-     */
200
-    public function setTableClasses($classes = null)
201
-    {
202
-        $this->table_classes = $classes;
203
-
204
-        return $this;
205
-    }
206
-
207
-    //--------------------------------------------------------------------
208
-
209
-    /**
210
-     * Given the contents to render, will build a list of links for the sidebar
211
-     * out of the headings in the file.
212
-     *
213
-     * Note: Will ONLY use h2 and h3 to build the links from.
214
-     *
215
-     * Note: The $content passed in WILL be modified by adding named anchors
216
-     * that match up with the locations.
217
-     *
218
-     * @param string $content The HTML to analyse for headings.
219
-     * @return string
220
-     */
221
-    public function buildDocumentMap(&$content)
222
-    {
223
-        if (empty($content)) {
224
-            return $content;
225
-        }
226
-
227
-        // If $content already has a wrapping <div> and </div> tags, remove them,
228
-        // since we'll replace them just below.
229
-        if (strpos($content, '<div>') === 0) {
230
-            $content = substr($content, 5);
231
-
232
-            // Trailing div also?
233
-            if (substr($content, -6) == '</div>') {
234
-                $content = substr($content, 0, -6);
235
-            }
236
-        }
237
-
238
-        try {
239
-            $xml = new \SimpleXMLElement('<?xml version="1.0" standalone="yes"?><div>' . $content . '</div>');
240
-        } catch (\Exception $e) {
241
-            // SimpleXML barfed on us, so send back the un-modified content
242
-            return [];
243
-        }
244
-
245
-        $map = [];
246
-        list($map, $content) = $this->extractDocMapAndAddAnchors($content, $xml, $map);
247
-
248
-        return $map;
249
-    }
250
-
251
-    //--------------------------------------------------------------------
252
-
253
-    /**
254
-     * Stores the name of the callback method to run to convert the source
255
-     * files to viewable files. By default, this should be used to register
256
-     * a Mardown Extended formatter with the system, but could be used to
257
-     * extend the
258
-     *
259
-     * @param string $callback
260
-     * @param bool $cascade // If FALSE the formatting of a component ends here. If TRUE, will be passed to next formatter.
261
-     * @return $this
262
-     */
263
-    public function registerFormatter($callback = null, $cascade = false)
264
-    {
265
-        if (empty($callback)) return;
266
-
267
-        $this->formatters[] = [
268
-            'callable' => $callback,
269
-            'cascade'  => (bool)$cascade
270
-        ];
271
-
272
-        return $this;
273
-    }
274
-
275
-    //--------------------------------------------------------------------
276
-
277
-    /**
278
-     * Runs the text through the registered formatters.
279
-     *
280
-     * @param $str
281
-     * @return mixed
282
-     */
283
-    public function format($str)
284
-    {
285
-        if (! is_array($this->formatters)) return $str;
286
-
287
-        foreach ($this->formatters as $formatter) {
288
-            $method = $formatter['callable'];
289
-            $cascade = $formatter['cascade'];
290
-
291
-            $str = call_user_func($method, $str);
292
-
293
-            if (! $cascade) return $str;
294
-        }
295
-
296
-        return $str;
297
-    }
298
-
299
-    //--------------------------------------------------------------------
300
-
301
-    //--------------------------------------------------------------------
302
-    // Table of Contents methods
303
-    //--------------------------------------------------------------------
304
-
305
-    /**
306
-     * Retrieves the list of files in a folder and preps the name and filename
307
-     * so it's ready for creating the HTML.
308
-     *
309
-     * @param  String $folder The path to the folder to retrieve.
310
-     *
311
-     * @return Array  An associative array @see parse_ini_file for format
312
-     * details.
313
-     */
314
-    public function buildTOC($folder)
315
-    {
316
-        // If the toc file exists in the folder, use it to build the links.
317
-        if (is_file("{$folder}/_toc.ini")) {
318
-            $toc = parse_ini_file("{$folder}/_toc.ini", true);
319
-            return $this->columnizeTOC($toc);
320
-        }
321
-
322
-        // If the toc file does not exist, build the links by listing the files
323
-        // in the directory (and any sub-directories)
324
-        $map = $this->directory_map($folder);
325
-
326
-        // If directory_map can not open the directory or find any files inside
327
-        // the directory, return an empty array.
328
-        if (empty($map)) {
329
-            return [];
330
-        }
331
-
332
-        // If these docs are located in the /application/docs or /bonfire/docs
333
-        // directory, just use $this->current_group for the root.
334
-        // Module docs need $this->current_group and $type.
335
-        $tocRoot = $this->current_folder;
336
-        if ($this->current_folder != strtolower($folder)) {
337
-            $tocRoot .= '/' . strtolower($folder);
338
-        }
339
-
340
-        $toc = [];
341
-        foreach ($map as $files) {
342
-            // If $files isn't an array, then make it one so that all situations
343
-            // may be dealt with cleanly.
344
-            if (! is_array($files)) {
345
-                $files = [$files];
346
-            }
347
-
348
-            foreach ($files as $file) {
349
-                if (in_array($file, $this->ignore_files)) {
350
-                    continue;
351
-                }
352
-
353
-                // The title for the index is the passed $type. Otherwise,
354
-                // build the title from the file's name.
355
-                if (strpos($file, 'index') === false) {
356
-                    $title = str_replace($this->docs_ext, '', $file);
357
-                    $title = str_replace('_', ' ', $title);
358
-                    $title = ucwords($title);
359
-
360
-                    $toc["{$tocRoot}/{$file}"] = $title;
361
-                } else {
362
-                    $toc[$tocRoot] = $type;
363
-                }
364
-            }
365
-        }
366
-
367
-        $toc = $this->columnizeTOC($toc);
368
-
369
-        return $toc;
370
-    }
371
-
372
-    //--------------------------------------------------------------------
373
-
374
-    /**
375
-     * Sorts the passed TOC array into columns of as close to equal length
376
-     * as we can get it.
377
-     *
378
-     * @param $toc
379
-     * @return array
380
-     */
381
-    protected function columnizeTOC($toc)
382
-    {
383
-        $section_count = count($toc);
384
-
385
-        // First - determine the size of each 'section'.
386
-        $sizes = [];
387
-
388
-        foreach ($toc as $section => $chapters) {
389
-            $sizes[] = count($chapters);
390
-        }
391
-
392
-        $column_avg = (int)round(array_sum($sizes) / $section_count);
393
-
394
-        // Split things into 4 columns of approximately equal size.
395
-        // If we only have 4 columns (or less), then make sure to
396
-        // deal with that also.
397
-        $columns = [];
398
-
399
-        $current_column = 0;
400
-        $current_column_count = 0;
401
-        $keys = array_keys($toc);
402
-
403
-        for ($i = 0; $i <= $section_count; $i++) {
404
-            if (! isset($keys[$i])) {
405
-                continue;
406
-            }
407
-
408
-            $section = array_shift($toc);
409
-
410
-            // Can we stay in this column?
411
-            if ($current_column_count <= $column_avg && $section_count > 4) {
412
-                // Don't forget to account for the heading also.
413
-                $current_column_count += count($section) + 1;
414
-            } else {
415
-                $current_column_count = 0;
416
-                $current_column++;
417
-            }
418
-
419
-            $columns[$current_column][$keys[$i]] = $section;
420
-        }
421
-
422
-        return $columns;
423
-    }
424
-
425
-    //--------------------------------------------------------------------
426
-
427
-    //--------------------------------------------------------------------
428
-    // Folder Methods
429
-    //--------------------------------------------------------------------
430
-
431
-    /**
432
-     * Returns the current docFolders array.
433
-     *
434
-     * @return array
435
-     */
436
-    public function docFolders()
437
-    {
438
-        return $this->doc_folders;
439
-    }
440
-
441
-    //--------------------------------------------------------------------
442
-
443
-    /**
444
-     * Registers a path to be used when searching for documentation files.
445
-     *
446
-     * @param $name     A nickname to reference it by later.
447
-     * @param $path     The server path to the folder.
448
-     * @return $this
449
-     */
450
-    public function addDocFolder($name, $path)
451
-    {
452
-        // Standardize the path
453
-        $path = realpath($path) . '/';
454
-
455
-        // realpath will return FALSE if the path doesn't exist
456
-        // or the script doesn't have access to it.
457
-        if (! $path || $path == '/') {
458
-            return $this;
459
-        }
460
-
461
-        $name = strtolower($name);
462
-
463
-        $this->doc_folders[$name] = $path;
464
-
465
-        return $this;
466
-    }
467
-
468
-    //--------------------------------------------------------------------
469
-
470
-    /**
471
-     * Removes a folder from the folders we scan for documentation files
472
-     * within.
473
-     *
474
-     * @param $name
475
-     * @return $this
476
-     */
477
-    public function removeDocFolder($name)
478
-    {
479
-        $name = strtolower($name);
480
-
481
-        if (isset($this->doc_folders[$name])) {
482
-            unset($this->doc_folders[$name]);
483
-        }
484
-
485
-        return $this;
486
-    }
487
-
488
-    //--------------------------------------------------------------------
489
-
490
-    //--------------------------------------------------------------------
491
-    // Private Methods
492
-    //--------------------------------------------------------------------
493
-
494
-    /**
495
-     * Analyzes the passed in current url string and checks against
496
-     * a list of groups to determine what the current group is.
497
-     *
498
-     * @param $current_url
499
-     * @param $groups
500
-     * @return string
501
-     */
502
-    protected function detectCurrentFolder($current_url, $groups = [])
503
-    {
504
-        if (! is_array($groups)) {
505
-            return null;
506
-        }
507
-
508
-        $segments = explode('/', $current_url);
509
-
510
-        // We start from the back of the array since
511
-        // that's most likely to be close to the end.
512
-        $segments = array_reverse($segments);
513
-
514
-        foreach ($segments as $segment) {
515
-            foreach ($groups as $group) {
516
-                if (strtolower($group) == strtolower($segment)) {
517
-                    return $group;
518
-                }
519
-            }
520
-        }
521
-
522
-        // Nothing found?
523
-        return null;
524
-    }
525
-
526
-    //--------------------------------------------------------------------
527
-
528
-    //--------------------------------------------------------------------
529
-    // Private Methods
530
-    //--------------------------------------------------------------------
531
-
532
-    /**
533
-     * Locates the file on disk and reads the contents into a single string.
534
-     *
535
-     * If a folder Nickname (see addDocFolder() ) is passed as the second parameter,
536
-     * it will limit it's search to that single folder. If nothing is passed, it will
537
-     * search through all of the folders in the order they were given to the library,
538
-     * until it finds the first one.
539
-     *
540
-     * @param string $path The 'path' of the file (relative to the docs
541
-     *                                 folder. Usually from the URI)
542
-     * @param string $restrictToFolder (Optional) The nickname of one of the
543
-     *                                 folders to restrict the search to.
544
-     *
545
-     * @throws RuntimeException
546
-     * @return null|string
547
-     */
548
-    private function locateAndReadFile($path, $restrictToFolder = null)
549
-    {
550
-        $folders = $this->doc_folders;
551
-
552
-        if (! is_null($restrictToFolder)) {
553
-            // Make sure the folder exists
554
-            if (! is_null($restrictToFolder) && ! isset($this->doc_folders[$restrictToFolder])) {
555
-                throw new \RuntimeException('You must add the docs folder that you wish to find docs from.');
556
-            }
557
-
558
-            $folders = [$this->doc_folders[$restrictToFolder]];
559
-        }
560
-
561
-        foreach ($folders as $alias => $folder) {
562
-            if (file_exists($folder . $path . $this->docs_ext)) {
563
-                // Store the alias so we know which folder we're in.
564
-                $this->current_folder = $alias;
565
-
566
-                return file_get_contents($folder . $path . $this->docs_ext);
567
-            }
568
-        }
569
-
570
-        return null;
571
-    }
572
-
573
-    //--------------------------------------------------------------------
574
-
575
-    /**
576
-     * Re-formats the passed in link.
577
-     *
578
-     * @param $link
579
-     * @param $current_url
580
-     * @param $site_url
581
-     * @return mixed
582
-     */
583
-    private function reformatAnchor($link, $groups, $current_url, $site_url)
584
-    {
585
-        // Grab the href value.
586
-        $href = $link->attributes()->href;
587
-
588
-        // If the href is null, it's probably a named anchor with no content.
589
-        if (! $href) {
590
-            // Make sure it has an href, else the XML will not close this
591
-            // tag correctly.
592
-            $link['href'] = ' ';
593
-
594
-            return $link;
595
-        }
596
-
597
-        // Remove any trailing # signs
598
-        $href = rtrim($href, '# ');
599
-
600
-        // If the href starts with #, then attach the current_url to it
601
-        if ($href != '' && substr_compare($href, '#', 0, 1) === 0) {
602
-            $link['href'] = $current_url . $href;
603
-
604
-            return $link;
605
-        }
606
-
607
-        // If it's a full external path, go on...
608
-        if ((strpos($href, 'http://') !== false || strpos($href, 'https://') !== false) &&
609
-            strpos($href, $site_url) === false
610
-        ) {
611
-            $link['target'] = "_blank";
612
-            return $link;
613
-        }
614
-
615
-        // If it's a full local path, get rid of it.
616
-        if (strpos($href, $site_url) !== false) {
617
-            $href = str_replace($site_url, '', $href);
618
-        }
619
-
620
-        // Strip out some unnecessary items, just in case they're there.
621
-        if (substr($href, 0, strlen('docs/')) == 'docs/') {
622
-            $href = substr($href, strlen('docs/'));
623
-        }
624
-
625
-        // This includes 'bonfire/' if it was missed during the conversion.
626
-        if (substr($href, 0, strlen('bonfire/')) == 'bonfire/') {
627
-            $href = substr($href, strlen('bonfire/'));
628
-        }
629
-
630
-        // If another 'group' is not already defined at the head of the link
631
-        // then add the current group to it.
632
-        $group_found = false;
633
-
634
-        foreach ($groups as $group) {
635
-            if (strpos($href, $group) === 0) {
636
-                $group_found = true;
637
-            }
638
-        }
639
-
640
-        if (! $group_found) {
641
-            $href = $this->current_folder . '/' . $href;
642
-        }
643
-
644
-        // Convert to full site_url
645
-        if (strpos($href, 'http') !== 0) {
646
-            $href = $site_url . 'docs/' . ltrim($href, '/ ');
647
-        }
648
-
649
-        // Save the corrected href
650
-        $link['href'] = $href;
651
-
652
-        return $link;
653
-    }
654
-
655
-    //--------------------------------------------------------------------
656
-
657
-    /**
658
-     * Creates a Document Map based on <h2> and <h3> tags.
659
-     * Also adds named anchors into the $content so the map
660
-     * can link to the content properly.
661
-     *
662
-     * @param $content
663
-     * @param $xml
664
-     * @param $map
665
-     * @return array
666
-     */
667
-    protected function extractDocMapAndAddAnchors(&$content, $xml, $map)
668
-    {
669
-        // Holds the current h2 we're processing
670
-        $current_obj = [];
671
-
672
-        $currentChild = 0;
673
-
674
-        foreach ($xml->children() as $childType => $line) {
675
-            $currentChild++;
676
-
677
-            // If it's an h1 - take the first and make it
678
-            // our page title.
679
-            if ($childType == 'h1' && empty($this->page_title))
680
-            {
681
-                $this->page_title = (string)$line;
682
-            }
683
-
684
-            // Make sure that our current object is
685
-            // stored and reset.
686
-            if ($childType == 'h1' || $childType == 'h2') {
687
-                if (count($current_obj)) {
688
-                    $map[] = $current_obj;
689
-                    $current_obj = [];
690
-                }
691
-            }
692
-
693
-            if ($childType == 'h2') {
694
-                $name = (string)$line;
695
-                $link = strtolower(str_replace(' ', '_', (string)$line));
696
-
697
-                $current_obj['name'] = $name;
698
-                $current_obj['link'] = '#' . $link;
699
-                $current_obj['items'] = [];
700
-
701
-                // Insert a named anchor into the $content
702
-                $anchor = '<a name="' . $link . '" id="' . $link . '" ></a>';
703
-
704
-                $search = "<h2>{$name}</h2>";
705
-
706
-                $content = str_replace($search, $anchor . $search, $content);
707
-            } elseif ($childType == 'h3') {
708
-                // Make sure we have some place to store the items.
709
-                if (! isset($current_obj['items'])) {
710
-                    $current_obj['items'] = [];
711
-                }
712
-
713
-                $link = strtolower(str_replace(' ', '_', (string)$line));
714
-                $name = (string)$line;
715
-
716
-                $current_obj['items'][] = [
717
-                    'name' => $name,
718
-                    'link' => '#' . $link
719
-                ];
720
-
721
-                // Insert a named anchor into the $content
722
-                $anchor = '<a name="' . $link . '" id="' . $link . '" ></a>';
723
-
724
-                $search = "<h3>{$name}</h3>";
725
-
726
-                $content = str_replace($search, $anchor . $search, $content);
727
-            }
728
-
729
-            // Is this the last element? Then close out our current object.
730
-            if (count($xml) == $currentChild) {
731
-                if (count($current_obj)) {
732
-                    $map[] = $current_obj;
733
-                }
734
-            }
735
-        }
736
-        return [$map, $content];
737
-    }
738
-    //--------------------------------------------------------------------
739
-
740
-    /**
741
-     * Create a Directory Map
742
-     *
743
-     * Reads the specified directory and builds an array
744
-     * representation of it. Sub-folders contained with the
745
-     * directory will be mapped as well.
746
-     *
747
-     * @param    string $source_dir Path to source
748
-     * @param    int $directory_depth Depth of directories to traverse
749
-     *                        (0 = fully recursive, 1 = current dir, etc)
750
-     * @param    bool $hidden Whether to show hidden files
751
-     * @return    array
752
-     */
753
-    protected function directory_map($source_dir, $directory_depth = 0, $hidden = FALSE)
754
-    {
755
-        if ($fp = @opendir($source_dir)) {
756
-            $filedata = array();
757
-            $new_depth = $directory_depth - 1;
758
-            $source_dir = rtrim($source_dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
759
-
760
-            while (FALSE !== ($file = readdir($fp))) {
761
-                // Remove '.', '..', and hidden files [optional]
762
-                if ($file === '.' OR $file === '..' OR ($hidden === FALSE && $file[0] === '.')) {
763
-                    continue;
764
-                }
765
-
766
-                is_dir($source_dir . $file) && $file .= DIRECTORY_SEPARATOR;
767
-
768
-                if (($directory_depth < 1 OR $new_depth > 0) && is_dir($source_dir . $file)) {
769
-                    $filedata[$file] = directory_map($source_dir . $file, $new_depth, $hidden);
770
-                } else {
771
-                    $filedata[] = $file;
772
-                }
773
-            }
774
-
775
-            closedir($fp);
776
-            return $filedata;
777
-        }
778
-
779
-        return FALSE;
780
-    }
781
-
782
-    //--------------------------------------------------------------------
179
+		foreach ($xml->xpath('//a') as $link) {
180
+			$link = $this->reformatAnchor($link, $groups, $current_url, $site_url);
181
+		}
182
+
183
+		$content = $xml->asXML();
184
+		$content = trim(str_replace('<?xml version="1.0" standalone="yes"?>', '', $content));
185
+
186
+		// Clean up and style the tables
187
+		$content = str_replace('<table>', '<table class="' . $this->table_classes . '">', $content);
188
+
189
+		return $content;
190
+	}
191
+	//--------------------------------------------------------------------
192
+
193
+	/**
194
+	 * Allows users to define the classes that are attached to
195
+	 * generated tables.
196
+	 *
197
+	 * @param null $classes
198
+	 * @return $this
199
+	 */
200
+	public function setTableClasses($classes = null)
201
+	{
202
+		$this->table_classes = $classes;
203
+
204
+		return $this;
205
+	}
206
+
207
+	//--------------------------------------------------------------------
208
+
209
+	/**
210
+	 * Given the contents to render, will build a list of links for the sidebar
211
+	 * out of the headings in the file.
212
+	 *
213
+	 * Note: Will ONLY use h2 and h3 to build the links from.
214
+	 *
215
+	 * Note: The $content passed in WILL be modified by adding named anchors
216
+	 * that match up with the locations.
217
+	 *
218
+	 * @param string $content The HTML to analyse for headings.
219
+	 * @return string
220
+	 */
221
+	public function buildDocumentMap(&$content)
222
+	{
223
+		if (empty($content)) {
224
+			return $content;
225
+		}
226
+
227
+		// If $content already has a wrapping <div> and </div> tags, remove them,
228
+		// since we'll replace them just below.
229
+		if (strpos($content, '<div>') === 0) {
230
+			$content = substr($content, 5);
231
+
232
+			// Trailing div also?
233
+			if (substr($content, -6) == '</div>') {
234
+				$content = substr($content, 0, -6);
235
+			}
236
+		}
237
+
238
+		try {
239
+			$xml = new \SimpleXMLElement('<?xml version="1.0" standalone="yes"?><div>' . $content . '</div>');
240
+		} catch (\Exception $e) {
241
+			// SimpleXML barfed on us, so send back the un-modified content
242
+			return [];
243
+		}
244
+
245
+		$map = [];
246
+		list($map, $content) = $this->extractDocMapAndAddAnchors($content, $xml, $map);
247
+
248
+		return $map;
249
+	}
250
+
251
+	//--------------------------------------------------------------------
252
+
253
+	/**
254
+	 * Stores the name of the callback method to run to convert the source
255
+	 * files to viewable files. By default, this should be used to register
256
+	 * a Mardown Extended formatter with the system, but could be used to
257
+	 * extend the
258
+	 *
259
+	 * @param string $callback
260
+	 * @param bool $cascade // If FALSE the formatting of a component ends here. If TRUE, will be passed to next formatter.
261
+	 * @return $this
262
+	 */
263
+	public function registerFormatter($callback = null, $cascade = false)
264
+	{
265
+		if (empty($callback)) return;
266
+
267
+		$this->formatters[] = [
268
+			'callable' => $callback,
269
+			'cascade'  => (bool)$cascade
270
+		];
271
+
272
+		return $this;
273
+	}
274
+
275
+	//--------------------------------------------------------------------
276
+
277
+	/**
278
+	 * Runs the text through the registered formatters.
279
+	 *
280
+	 * @param $str
281
+	 * @return mixed
282
+	 */
283
+	public function format($str)
284
+	{
285
+		if (! is_array($this->formatters)) return $str;
286
+
287
+		foreach ($this->formatters as $formatter) {
288
+			$method = $formatter['callable'];
289
+			$cascade = $formatter['cascade'];
290
+
291
+			$str = call_user_func($method, $str);
292
+
293
+			if (! $cascade) return $str;
294
+		}
295
+
296
+		return $str;
297
+	}
298
+
299
+	//--------------------------------------------------------------------
300
+
301
+	//--------------------------------------------------------------------
302
+	// Table of Contents methods
303
+	//--------------------------------------------------------------------
304
+
305
+	/**
306
+	 * Retrieves the list of files in a folder and preps the name and filename
307
+	 * so it's ready for creating the HTML.
308
+	 *
309
+	 * @param  String $folder The path to the folder to retrieve.
310
+	 *
311
+	 * @return Array  An associative array @see parse_ini_file for format
312
+	 * details.
313
+	 */
314
+	public function buildTOC($folder)
315
+	{
316
+		// If the toc file exists in the folder, use it to build the links.
317
+		if (is_file("{$folder}/_toc.ini")) {
318
+			$toc = parse_ini_file("{$folder}/_toc.ini", true);
319
+			return $this->columnizeTOC($toc);
320
+		}
321
+
322
+		// If the toc file does not exist, build the links by listing the files
323
+		// in the directory (and any sub-directories)
324
+		$map = $this->directory_map($folder);
325
+
326
+		// If directory_map can not open the directory or find any files inside
327
+		// the directory, return an empty array.
328
+		if (empty($map)) {
329
+			return [];
330
+		}
331
+
332
+		// If these docs are located in the /application/docs or /bonfire/docs
333
+		// directory, just use $this->current_group for the root.
334
+		// Module docs need $this->current_group and $type.
335
+		$tocRoot = $this->current_folder;
336
+		if ($this->current_folder != strtolower($folder)) {
337
+			$tocRoot .= '/' . strtolower($folder);
338
+		}
339
+
340
+		$toc = [];
341
+		foreach ($map as $files) {
342
+			// If $files isn't an array, then make it one so that all situations
343
+			// may be dealt with cleanly.
344
+			if (! is_array($files)) {
345
+				$files = [$files];
346
+			}
347
+
348
+			foreach ($files as $file) {
349
+				if (in_array($file, $this->ignore_files)) {
350
+					continue;
351
+				}
352
+
353
+				// The title for the index is the passed $type. Otherwise,
354
+				// build the title from the file's name.
355
+				if (strpos($file, 'index') === false) {
356
+					$title = str_replace($this->docs_ext, '', $file);
357
+					$title = str_replace('_', ' ', $title);
358
+					$title = ucwords($title);
359
+
360
+					$toc["{$tocRoot}/{$file}"] = $title;
361
+				} else {
362
+					$toc[$tocRoot] = $type;
363
+				}
364
+			}
365
+		}
366
+
367
+		$toc = $this->columnizeTOC($toc);
368
+
369
+		return $toc;
370
+	}
371
+
372
+	//--------------------------------------------------------------------
373
+
374
+	/**
375
+	 * Sorts the passed TOC array into columns of as close to equal length
376
+	 * as we can get it.
377
+	 *
378
+	 * @param $toc
379
+	 * @return array
380
+	 */
381
+	protected function columnizeTOC($toc)
382
+	{
383
+		$section_count = count($toc);
384
+
385
+		// First - determine the size of each 'section'.
386
+		$sizes = [];
387
+
388
+		foreach ($toc as $section => $chapters) {
389
+			$sizes[] = count($chapters);
390
+		}
391
+
392
+		$column_avg = (int)round(array_sum($sizes) / $section_count);
393
+
394
+		// Split things into 4 columns of approximately equal size.
395
+		// If we only have 4 columns (or less), then make sure to
396
+		// deal with that also.
397
+		$columns = [];
398
+
399
+		$current_column = 0;
400
+		$current_column_count = 0;
401
+		$keys = array_keys($toc);
402
+
403
+		for ($i = 0; $i <= $section_count; $i++) {
404
+			if (! isset($keys[$i])) {
405
+				continue;
406
+			}
407
+
408
+			$section = array_shift($toc);
409
+
410
+			// Can we stay in this column?
411
+			if ($current_column_count <= $column_avg && $section_count > 4) {
412
+				// Don't forget to account for the heading also.
413
+				$current_column_count += count($section) + 1;
414
+			} else {
415
+				$current_column_count = 0;
416
+				$current_column++;
417
+			}
418
+
419
+			$columns[$current_column][$keys[$i]] = $section;
420
+		}
421
+
422
+		return $columns;
423
+	}
424
+
425
+	//--------------------------------------------------------------------
426
+
427
+	//--------------------------------------------------------------------
428
+	// Folder Methods
429
+	//--------------------------------------------------------------------
430
+
431
+	/**
432
+	 * Returns the current docFolders array.
433
+	 *
434
+	 * @return array
435
+	 */
436
+	public function docFolders()
437
+	{
438
+		return $this->doc_folders;
439
+	}
440
+
441
+	//--------------------------------------------------------------------
442
+
443
+	/**
444
+	 * Registers a path to be used when searching for documentation files.
445
+	 *
446
+	 * @param $name     A nickname to reference it by later.
447
+	 * @param $path     The server path to the folder.
448
+	 * @return $this
449
+	 */
450
+	public function addDocFolder($name, $path)
451
+	{
452
+		// Standardize the path
453
+		$path = realpath($path) . '/';
454
+
455
+		// realpath will return FALSE if the path doesn't exist
456
+		// or the script doesn't have access to it.
457
+		if (! $path || $path == '/') {
458
+			return $this;
459
+		}
460
+
461
+		$name = strtolower($name);
462
+
463
+		$this->doc_folders[$name] = $path;
464
+
465
+		return $this;
466
+	}
467
+
468
+	//--------------------------------------------------------------------
469
+
470
+	/**
471
+	 * Removes a folder from the folders we scan for documentation files
472
+	 * within.
473
+	 *
474
+	 * @param $name
475
+	 * @return $this
476
+	 */
477
+	public function removeDocFolder($name)
478
+	{
479
+		$name = strtolower($name);
480
+
481
+		if (isset($this->doc_folders[$name])) {
482
+			unset($this->doc_folders[$name]);
483
+		}
484
+
485
+		return $this;
486
+	}
487
+
488
+	//--------------------------------------------------------------------
489
+
490
+	//--------------------------------------------------------------------
491
+	// Private Methods
492
+	//--------------------------------------------------------------------
493
+
494
+	/**
495
+	 * Analyzes the passed in current url string and checks against
496
+	 * a list of groups to determine what the current group is.
497
+	 *
498
+	 * @param $current_url
499
+	 * @param $groups
500
+	 * @return string
501
+	 */
502
+	protected function detectCurrentFolder($current_url, $groups = [])
503
+	{
504
+		if (! is_array($groups)) {
505
+			return null;
506
+		}
507
+
508
+		$segments = explode('/', $current_url);
509
+
510
+		// We start from the back of the array since
511
+		// that's most likely to be close to the end.
512
+		$segments = array_reverse($segments);
513
+
514
+		foreach ($segments as $segment) {
515
+			foreach ($groups as $group) {
516
+				if (strtolower($group) == strtolower($segment)) {
517
+					return $group;
518
+				}
519
+			}
520
+		}
521
+
522
+		// Nothing found?
523
+		return null;
524
+	}
525
+
526
+	//--------------------------------------------------------------------
527
+
528
+	//--------------------------------------------------------------------
529
+	// Private Methods
530
+	//--------------------------------------------------------------------
531
+
532
+	/**
533
+	 * Locates the file on disk and reads the contents into a single string.
534
+	 *
535
+	 * If a folder Nickname (see addDocFolder() ) is passed as the second parameter,
536
+	 * it will limit it's search to that single folder. If nothing is passed, it will
537
+	 * search through all of the folders in the order they were given to the library,
538
+	 * until it finds the first one.
539
+	 *
540
+	 * @param string $path The 'path' of the file (relative to the docs
541
+	 *                                 folder. Usually from the URI)
542
+	 * @param string $restrictToFolder (Optional) The nickname of one of the
543
+	 *                                 folders to restrict the search to.
544
+	 *
545
+	 * @throws RuntimeException
546
+	 * @return null|string
547
+	 */
548
+	private function locateAndReadFile($path, $restrictToFolder = null)
549
+	{
550
+		$folders = $this->doc_folders;
551
+
552
+		if (! is_null($restrictToFolder)) {
553
+			// Make sure the folder exists
554
+			if (! is_null($restrictToFolder) && ! isset($this->doc_folders[$restrictToFolder])) {
555
+				throw new \RuntimeException('You must add the docs folder that you wish to find docs from.');
556
+			}
557
+
558
+			$folders = [$this->doc_folders[$restrictToFolder]];
559
+		}
560
+
561
+		foreach ($folders as $alias => $folder) {
562
+			if (file_exists($folder . $path . $this->docs_ext)) {
563
+				// Store the alias so we know which folder we're in.
564
+				$this->current_folder = $alias;
565
+
566
+				return file_get_contents($folder . $path . $this->docs_ext);
567
+			}
568
+		}
569
+
570
+		return null;
571
+	}
572
+
573
+	//--------------------------------------------------------------------
574
+
575
+	/**
576
+	 * Re-formats the passed in link.
577
+	 *
578
+	 * @param $link
579
+	 * @param $current_url
580
+	 * @param $site_url
581
+	 * @return mixed
582
+	 */
583
+	private function reformatAnchor($link, $groups, $current_url, $site_url)
584
+	{
585
+		// Grab the href value.
586
+		$href = $link->attributes()->href;
587
+
588
+		// If the href is null, it's probably a named anchor with no content.
589
+		if (! $href) {
590
+			// Make sure it has an href, else the XML will not close this
591
+			// tag correctly.
592
+			$link['href'] = ' ';
593
+
594
+			return $link;
595
+		}
596
+
597
+		// Remove any trailing # signs
598
+		$href = rtrim($href, '# ');
599
+
600
+		// If the href starts with #, then attach the current_url to it
601
+		if ($href != '' && substr_compare($href, '#', 0, 1) === 0) {
602
+			$link['href'] = $current_url . $href;
603
+
604
+			return $link;
605
+		}
606
+
607
+		// If it's a full external path, go on...
608
+		if ((strpos($href, 'http://') !== false || strpos($href, 'https://') !== false) &&
609
+			strpos($href, $site_url) === false
610
+		) {
611
+			$link['target'] = "_blank";
612
+			return $link;
613
+		}
614
+
615
+		// If it's a full local path, get rid of it.
616
+		if (strpos($href, $site_url) !== false) {
617
+			$href = str_replace($site_url, '', $href);
618
+		}
619
+
620
+		// Strip out some unnecessary items, just in case they're there.
621
+		if (substr($href, 0, strlen('docs/')) == 'docs/') {
622
+			$href = substr($href, strlen('docs/'));
623
+		}
624
+
625
+		// This includes 'bonfire/' if it was missed during the conversion.
626
+		if (substr($href, 0, strlen('bonfire/')) == 'bonfire/') {
627
+			$href = substr($href, strlen('bonfire/'));
628
+		}
629
+
630
+		// If another 'group' is not already defined at the head of the link
631
+		// then add the current group to it.
632
+		$group_found = false;
633
+
634
+		foreach ($groups as $group) {
635
+			if (strpos($href, $group) === 0) {
636
+				$group_found = true;
637
+			}
638
+		}
639
+
640
+		if (! $group_found) {
641
+			$href = $this->current_folder . '/' . $href;
642
+		}
643
+
644
+		// Convert to full site_url
645
+		if (strpos($href, 'http') !== 0) {
646
+			$href = $site_url . 'docs/' . ltrim($href, '/ ');
647
+		}
648
+
649
+		// Save the corrected href
650
+		$link['href'] = $href;
651
+
652
+		return $link;
653
+	}
654
+
655
+	//--------------------------------------------------------------------
656
+
657
+	/**
658
+	 * Creates a Document Map based on <h2> and <h3> tags.
659
+	 * Also adds named anchors into the $content so the map
660
+	 * can link to the content properly.
661
+	 *
662
+	 * @param $content
663
+	 * @param $xml
664
+	 * @param $map
665
+	 * @return array
666
+	 */
667
+	protected function extractDocMapAndAddAnchors(&$content, $xml, $map)
668
+	{
669
+		// Holds the current h2 we're processing
670
+		$current_obj = [];
671
+
672
+		$currentChild = 0;
673
+
674
+		foreach ($xml->children() as $childType => $line) {
675
+			$currentChild++;
676
+
677
+			// If it's an h1 - take the first and make it
678
+			// our page title.
679
+			if ($childType == 'h1' && empty($this->page_title))
680
+			{
681
+				$this->page_title = (string)$line;
682
+			}
683
+
684
+			// Make sure that our current object is
685
+			// stored and reset.
686
+			if ($childType == 'h1' || $childType == 'h2') {
687
+				if (count($current_obj)) {
688
+					$map[] = $current_obj;
689
+					$current_obj = [];
690
+				}
691
+			}
692
+
693
+			if ($childType == 'h2') {
694
+				$name = (string)$line;
695
+				$link = strtolower(str_replace(' ', '_', (string)$line));
696
+
697
+				$current_obj['name'] = $name;
698
+				$current_obj['link'] = '#' . $link;
699
+				$current_obj['items'] = [];
700
+
701
+				// Insert a named anchor into the $content
702
+				$anchor = '<a name="' . $link . '" id="' . $link . '" ></a>';
703
+
704
+				$search = "<h2>{$name}</h2>";
705
+
706
+				$content = str_replace($search, $anchor . $search, $content);
707
+			} elseif ($childType == 'h3') {
708
+				// Make sure we have some place to store the items.
709
+				if (! isset($current_obj['items'])) {
710
+					$current_obj['items'] = [];
711
+				}
712
+
713
+				$link = strtolower(str_replace(' ', '_', (string)$line));
714
+				$name = (string)$line;
715
+
716
+				$current_obj['items'][] = [
717
+					'name' => $name,
718
+					'link' => '#' . $link
719
+				];
720
+
721
+				// Insert a named anchor into the $content
722
+				$anchor = '<a name="' . $link . '" id="' . $link . '" ></a>';
723
+
724
+				$search = "<h3>{$name}</h3>";
725
+
726
+				$content = str_replace($search, $anchor . $search, $content);
727
+			}
728
+
729
+			// Is this the last element? Then close out our current object.
730
+			if (count($xml) == $currentChild) {
731
+				if (count($current_obj)) {
732
+					$map[] = $current_obj;
733
+				}
734
+			}
735
+		}
736
+		return [$map, $content];
737
+	}
738
+	//--------------------------------------------------------------------
739
+
740
+	/**
741
+	 * Create a Directory Map
742
+	 *
743
+	 * Reads the specified directory and builds an array
744
+	 * representation of it. Sub-folders contained with the
745
+	 * directory will be mapped as well.
746
+	 *
747
+	 * @param    string $source_dir Path to source
748
+	 * @param    int $directory_depth Depth of directories to traverse
749
+	 *                        (0 = fully recursive, 1 = current dir, etc)
750
+	 * @param    bool $hidden Whether to show hidden files
751
+	 * @return    array
752
+	 */
753
+	protected function directory_map($source_dir, $directory_depth = 0, $hidden = FALSE)
754
+	{
755
+		if ($fp = @opendir($source_dir)) {
756
+			$filedata = array();
757
+			$new_depth = $directory_depth - 1;
758
+			$source_dir = rtrim($source_dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
759
+
760
+			while (FALSE !== ($file = readdir($fp))) {
761
+				// Remove '.', '..', and hidden files [optional]
762
+				if ($file === '.' OR $file === '..' OR ($hidden === FALSE && $file[0] === '.')) {
763
+					continue;
764
+				}
765
+
766
+				is_dir($source_dir . $file) && $file .= DIRECTORY_SEPARATOR;
767
+
768
+				if (($directory_depth < 1 OR $new_depth > 0) && is_dir($source_dir . $file)) {
769
+					$filedata[$file] = directory_map($source_dir . $file, $new_depth, $hidden);
770
+				} else {
771
+					$filedata[] = $file;
772
+				}
773
+			}
774
+
775
+			closedir($fp);
776
+			return $filedata;
777
+		}
778
+
779
+		return FALSE;
780
+	}
781
+
782
+	//--------------------------------------------------------------------
783 783
 
784 784
 }
Please login to merge, or discard this patch.
myth/Docs/DocBuilderInterface.php 1 patch
Indentation   +103 added lines, -103 removed lines patch added patch discarded remove patch
@@ -40,117 +40,117 @@
 block discarded – undo
40 40
  */
41 41
 interface DocBuilderInterface
42 42
 {
43
-    /**
44
-     * Does the actual work of reading in and parsing the help file.
45
-     * If a folder Nickname (see addDocFolder() ) is passed as the second parameter,
46
-     * it will limit it's search to that single folder. If nothing is passed, it will
47
-     * search through all of the folders in the order they were given to the library,
48
-     * until it finds the first one.
49
-     *
50
-     * @param string $path The 'path' of the file (relative to the docs
51
-     *                                 folder. Usually from the URI)
52
-     * @param string $restrictToFolder (Optional) The folder nickname
53
-     *
54
-     * @return string
55
-     */
56
-    public function readPage($path, $restrictToFolder = null);
43
+	/**
44
+	 * Does the actual work of reading in and parsing the help file.
45
+	 * If a folder Nickname (see addDocFolder() ) is passed as the second parameter,
46
+	 * it will limit it's search to that single folder. If nothing is passed, it will
47
+	 * search through all of the folders in the order they were given to the library,
48
+	 * until it finds the first one.
49
+	 *
50
+	 * @param string $path The 'path' of the file (relative to the docs
51
+	 *                                 folder. Usually from the URI)
52
+	 * @param string $restrictToFolder (Optional) The folder nickname
53
+	 *
54
+	 * @return string
55
+	 */
56
+	public function readPage($path, $restrictToFolder = null);
57 57
 
58
-    /**
59
-     * Parses the contents. Currently runs through the Markdown Extended
60
-     * parser to convert to HTML.
61
-     *
62
-     * @param $str
63
-     * @return mixed
64
-     */
65
-    public function parse($str);
58
+	/**
59
+	 * Parses the contents. Currently runs through the Markdown Extended
60
+	 * parser to convert to HTML.
61
+	 *
62
+	 * @param $str
63
+	 * @return mixed
64
+	 */
65
+	public function parse($str);
66 66
 
67
-    /**
68
-     * Perform a few housekeeping tasks on a page, like rewriting URLs to full
69
-     * URLs, not relative, ensuring they link correctly, etc.
70
-     *
71
-     * @param      $content
72
-     * @param null $site_url
73
-     * @param null $current_url
74
-     * @return string   The post-processed HTML.
75
-     */
76
-    public function postProcess($content, $site_url = null, $current_url = null);
67
+	/**
68
+	 * Perform a few housekeeping tasks on a page, like rewriting URLs to full
69
+	 * URLs, not relative, ensuring they link correctly, etc.
70
+	 *
71
+	 * @param      $content
72
+	 * @param null $site_url
73
+	 * @param null $current_url
74
+	 * @return string   The post-processed HTML.
75
+	 */
76
+	public function postProcess($content, $site_url = null, $current_url = null);
77 77
 
78
-    /**
79
-     * Allows users to define the classes that are attached to
80
-     * generated tables.
81
-     *
82
-     * @param null $classes
83
-     * @return $this
84
-     */
85
-    public function setTableClasses($classes = null);
78
+	/**
79
+	 * Allows users to define the classes that are attached to
80
+	 * generated tables.
81
+	 *
82
+	 * @param null $classes
83
+	 * @return $this
84
+	 */
85
+	public function setTableClasses($classes = null);
86 86
 
87
-    /**
88
-     * Given the contents to render, will build a list of links for the sidebar
89
-     * out of the headings in the file.
90
-     *
91
-     * Note: Will ONLY use h2 and h3 to build the links from.
92
-     *
93
-     * Note: The $content passed in WILL be modified by adding named anchors
94
-     * that match up with the locations.
95
-     *
96
-     * @param string $content The HTML to analyse for headings.
97
-     * @return string
98
-     */
99
-    public function buildDocumentMap(&$content);
87
+	/**
88
+	 * Given the contents to render, will build a list of links for the sidebar
89
+	 * out of the headings in the file.
90
+	 *
91
+	 * Note: Will ONLY use h2 and h3 to build the links from.
92
+	 *
93
+	 * Note: The $content passed in WILL be modified by adding named anchors
94
+	 * that match up with the locations.
95
+	 *
96
+	 * @param string $content The HTML to analyse for headings.
97
+	 * @return string
98
+	 */
99
+	public function buildDocumentMap(&$content);
100 100
 
101
-    /**
102
-     * Stores the name of the callback method to run to convert the source
103
-     * files to viewable files. By default, this should be used to register
104
-     * a Mardown Extended formatter with the system, but could be used to
105
-     * extend the
106
-     *
107
-     * @param string $callback_name
108
-     * @param bool $cascade // If FALSE the formatting of a component ends here. If TRUE, will be passed to next formatter.
109
-     * @return $this
110
-     */
111
-    public function registerFormatter($callback_name = '', $cascade = false);
101
+	/**
102
+	 * Stores the name of the callback method to run to convert the source
103
+	 * files to viewable files. By default, this should be used to register
104
+	 * a Mardown Extended formatter with the system, but could be used to
105
+	 * extend the
106
+	 *
107
+	 * @param string $callback_name
108
+	 * @param bool $cascade // If FALSE the formatting of a component ends here. If TRUE, will be passed to next formatter.
109
+	 * @return $this
110
+	 */
111
+	public function registerFormatter($callback_name = '', $cascade = false);
112 112
 
113
-    /**
114
-     * Runs the text through the registered formatters.
115
-     *
116
-     * @param $str
117
-     * @return mixed
118
-     */
119
-    public function format($str);
113
+	/**
114
+	 * Runs the text through the registered formatters.
115
+	 *
116
+	 * @param $str
117
+	 * @return mixed
118
+	 */
119
+	public function format($str);
120 120
 
121
-    /**
122
-     * Retrieves the list of files in a folder and preps the name and filename
123
-     * so it's ready for creating the HTML.
124
-     *
125
-     * @param  String $folder The path to the folder to retrieve.
126
-     *
127
-     * @return Array  An associative array @see parse_ini_file for format
128
-     * details.
129
-     */
130
-    public function buildTOC($folder);
121
+	/**
122
+	 * Retrieves the list of files in a folder and preps the name and filename
123
+	 * so it's ready for creating the HTML.
124
+	 *
125
+	 * @param  String $folder The path to the folder to retrieve.
126
+	 *
127
+	 * @return Array  An associative array @see parse_ini_file for format
128
+	 * details.
129
+	 */
130
+	public function buildTOC($folder);
131 131
 
132
-    /**
133
-     * Returns the current docFolders array.
134
-     *
135
-     * @return array
136
-     */
137
-    public function docFolders();
132
+	/**
133
+	 * Returns the current docFolders array.
134
+	 *
135
+	 * @return array
136
+	 */
137
+	public function docFolders();
138 138
 
139
-    /**
140
-     * Registers a path to be used when searching for documentation files.
141
-     *
142
-     * @param $name     A nickname to reference it by later.
143
-     * @param $path     The server path to the folder.
144
-     * @return $this
145
-     */
146
-    public function addDocFolder($name, $path);
139
+	/**
140
+	 * Registers a path to be used when searching for documentation files.
141
+	 *
142
+	 * @param $name     A nickname to reference it by later.
143
+	 * @param $path     The server path to the folder.
144
+	 * @return $this
145
+	 */
146
+	public function addDocFolder($name, $path);
147 147
 
148
-    /**
149
-     * Removes a folder from the folders we scan for documentation files
150
-     * within.
151
-     *
152
-     * @param $name
153
-     * @return $this
154
-     */
155
-    public function removeDocFolder($name);
148
+	/**
149
+	 * Removes a folder from the folders we scan for documentation files
150
+	 * within.
151
+	 *
152
+	 * @param $name
153
+	 * @return $this
154
+	 */
155
+	public function removeDocFolder($name);
156 156
 }
Please login to merge, or discard this patch.
myth/Docs/DocSearchInterface.php 1 patch
Indentation   +59 added lines, -59 removed lines patch added patch discarded remove patch
@@ -1,71 +1,71 @@
 block discarded – undo
1 1
 <?php namespace Myth\Docs;
2 2
 /**
3
- * Sprint
4
- *
5
- * A set of power tools to enhance the CodeIgniter framework and provide consistent workflow.
6
- *
7
- * Permission is hereby granted, free of charge, to any person obtaining a copy
8
- * of this software and associated documentation files (the "Software"), to deal
9
- * in the Software without restriction, including without limitation the rights
10
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- * copies of the Software, and to permit persons to whom the Software is
12
- * furnished to do so, subject to the following conditions:
13
- *
14
- * The above copyright notice and this permission notice shall be included in
15
- * all copies or substantial portions of the Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
- * THE SOFTWARE.
24
- *
25
- * @package     Sprint
26
- * @author      Lonnie Ezell
27
- * @copyright   Copyright 2014-2015, New Myth Media, LLC (http://newmythmedia.com)
28
- * @license     http://opensource.org/licenses/MIT  (MIT)
29
- * @link        http://sprintphp.com
30
- * @since       Version 1.0
31
- */
3
+	 * Sprint
4
+	 *
5
+	 * A set of power tools to enhance the CodeIgniter framework and provide consistent workflow.
6
+	 *
7
+	 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+	 * of this software and associated documentation files (the "Software"), to deal
9
+	 * in the Software without restriction, including without limitation the rights
10
+	 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+	 * copies of the Software, and to permit persons to whom the Software is
12
+	 * furnished to do so, subject to the following conditions:
13
+	 *
14
+	 * The above copyright notice and this permission notice shall be included in
15
+	 * all copies or substantial portions of the Software.
16
+	 *
17
+	 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+	 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+	 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+	 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+	 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+	 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+	 * THE SOFTWARE.
24
+	 *
25
+	 * @package     Sprint
26
+	 * @author      Lonnie Ezell
27
+	 * @copyright   Copyright 2014-2015, New Myth Media, LLC (http://newmythmedia.com)
28
+	 * @license     http://opensource.org/licenses/MIT  (MIT)
29
+	 * @link        http://sprintphp.com
30
+	 * @since       Version 1.0
31
+	 */
32 32
 
33 33
 interface DocSearchInterface {
34 34
 
35
-    /**
36
-     * The entry point for performing a search of the documentation.
37
-     *
38
-     * @param null  $terms
39
-     * @param array $folders
40
-     *
41
-     * @return array|null
42
-     */
43
-    public function search($terms = null, $folders = []);
35
+	/**
36
+	 * The entry point for performing a search of the documentation.
37
+	 *
38
+	 * @param null  $terms
39
+	 * @param array $folders
40
+	 *
41
+	 * @return array|null
42
+	 */
43
+	public function search($terms = null, $folders = []);
44 44
 
45
-    //--------------------------------------------------------------------
45
+	//--------------------------------------------------------------------
46 46
 
47
-    /**
48
-     * Stores the name of the callback method to run to convert the source
49
-     * files to viewable files. By default, this should be used to register
50
-     * a Mardown Extended formatter with the system, but could be used to
51
-     * extend the
52
-     *
53
-     * @param string $callback_name
54
-     * @param bool   $cascade       // If FALSE the formatting of a component ends here. If TRUE, will be passed to next formatter.
55
-     * @return $this
56
-     */
57
-    public function registerFormatter($callback_name='', $cascade=false);
47
+	/**
48
+	 * Stores the name of the callback method to run to convert the source
49
+	 * files to viewable files. By default, this should be used to register
50
+	 * a Mardown Extended formatter with the system, but could be used to
51
+	 * extend the
52
+	 *
53
+	 * @param string $callback_name
54
+	 * @param bool   $cascade       // If FALSE the formatting of a component ends here. If TRUE, will be passed to next formatter.
55
+	 * @return $this
56
+	 */
57
+	public function registerFormatter($callback_name='', $cascade=false);
58 58
 
59
-    //--------------------------------------------------------------------
59
+	//--------------------------------------------------------------------
60 60
 
61
-    /**
62
-     * Runs the text through the registered formatters.
63
-     *
64
-     * @param $str
65
-     * @return mixed
66
-     */
67
-    public function format($str);
61
+	/**
62
+	 * Runs the text through the registered formatters.
63
+	 *
64
+	 * @param $str
65
+	 * @return mixed
66
+	 */
67
+	public function format($str);
68 68
 
69
-    //--------------------------------------------------------------------
69
+	//--------------------------------------------------------------------
70 70
 
71 71
 }
Please login to merge, or discard this patch.
myth/Docs/Search.php 1 patch
Indentation   +415 added lines, -415 removed lines patch added patch discarded remove patch
@@ -41,420 +41,420 @@
 block discarded – undo
41 41
 class Search implements DocSearchInterface
42 42
 {
43 43
 
44
-    /**
45
-     * Minimum characters that can be submitted for a search.
46
-     *
47
-     * @var int
48
-     */
49
-    protected $min_chars = 3;
50
-
51
-    /**
52
-     * Maximum characters that can be submitted for a search.
53
-     *
54
-     * @var int
55
-     */
56
-    protected $max_chars = 30;
57
-
58
-    /**
59
-     * Valid file extensions we can search in.
60
-     *
61
-     * @var string
62
-     */
63
-    protected $allowed_file_types = 'html|htm|php|php4|php5|txt|md';
64
-
65
-    /**
66
-     * Which files should we skip over during our search?
67
-     *
68
-     * @var array
69
-     */
70
-    protected $skip_files = ['.', '..', '_404.md', '_toc.ini'];
71
-
72
-    /**
73
-     * How much of each file should we read.
74
-     * Use lower values for faster searches.
75
-     *
76
-     * @var int
77
-     */
78
-    protected $byte_size = 51200;
79
-
80
-    /**
81
-     * Number of words long (approximately)
82
-     * the result excerpt should be.
83
-     *
84
-     * @var int
85
-     */
86
-    protected $excerpt_length = 60;
87
-
88
-    /**
89
-     * The maximum number of results allowed from a single file.
90
-     *
91
-     * @var int
92
-     */
93
-    protected $max_per_file = 1;
94
-
95
-    protected $doc_folders = array();
96
-
97
-    protected $formatters = array();
98
-
99
-    //--------------------------------------------------------------------
100
-
101
-    /**
102
-     * The entry point for performing a search of the documentation.
103
-     *
104
-     * @param null $terms
105
-     * @param array $folders
106
-     *
107
-     * @return array|null
108
-     */
109
-    public function search($terms = null, $folders = [])
110
-    {
111
-        if (empty($terms) || empty($folders)) {
112
-            return null;
113
-        }
114
-
115
-        $results = [];
116
-        $this->doc_folders = $folders;
117
-
118
-        foreach ($folders as $group => $folder) {
119
-            $results = array_merge($results, $this->searchFolder($terms, $folder, $group));
120
-        }
121
-
122
-        return $results;
123
-    }
124
-
125
-    //--------------------------------------------------------------------
126
-
127
-    //--------------------------------------------------------------------
128
-    // Private Methods
129
-    //--------------------------------------------------------------------
130
-
131
-
132
-    /**
133
-     * Searches a single directory worth of files.
134
-     *
135
-     * @param $term
136
-     * @param $folder
137
-     * @param $group_name
138
-     *
139
-     * @return array The results.
140
-     */
141
-    protected function searchFolder($term, $folder, $group_name)
142
-    {
143
-        $results = [];
144
-
145
-        $map = $this->directory_map($folder, 2);
146
-
147
-        $map = $this->flattenMap($map);
148
-
149
-        // Make sure we have something to work with.
150
-        if (! is_array($map) || (is_array($map) && ! count($map))) {
151
-            return [];
152
-        }
153
-
154
-        // Loop over each file and search the contents for our term.
155
-        foreach ($map as $dir => $file) {
156
-            $file_count = 0;
157
-
158
-            if (in_array($file, $this->skip_files)) {
159
-                continue;
160
-            }
161
-
162
-            // Is it a folder?
163
-            if (is_array($file) && count($file)) {
164
-                $results = array_merge($results, $this->searchFolder($term, $folder . '/' . $dir, $group_name));
165
-                continue;
166
-            }
167
-
168
-            // Make sure it's the right file type...
169
-            if (! preg_match("/({$this->allowed_file_types})/i", $file)) {
170
-                continue;
171
-            }
172
-
173
-            $path = is_string($dir) ? $folder . '/' . $dir . '/' . $file : $folder . '/' . $file;
174
-            $term_html = htmlentities($term);
175
-
176
-            // Read in the file text
177
-            $handle = fopen($path, 'r');
178
-            $text = fread($handle, $this->byte_size);
179
-
180
-            // Do we have a match in here somewhere?
181
-            $found = stristr($text, $term) || stristr($text, $term_html);
182
-
183
-            if (! $found) {
184
-                continue;
185
-            }
186
-
187
-            // Escape our terms to safely use in a preg_match
188
-            $excerpt = strip_tags($text);
189
-            $term = preg_quote($term);
190
-            $term = str_replace("/", "\/", "{$term}");
191
-            $term_html = preg_quote($term_html);
192
-            $term_html = str_replace("/", "\/", "{$term_html}");
193
-
194
-            // Add the item to our results with extracts.
195
-            if (preg_match_all(
196
-                "/((\s\S*){0,3})($term|$term_html)((\s?\S*){0,3})/i",
197
-                $excerpt,
198
-                $matches,
199
-                PREG_OFFSET_CAPTURE | PREG_SET_ORDER
200
-            )) {
201
-                foreach ($matches as $match) {
202
-                    if ($file_count >= $this->max_per_file) {
203
-                        continue;
204
-                    }
205
-                    $result_url = '/docs/' . $group_name . '/' . str_replace('.md', '', $file);
206
-
207
-                    foreach ($this->doc_folders as $alias => $folder) {
208
-                        $result_url = str_replace($folder, $alias, $result_url);
209
-                    }
210
-
211
-                    $results[] = [
212
-                        'title' => $this->extractTitle($excerpt, $file),
213
-                        'file' => $folder . '/' . $file,
214
-                        'url' => $result_url,
215
-                        'extract' => $this->buildExtract($excerpt, $term, $match[0][0])
216
-                    ];
217
-
218
-                    $file_count++;
219
-                }
220
-            }
221
-        }
222
-
223
-        return $results;
224
-    }
225
-
226
-    //--------------------------------------------------------------------
227
-
228
-    /**
229
-     * Stores the name of the callback method to run to convert the source
230
-     * files to viewable files. By default, this should be used to register
231
-     * a Mardown Extended formatter with the system, but could be used to
232
-     * extend the
233
-     *
234
-     * @param string $callback_name
235
-     * @param bool $cascade // If FALSE the formatting of a component ends here. If TRUE, will be passed to next formatter.
236
-     * @return $this
237
-     */
238
-    public function registerFormatter($callback_name = '', $cascade = false)
239
-    {
240
-        if (empty($callback_name)) return;
241
-
242
-        $this->formatters[] = array($callback_name => $cascade);
243
-
244
-        return $this;
245
-    }
246
-
247
-    //--------------------------------------------------------------------
248
-
249
-    /**
250
-     * Runs the text through the registered formatters.
251
-     *
252
-     * @param $str
253
-     * @return mixed
254
-     */
255
-    public function format($str)
256
-    {
257
-        if (! is_array($this->formatters)) return $str;
258
-
259
-        foreach ($this->formatters as $formatter) {
260
-            $method = key($formatter);
261
-            $cascade = $formatter[$method];
262
-
263
-            $str = call_user_func($method, $str);
264
-
265
-            if (! $cascade) return $str;
266
-        }
267
-
268
-        return $str;
269
-    }
270
-
271
-    //--------------------------------------------------------------------
272
-
273
-
274
-    //--------------------------------------------------------------------
275
-    // Protected Methods
276
-    //--------------------------------------------------------------------
277
-
278
-    /**
279
-     * Converts an array generated by directory_map into a flat array of
280
-     * folders, removing any nested folders and adding them to the path.
281
-     *
282
-     * @param $map
283
-     * @param $prefix   Used to recursively add the folder name...
284
-     * @return mixed
285
-     */
286
-    protected function flattenMap($map, $prefix = '')
287
-    {
288
-        if (! is_array($map) || ! count($map)) {
289
-            return $map;
290
-        }
291
-
292
-        $return = [];
293
-
294
-        foreach ($map as $folder => $files) {
295
-
296
-            // If it's a folder name and an array of files
297
-            // then call this method recursively to flatten it out.
298
-            if (is_array($files)) {
299
-                $return = array_merge($return, $this->flattenMap($files, $prefix . $folder));
300
-                continue;
301
-            }
302
-
303
-            // Else, add our prefix (if any) to the filename...
304
-            $return[] = $prefix . $files;
305
-        }
306
-
307
-        return $return;
308
-    }
309
-
310
-    //--------------------------------------------------------------------
311
-
312
-    /**
313
-     * Handles extracting the text surrounding our match and basic match formatting.
314
-     *
315
-     * @param $excerpt
316
-     * @param $term
317
-     * @param $match_string
318
-     *
319
-     * @return string
320
-     */
321
-    protected function buildExtract($excerpt, $term, $match_string)
322
-    {
323
-        // Find the character positions within the string that our match was found at.
324
-        // That way we'll know from what positions before and after this we want to grab it in.
325
-        $start_offset = stripos($excerpt, $match_string);
326
-
327
-        // Modify the start and end positions based on $this->excerpt_length / 2.
328
-        $buffer = floor($this->excerpt_length / 2);
329
-
330
-        // Adjust our start position
331
-        $start_offset = $start_offset - $buffer;
332
-        if ($start_offset < 0) {
333
-            $start_offset = 0;
334
-        }
335
-
336
-        $extract = substr($excerpt, $start_offset);
337
-
338
-        $extract = strip_tags($this->format($extract));
339
-
340
-        $extract = $this->firstXWords($extract, $this->excerpt_length);
341
-
342
-        // Wrap the search term in a span we can style.
343
-        $extract = str_ireplace($term, '<span class="term-hilight">' . $term . '</span>', $extract);
344
-
345
-        return $extract;
346
-    }
347
-
348
-    //--------------------------------------------------------------------
349
-
350
-    /**
351
-     * Extracts the title from a bit of markdown formatted text. If it doesn't
352
-     * have an h1 or h2, then it uses the filename.
353
-     *
354
-     * @param $excerpt
355
-     * @param $file
356
-     * @return string
357
-     */
358
-    protected function extractTitle($excerpt, $file)
359
-    {
360
-        $title = '';
361
-
362
-        // Easiest to work if this is split into lines.
363
-        $lines = explode("\n", $excerpt);
364
-
365
-        if (is_array($lines) && count($lines)) {
366
-            foreach ($lines as $line) {
367
-                if (strpos($line, '# ') === 0 || strpos($line, '## ') === 0) {
368
-                    $title = trim(str_replace('#', '', $line));
369
-                    break;
370
-                }
371
-            }
372
-        }
373
-
374
-        // If it's empty, we'll use the filename.
375
-        if (empty($title)) {
376
-            $title = str_replace('_', ' ', $file);
377
-            $title = str_replace('.md', ' ', $title);
378
-            $title = ucwords($title);
379
-        }
380
-
381
-        return $title;
382
-    }
383
-    //--------------------------------------------------------------------
384
-
385
-    /**
386
-     * Create a Directory Map
387
-     *
388
-     * Reads the specified directory and builds an array
389
-     * representation of it. Sub-folders contained with the
390
-     * directory will be mapped as well.
391
-     *
392
-     * @param    string $source_dir Path to source
393
-     * @param    int $directory_depth Depth of directories to traverse
394
-     *                        (0 = fully recursive, 1 = current dir, etc)
395
-     * @param    bool $hidden Whether to show hidden files
396
-     * @return    array
397
-     */
398
-    protected function directory_map($source_dir, $directory_depth = 0, $hidden = FALSE)
399
-    {
400
-        if ($fp = @opendir($source_dir)) {
401
-            $filedata = array();
402
-            $new_depth = $directory_depth - 1;
403
-            $source_dir = rtrim($source_dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
404
-
405
-            while (FALSE !== ($file = readdir($fp))) {
406
-                // Remove '.', '..', and hidden files [optional]
407
-                if ($file === '.' OR $file === '..' OR ($hidden === FALSE && $file[0] === '.')) {
408
-                    continue;
409
-                }
410
-
411
-                is_dir($source_dir . $file) && $file .= DIRECTORY_SEPARATOR;
412
-
413
-                if (($directory_depth < 1 OR $new_depth > 0) && is_dir($source_dir . $file))
414
-                {
415
-                    $filedata[$file] = $this->directory_map($source_dir . $file, $new_depth, $hidden);
416
-                } else
417
-                {
418
-                    // Replace the directory separator here with a forward slash since
419
-                    // Windows uses backward slashes and not all browsers will auto-replace
420
-                    // those slashes in URLs.
421
-                    $filedata[] = str_replace(DIRECTORY_SEPARATOR, '/', $file);
422
-                }
423
-            }
424
-
425
-            closedir($fp);
426
-            return $filedata;
427
-        }
428
-
429
-        return FALSE;
430
-    }
431
-
432
-    //--------------------------------------------------------------------
433
-
434
-    /**
435
-     * Gets the first 'X' words of a string.
436
-     *
437
-     * @param $str
438
-     * @param int $wordCount
439
-     * @return string
440
-     */
441
-    protected function firstXWords($str, $wordCount = 10)
442
-    {
443
-        return implode(
444
-            '',
445
-            array_slice(
446
-                preg_split(
447
-                    '/([\s,\.;\?\!]+)/',
448
-                    $str,
449
-                    $wordCount * 2 + 1,
450
-                    PREG_SPLIT_DELIM_CAPTURE
451
-                ),
452
-                0,
453
-                $wordCount * 2 - 1
454
-            )
455
-        );
456
-    }
457
-
458
-    //--------------------------------------------------------------------
44
+	/**
45
+	 * Minimum characters that can be submitted for a search.
46
+	 *
47
+	 * @var int
48
+	 */
49
+	protected $min_chars = 3;
50
+
51
+	/**
52
+	 * Maximum characters that can be submitted for a search.
53
+	 *
54
+	 * @var int
55
+	 */
56
+	protected $max_chars = 30;
57
+
58
+	/**
59
+	 * Valid file extensions we can search in.
60
+	 *
61
+	 * @var string
62
+	 */
63
+	protected $allowed_file_types = 'html|htm|php|php4|php5|txt|md';
64
+
65
+	/**
66
+	 * Which files should we skip over during our search?
67
+	 *
68
+	 * @var array
69
+	 */
70
+	protected $skip_files = ['.', '..', '_404.md', '_toc.ini'];
71
+
72
+	/**
73
+	 * How much of each file should we read.
74
+	 * Use lower values for faster searches.
75
+	 *
76
+	 * @var int
77
+	 */
78
+	protected $byte_size = 51200;
79
+
80
+	/**
81
+	 * Number of words long (approximately)
82
+	 * the result excerpt should be.
83
+	 *
84
+	 * @var int
85
+	 */
86
+	protected $excerpt_length = 60;
87
+
88
+	/**
89
+	 * The maximum number of results allowed from a single file.
90
+	 *
91
+	 * @var int
92
+	 */
93
+	protected $max_per_file = 1;
94
+
95
+	protected $doc_folders = array();
96
+
97
+	protected $formatters = array();
98
+
99
+	//--------------------------------------------------------------------
100
+
101
+	/**
102
+	 * The entry point for performing a search of the documentation.
103
+	 *
104
+	 * @param null $terms
105
+	 * @param array $folders
106
+	 *
107
+	 * @return array|null
108
+	 */
109
+	public function search($terms = null, $folders = [])
110
+	{
111
+		if (empty($terms) || empty($folders)) {
112
+			return null;
113
+		}
114
+
115
+		$results = [];
116
+		$this->doc_folders = $folders;
117
+
118
+		foreach ($folders as $group => $folder) {
119
+			$results = array_merge($results, $this->searchFolder($terms, $folder, $group));
120
+		}
121
+
122
+		return $results;
123
+	}
124
+
125
+	//--------------------------------------------------------------------
126
+
127
+	//--------------------------------------------------------------------
128
+	// Private Methods
129
+	//--------------------------------------------------------------------
130
+
131
+
132
+	/**
133
+	 * Searches a single directory worth of files.
134
+	 *
135
+	 * @param $term
136
+	 * @param $folder
137
+	 * @param $group_name
138
+	 *
139
+	 * @return array The results.
140
+	 */
141
+	protected function searchFolder($term, $folder, $group_name)
142
+	{
143
+		$results = [];
144
+
145
+		$map = $this->directory_map($folder, 2);
146
+
147
+		$map = $this->flattenMap($map);
148
+
149
+		// Make sure we have something to work with.
150
+		if (! is_array($map) || (is_array($map) && ! count($map))) {
151
+			return [];
152
+		}
153
+
154
+		// Loop over each file and search the contents for our term.
155
+		foreach ($map as $dir => $file) {
156
+			$file_count = 0;
157
+
158
+			if (in_array($file, $this->skip_files)) {
159
+				continue;
160
+			}
161
+
162
+			// Is it a folder?
163
+			if (is_array($file) && count($file)) {
164
+				$results = array_merge($results, $this->searchFolder($term, $folder . '/' . $dir, $group_name));
165
+				continue;
166
+			}
167
+
168
+			// Make sure it's the right file type...
169
+			if (! preg_match("/({$this->allowed_file_types})/i", $file)) {
170
+				continue;
171
+			}
172
+
173
+			$path = is_string($dir) ? $folder . '/' . $dir . '/' . $file : $folder . '/' . $file;
174
+			$term_html = htmlentities($term);
175
+
176
+			// Read in the file text
177
+			$handle = fopen($path, 'r');
178
+			$text = fread($handle, $this->byte_size);
179
+
180
+			// Do we have a match in here somewhere?
181
+			$found = stristr($text, $term) || stristr($text, $term_html);
182
+
183
+			if (! $found) {
184
+				continue;
185
+			}
186
+
187
+			// Escape our terms to safely use in a preg_match
188
+			$excerpt = strip_tags($text);
189
+			$term = preg_quote($term);
190
+			$term = str_replace("/", "\/", "{$term}");
191
+			$term_html = preg_quote($term_html);
192
+			$term_html = str_replace("/", "\/", "{$term_html}");
193
+
194
+			// Add the item to our results with extracts.
195
+			if (preg_match_all(
196
+				"/((\s\S*){0,3})($term|$term_html)((\s?\S*){0,3})/i",
197
+				$excerpt,
198
+				$matches,
199
+				PREG_OFFSET_CAPTURE | PREG_SET_ORDER
200
+			)) {
201
+				foreach ($matches as $match) {
202
+					if ($file_count >= $this->max_per_file) {
203
+						continue;
204
+					}
205
+					$result_url = '/docs/' . $group_name . '/' . str_replace('.md', '', $file);
206
+
207
+					foreach ($this->doc_folders as $alias => $folder) {
208
+						$result_url = str_replace($folder, $alias, $result_url);
209
+					}
210
+
211
+					$results[] = [
212
+						'title' => $this->extractTitle($excerpt, $file),
213
+						'file' => $folder . '/' . $file,
214
+						'url' => $result_url,
215
+						'extract' => $this->buildExtract($excerpt, $term, $match[0][0])
216
+					];
217
+
218
+					$file_count++;
219
+				}
220
+			}
221
+		}
222
+
223
+		return $results;
224
+	}
225
+
226
+	//--------------------------------------------------------------------
227
+
228
+	/**
229
+	 * Stores the name of the callback method to run to convert the source
230
+	 * files to viewable files. By default, this should be used to register
231
+	 * a Mardown Extended formatter with the system, but could be used to
232
+	 * extend the
233
+	 *
234
+	 * @param string $callback_name
235
+	 * @param bool $cascade // If FALSE the formatting of a component ends here. If TRUE, will be passed to next formatter.
236
+	 * @return $this
237
+	 */
238
+	public function registerFormatter($callback_name = '', $cascade = false)
239
+	{
240
+		if (empty($callback_name)) return;
241
+
242
+		$this->formatters[] = array($callback_name => $cascade);
243
+
244
+		return $this;
245
+	}
246
+
247
+	//--------------------------------------------------------------------
248
+
249
+	/**
250
+	 * Runs the text through the registered formatters.
251
+	 *
252
+	 * @param $str
253
+	 * @return mixed
254
+	 */
255
+	public function format($str)
256
+	{
257
+		if (! is_array($this->formatters)) return $str;
258
+
259
+		foreach ($this->formatters as $formatter) {
260
+			$method = key($formatter);
261
+			$cascade = $formatter[$method];
262
+
263
+			$str = call_user_func($method, $str);
264
+
265
+			if (! $cascade) return $str;
266
+		}
267
+
268
+		return $str;
269
+	}
270
+
271
+	//--------------------------------------------------------------------
272
+
273
+
274
+	//--------------------------------------------------------------------
275
+	// Protected Methods
276
+	//--------------------------------------------------------------------
277
+
278
+	/**
279
+	 * Converts an array generated by directory_map into a flat array of
280
+	 * folders, removing any nested folders and adding them to the path.
281
+	 *
282
+	 * @param $map
283
+	 * @param $prefix   Used to recursively add the folder name...
284
+	 * @return mixed
285
+	 */
286
+	protected function flattenMap($map, $prefix = '')
287
+	{
288
+		if (! is_array($map) || ! count($map)) {
289
+			return $map;
290
+		}
291
+
292
+		$return = [];
293
+
294
+		foreach ($map as $folder => $files) {
295
+
296
+			// If it's a folder name and an array of files
297
+			// then call this method recursively to flatten it out.
298
+			if (is_array($files)) {
299
+				$return = array_merge($return, $this->flattenMap($files, $prefix . $folder));
300
+				continue;
301
+			}
302
+
303
+			// Else, add our prefix (if any) to the filename...
304
+			$return[] = $prefix . $files;
305
+		}
306
+
307
+		return $return;
308
+	}
309
+
310
+	//--------------------------------------------------------------------
311
+
312
+	/**
313
+	 * Handles extracting the text surrounding our match and basic match formatting.
314
+	 *
315
+	 * @param $excerpt
316
+	 * @param $term
317
+	 * @param $match_string
318
+	 *
319
+	 * @return string
320
+	 */
321
+	protected function buildExtract($excerpt, $term, $match_string)
322
+	{
323
+		// Find the character positions within the string that our match was found at.
324
+		// That way we'll know from what positions before and after this we want to grab it in.
325
+		$start_offset = stripos($excerpt, $match_string);
326
+
327
+		// Modify the start and end positions based on $this->excerpt_length / 2.
328
+		$buffer = floor($this->excerpt_length / 2);
329
+
330
+		// Adjust our start position
331
+		$start_offset = $start_offset - $buffer;
332
+		if ($start_offset < 0) {
333
+			$start_offset = 0;
334
+		}
335
+
336
+		$extract = substr($excerpt, $start_offset);
337
+
338
+		$extract = strip_tags($this->format($extract));
339
+
340
+		$extract = $this->firstXWords($extract, $this->excerpt_length);
341
+
342
+		// Wrap the search term in a span we can style.
343
+		$extract = str_ireplace($term, '<span class="term-hilight">' . $term . '</span>', $extract);
344
+
345
+		return $extract;
346
+	}
347
+
348
+	//--------------------------------------------------------------------
349
+
350
+	/**
351
+	 * Extracts the title from a bit of markdown formatted text. If it doesn't
352
+	 * have an h1 or h2, then it uses the filename.
353
+	 *
354
+	 * @param $excerpt
355
+	 * @param $file
356
+	 * @return string
357
+	 */
358
+	protected function extractTitle($excerpt, $file)
359
+	{
360
+		$title = '';
361
+
362
+		// Easiest to work if this is split into lines.
363
+		$lines = explode("\n", $excerpt);
364
+
365
+		if (is_array($lines) && count($lines)) {
366
+			foreach ($lines as $line) {
367
+				if (strpos($line, '# ') === 0 || strpos($line, '## ') === 0) {
368
+					$title = trim(str_replace('#', '', $line));
369
+					break;
370
+				}
371
+			}
372
+		}
373
+
374
+		// If it's empty, we'll use the filename.
375
+		if (empty($title)) {
376
+			$title = str_replace('_', ' ', $file);
377
+			$title = str_replace('.md', ' ', $title);
378
+			$title = ucwords($title);
379
+		}
380
+
381
+		return $title;
382
+	}
383
+	//--------------------------------------------------------------------
384
+
385
+	/**
386
+	 * Create a Directory Map
387
+	 *
388
+	 * Reads the specified directory and builds an array
389
+	 * representation of it. Sub-folders contained with the
390
+	 * directory will be mapped as well.
391
+	 *
392
+	 * @param    string $source_dir Path to source
393
+	 * @param    int $directory_depth Depth of directories to traverse
394
+	 *                        (0 = fully recursive, 1 = current dir, etc)
395
+	 * @param    bool $hidden Whether to show hidden files
396
+	 * @return    array
397
+	 */
398
+	protected function directory_map($source_dir, $directory_depth = 0, $hidden = FALSE)
399
+	{
400
+		if ($fp = @opendir($source_dir)) {
401
+			$filedata = array();
402
+			$new_depth = $directory_depth - 1;
403
+			$source_dir = rtrim($source_dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
404
+
405
+			while (FALSE !== ($file = readdir($fp))) {
406
+				// Remove '.', '..', and hidden files [optional]
407
+				if ($file === '.' OR $file === '..' OR ($hidden === FALSE && $file[0] === '.')) {
408
+					continue;
409
+				}
410
+
411
+				is_dir($source_dir . $file) && $file .= DIRECTORY_SEPARATOR;
412
+
413
+				if (($directory_depth < 1 OR $new_depth > 0) && is_dir($source_dir . $file))
414
+				{
415
+					$filedata[$file] = $this->directory_map($source_dir . $file, $new_depth, $hidden);
416
+				} else
417
+				{
418
+					// Replace the directory separator here with a forward slash since
419
+					// Windows uses backward slashes and not all browsers will auto-replace
420
+					// those slashes in URLs.
421
+					$filedata[] = str_replace(DIRECTORY_SEPARATOR, '/', $file);
422
+				}
423
+			}
424
+
425
+			closedir($fp);
426
+			return $filedata;
427
+		}
428
+
429
+		return FALSE;
430
+	}
431
+
432
+	//--------------------------------------------------------------------
433
+
434
+	/**
435
+	 * Gets the first 'X' words of a string.
436
+	 *
437
+	 * @param $str
438
+	 * @param int $wordCount
439
+	 * @return string
440
+	 */
441
+	protected function firstXWords($str, $wordCount = 10)
442
+	{
443
+		return implode(
444
+			'',
445
+			array_slice(
446
+				preg_split(
447
+					'/([\s,\.;\?\!]+)/',
448
+					$str,
449
+					$wordCount * 2 + 1,
450
+					PREG_SPLIT_DELIM_CAPTURE
451
+				),
452
+				0,
453
+				$wordCount * 2 - 1
454
+			)
455
+		);
456
+	}
457
+
458
+	//--------------------------------------------------------------------
459 459
 
460 460
 }
Please login to merge, or discard this patch.
myth/Events/Events.php 1 patch
Indentation   +169 added lines, -169 removed lines patch added patch discarded remove patch
@@ -36,176 +36,176 @@
 block discarded – undo
36 36
 
37 37
 class Events {
38 38
 
39
-    /**
40
-     * The list of listeners.
41
-     *
42
-     * @var array
43
-     */
44
-    protected static $listeners = [];
45
-
46
-    /**
47
-     * Flag to let us know if we've read from the config file
48
-     * and have all of the defined events.
49
-     *
50
-     * @var bool
51
-     */
52
-    protected static $have_read_from_file = false;
53
-
54
-    //--------------------------------------------------------------------
55
-
56
-    /**
57
-     * Registers an action to happen on an event. The action can be any sort
58
-     * of callable:
59
-     *
60
-     *  Events::on('create', 'myFunction');               // procedural function
61
-     *  Events::on('create', ['myClass', 'myMethod']);    // Class::method
62
-     *  Events::on('create', [$myInstance, 'myMethod']);  // Method on an existing instance
63
-     *  Events::on('create', function() {});              // Closure
64
-     *
65
-     * @param $event_name
66
-     * @param callable $callback
67
-     * @param int $priority
68
-     */
69
-    public static function on($event_name, callable $callback, $priority=EVENTS_PRIORITY_NORMAL)
70
-    {
71
-        if (! isset(self::$listeners[$event_name]))
72
-        {
73
-            self::$listeners[$event_name] = [
74
-                true,   // If there's only 1 item, it's sorted.
75
-                [$priority],
76
-                [$callback]
77
-            ];
78
-        }
79
-        else
80
-        {
81
-            self::$listeners[$event_name][0] = false; // Not sorted
82
-            self::$listeners[$event_name][1][] = $priority;
83
-            self::$listeners[$event_name][2][] = $callback;
84
-        }
85
-    }
39
+	/**
40
+	 * The list of listeners.
41
+	 *
42
+	 * @var array
43
+	 */
44
+	protected static $listeners = [];
45
+
46
+	/**
47
+	 * Flag to let us know if we've read from the config file
48
+	 * and have all of the defined events.
49
+	 *
50
+	 * @var bool
51
+	 */
52
+	protected static $have_read_from_file = false;
53
+
54
+	//--------------------------------------------------------------------
55
+
56
+	/**
57
+	 * Registers an action to happen on an event. The action can be any sort
58
+	 * of callable:
59
+	 *
60
+	 *  Events::on('create', 'myFunction');               // procedural function
61
+	 *  Events::on('create', ['myClass', 'myMethod']);    // Class::method
62
+	 *  Events::on('create', [$myInstance, 'myMethod']);  // Method on an existing instance
63
+	 *  Events::on('create', function() {});              // Closure
64
+	 *
65
+	 * @param $event_name
66
+	 * @param callable $callback
67
+	 * @param int $priority
68
+	 */
69
+	public static function on($event_name, callable $callback, $priority=EVENTS_PRIORITY_NORMAL)
70
+	{
71
+		if (! isset(self::$listeners[$event_name]))
72
+		{
73
+			self::$listeners[$event_name] = [
74
+				true,   // If there's only 1 item, it's sorted.
75
+				[$priority],
76
+				[$callback]
77
+			];
78
+		}
79
+		else
80
+		{
81
+			self::$listeners[$event_name][0] = false; // Not sorted
82
+			self::$listeners[$event_name][1][] = $priority;
83
+			self::$listeners[$event_name][2][] = $callback;
84
+		}
85
+	}
86 86
     
87
-    //--------------------------------------------------------------------
88
-
89
-    /**
90
-     * Runs through all subscribed methods running them one at a time,
91
-     * until either:
92
-     *  a) All subscribers have finished or
93
-     *  b) a method returns false, at which point execution of subscribers stops.
94
-     *
95
-     * @param $event_name
96
-     * @return bool
97
-     */
98
-    public static function trigger($event_name, array $arguments = [])
99
-    {
100
-        // Read in our config/events file so that we have them all!
101
-        if (! self::$have_read_from_file)
102
-        {
103
-            if (is_file(APPPATH .'config/events.php'))
104
-            {
105
-                include APPPATH .'config/events.php';
106
-            }
107
-            self::$have_read_from_file = true;
108
-        }
109
-
110
-        foreach (self::listeners($event_name) as $listener)
111
-        {
112
-            $result = call_user_func_array($listener, $arguments);
113
-
114
-            if ($result === false)
115
-            {
116
-                return false;
117
-            }
118
-        }
119
-
120
-        return true;
121
-    }
87
+	//--------------------------------------------------------------------
88
+
89
+	/**
90
+	 * Runs through all subscribed methods running them one at a time,
91
+	 * until either:
92
+	 *  a) All subscribers have finished or
93
+	 *  b) a method returns false, at which point execution of subscribers stops.
94
+	 *
95
+	 * @param $event_name
96
+	 * @return bool
97
+	 */
98
+	public static function trigger($event_name, array $arguments = [])
99
+	{
100
+		// Read in our config/events file so that we have them all!
101
+		if (! self::$have_read_from_file)
102
+		{
103
+			if (is_file(APPPATH .'config/events.php'))
104
+			{
105
+				include APPPATH .'config/events.php';
106
+			}
107
+			self::$have_read_from_file = true;
108
+		}
109
+
110
+		foreach (self::listeners($event_name) as $listener)
111
+		{
112
+			$result = call_user_func_array($listener, $arguments);
113
+
114
+			if ($result === false)
115
+			{
116
+				return false;
117
+			}
118
+		}
119
+
120
+		return true;
121
+	}
122 122
     
123
-    //--------------------------------------------------------------------
124
-
125
-    /**
126
-     * Returns an array of listeners for a single event. They are
127
-     * sorted by priority.
128
-     *
129
-     * If the listener could not be found, returns FALSE, or TRUE if
130
-     * it was removed.
131
-     *
132
-     * @param $event_name
133
-     * @return array
134
-     */
135
-    public static function listeners($event_name)
136
-    {
137
-        if (! isset(self::$listeners[$event_name]))
138
-        {
139
-            return [];
140
-        }
141
-
142
-        // The list is not sorted
143
-        if (! self::$listeners[$event_name][0])
144
-        {
145
-            // Sort it!
146
-            array_multisort(self::$listeners[$event_name][1], SORT_NUMERIC, self::$listeners[$event_name][2]);
147
-
148
-            // Mark it as sorted already!
149
-            self::$listeners[$event_name][0] = true;
150
-        }
151
-
152
-        return self::$listeners[$event_name][2];
153
-    }
154
-
155
-    //--------------------------------------------------------------------
156
-
157
-    /**
158
-     * Removes a single listener from an event.
159
-     *
160
-     * If the listener couldn't be found, returns FALSE, else TRUE if
161
-     * it was removed.
162
-     *
163
-     * @param $event_name
164
-     * @param callable $listener
165
-     * @return bool
166
-     */
167
-    public static function removeListener($event_name, callable $listener)
168
-    {
169
-        if (! isset(self::$listeners[$event_name]))
170
-        {
171
-            return false;
172
-        }
173
-
174
-        foreach (self::$listeners[$event_name][2] as $index => $check)
175
-        {
176
-            if ($check === $listener)
177
-            {
178
-                unset(self::$listeners[$event_name][1][$index]);
179
-                unset(self::$listeners[$event_name][2][$index]);
180
-
181
-                return true;
182
-            }
183
-        }
184
-
185
-        return false;
186
-    }
187
-
188
-    //--------------------------------------------------------------------
189
-
190
-    /**
191
-     * Removes all listeners.
192
-     *
193
-     * If the event_name is specified, only listeners for that event will be
194
-     * removed, otherwise all listeners for all events are removed.
195
-     *
196
-     * @param null $event_name
197
-     */
198
-    public static function removeAllListeners($event_name=null)
199
-    {
200
-        if (! is_null($event_name))
201
-        {
202
-            unset(self::$listeners[$event_name]);
203
-        }
204
-        else {
205
-            self::$listeners = [];
206
-        }
207
-    }
208
-
209
-    //--------------------------------------------------------------------
123
+	//--------------------------------------------------------------------
124
+
125
+	/**
126
+	 * Returns an array of listeners for a single event. They are
127
+	 * sorted by priority.
128
+	 *
129
+	 * If the listener could not be found, returns FALSE, or TRUE if
130
+	 * it was removed.
131
+	 *
132
+	 * @param $event_name
133
+	 * @return array
134
+	 */
135
+	public static function listeners($event_name)
136
+	{
137
+		if (! isset(self::$listeners[$event_name]))
138
+		{
139
+			return [];
140
+		}
141
+
142
+		// The list is not sorted
143
+		if (! self::$listeners[$event_name][0])
144
+		{
145
+			// Sort it!
146
+			array_multisort(self::$listeners[$event_name][1], SORT_NUMERIC, self::$listeners[$event_name][2]);
147
+
148
+			// Mark it as sorted already!
149
+			self::$listeners[$event_name][0] = true;
150
+		}
151
+
152
+		return self::$listeners[$event_name][2];
153
+	}
154
+
155
+	//--------------------------------------------------------------------
156
+
157
+	/**
158
+	 * Removes a single listener from an event.
159
+	 *
160
+	 * If the listener couldn't be found, returns FALSE, else TRUE if
161
+	 * it was removed.
162
+	 *
163
+	 * @param $event_name
164
+	 * @param callable $listener
165
+	 * @return bool
166
+	 */
167
+	public static function removeListener($event_name, callable $listener)
168
+	{
169
+		if (! isset(self::$listeners[$event_name]))
170
+		{
171
+			return false;
172
+		}
173
+
174
+		foreach (self::$listeners[$event_name][2] as $index => $check)
175
+		{
176
+			if ($check === $listener)
177
+			{
178
+				unset(self::$listeners[$event_name][1][$index]);
179
+				unset(self::$listeners[$event_name][2][$index]);
180
+
181
+				return true;
182
+			}
183
+		}
184
+
185
+		return false;
186
+	}
187
+
188
+	//--------------------------------------------------------------------
189
+
190
+	/**
191
+	 * Removes all listeners.
192
+	 *
193
+	 * If the event_name is specified, only listeners for that event will be
194
+	 * removed, otherwise all listeners for all events are removed.
195
+	 *
196
+	 * @param null $event_name
197
+	 */
198
+	public static function removeAllListeners($event_name=null)
199
+	{
200
+		if (! is_null($event_name))
201
+		{
202
+			unset(self::$listeners[$event_name]);
203
+		}
204
+		else {
205
+			self::$listeners = [];
206
+		}
207
+	}
208
+
209
+	//--------------------------------------------------------------------
210 210
 
211 211
 }
Please login to merge, or discard this patch.
myth/Forensics/Console.php 1 patch
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -167,11 +167,11 @@
 block discarded – undo
167 167
 
168 168
 	public function reset()
169 169
 	{
170
-	    self::$logs = array(
171
-		    'console'		=> array(),
172
-		    'log_count'		=> 0,
173
-		    'memory_count'	=> 0,
174
-	    );
170
+		self::$logs = array(
171
+			'console'		=> array(),
172
+			'log_count'		=> 0,
173
+			'memory_count'	=> 0,
174
+		);
175 175
 	}
176 176
 
177 177
 	//--------------------------------------------------------------------
Please login to merge, or discard this patch.
myth/Forensics/Profiler.php 1 patch
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -531,16 +531,16 @@
 block discarded – undo
531 531
 
532 532
 
533 533
 	public static function get_file_size($size, $retstring = null) {
534
-        // adapted from code at http://aidanlister.com/repos/v/function.size_readable.php
535
-	    $sizes = array('bytes', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
534
+		// adapted from code at http://aidanlister.com/repos/v/function.size_readable.php
535
+		$sizes = array('bytes', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
536 536
 
537
-	    if ($retstring === null) { $retstring = '%01.2f %s'; }
537
+		if ($retstring === null) { $retstring = '%01.2f %s'; }
538 538
 
539 539
 		$lastsizestring = end($sizes);
540 540
 
541 541
 		foreach ($sizes as $sizestring) {
542
-	       	if ($size < 1024) { break; }
543
-	           if ($sizestring != $lastsizestring) { $size /= 1024; }
542
+		   	if ($size < 1024) { break; }
543
+			   if ($sizestring != $lastsizestring) { $size /= 1024; }
544 544
 		}
545 545
 
546 546
 		if ($sizestring == $sizes[0]) { $retstring = '%01d %s'; } // Bytes aren't normally fractional
Please login to merge, or discard this patch.
myth/Forge/BaseGenerator.php 1 patch
Indentation   +441 added lines, -441 removed lines patch added patch discarded remove patch
@@ -1,34 +1,34 @@  discard block
 block discarded – undo
1 1
 <?php namespace Myth\Forge;
2 2
 /**
3
- * Sprint
4
- *
5
- * A set of power tools to enhance the CodeIgniter framework and provide consistent workflow.
6
- *
7
- * Permission is hereby granted, free of charge, to any person obtaining a copy
8
- * of this software and associated documentation files (the "Software"), to deal
9
- * in the Software without restriction, including without limitation the rights
10
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- * copies of the Software, and to permit persons to whom the Software is
12
- * furnished to do so, subject to the following conditions:
13
- *
14
- * The above copyright notice and this permission notice shall be included in
15
- * all copies or substantial portions of the Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
- * THE SOFTWARE.
24
- *
25
- * @package     Sprint
26
- * @author      Lonnie Ezell
27
- * @copyright   Copyright 2014-2015, New Myth Media, LLC (http://newmythmedia.com)
28
- * @license     http://opensource.org/licenses/MIT  (MIT)
29
- * @link        http://sprintphp.com
30
- * @since       Version 1.0
31
- */
3
+	 * Sprint
4
+	 *
5
+	 * A set of power tools to enhance the CodeIgniter framework and provide consistent workflow.
6
+	 *
7
+	 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+	 * of this software and associated documentation files (the "Software"), to deal
9
+	 * in the Software without restriction, including without limitation the rights
10
+	 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+	 * copies of the Software, and to permit persons to whom the Software is
12
+	 * furnished to do so, subject to the following conditions:
13
+	 *
14
+	 * The above copyright notice and this permission notice shall be included in
15
+	 * all copies or substantial portions of the Software.
16
+	 *
17
+	 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+	 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+	 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+	 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+	 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+	 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+	 * THE SOFTWARE.
24
+	 *
25
+	 * @package     Sprint
26
+	 * @author      Lonnie Ezell
27
+	 * @copyright   Copyright 2014-2015, New Myth Media, LLC (http://newmythmedia.com)
28
+	 * @license     http://opensource.org/licenses/MIT  (MIT)
29
+	 * @link        http://sprintphp.com
30
+	 * @since       Version 1.0
31
+	 */
32 32
 
33 33
 use Myth\Controllers\CLIController;
34 34
 use Myth\CLI;
@@ -43,13 +43,13 @@  discard block
 block discarded – undo
43 43
  */
44 44
 abstract class BaseGenerator extends CLIController {
45 45
 
46
-    /**
47
-     * Instance of the active themer.
48
-     * @var null
49
-     */
50
-    protected $themer = null;
46
+	/**
47
+	 * Instance of the active themer.
48
+	 * @var null
49
+	 */
50
+	protected $themer = null;
51 51
 
52
-    protected $gen_path = null;
52
+	protected $gen_path = null;
53 53
 
54 54
 	/**
55 55
 	 * The name of the module being used, if any.
@@ -62,254 +62,254 @@  discard block
 block discarded – undo
62 62
 
63 63
 	protected $overwrite = false;
64 64
 
65
-    //--------------------------------------------------------------------
65
+	//--------------------------------------------------------------------
66 66
 
67
-    public function __construct()
68
-    {
69
-        parent::__construct();
67
+	public function __construct()
68
+	{
69
+		parent::__construct();
70 70
 
71
-        $this->load->config('forge');
71
+		$this->load->config('forge');
72 72
 
73
-	    // Detect if we're genning in a module
74
-	    if ($module = CLI::option('module'))
75
-	    {
76
-		    $this->module = $module;
73
+		// Detect if we're genning in a module
74
+		if ($module = CLI::option('module'))
75
+		{
76
+			$this->module = $module;
77 77
 
78
-		    $folders = config_item('modules_locations');
78
+			$folders = config_item('modules_locations');
79 79
 
80
-		    if (is_array($folders))
81
-		    {
82
-			    $this->module_path = $folders[0] . strtolower($module) .'/';
83
-		    }
80
+			if (is_array($folders))
81
+			{
82
+				$this->module_path = $folders[0] . strtolower($module) .'/';
83
+			}
84 84
 		}
85 85
 
86
-	    // Should we overwrite files?
87
-	    if (CLI::option('overwrite'))
88
-	    {
89
-		    $this->overwrite = true;
90
-	    }
91
-    }
86
+		// Should we overwrite files?
87
+		if (CLI::option('overwrite'))
88
+		{
89
+			$this->overwrite = true;
90
+		}
91
+	}
92 92
 
93
-    //--------------------------------------------------------------------
93
+	//--------------------------------------------------------------------
94 94
 
95 95
 
96
-    /**
97
-     * The method called by the main generator script. This must be
98
-     * overridden by child classes to implement the actual logic used.
99
-     *
100
-     * @param array $segments
101
-     * @param bool  $quiet      If true, models should accept default values.
102
-     * @return mixed
103
-     */
104
-    abstract function run($segments=[], $quiet=false);
96
+	/**
97
+	 * The method called by the main generator script. This must be
98
+	 * overridden by child classes to implement the actual logic used.
99
+	 *
100
+	 * @param array $segments
101
+	 * @param bool  $quiet      If true, models should accept default values.
102
+	 * @return mixed
103
+	 */
104
+	abstract function run($segments=[], $quiet=false);
105 105
 
106
-    //--------------------------------------------------------------------
106
+	//--------------------------------------------------------------------
107 107
 
108 108
 
109
-    /**
110
-     * Creates a file at the specified path with the given contents.
111
-     *
112
-     * @param $path
113
-     * @param null $contents
114
-     *
115
-     * @return bool
116
-     */
117
-    public function createFile($path, $contents=null, $overwrite=false, $perms=0644)
118
-    {
119
-	    $path = $this->sandbox($path);
109
+	/**
110
+	 * Creates a file at the specified path with the given contents.
111
+	 *
112
+	 * @param $path
113
+	 * @param null $contents
114
+	 *
115
+	 * @return bool
116
+	 */
117
+	public function createFile($path, $contents=null, $overwrite=false, $perms=0644)
118
+	{
119
+		$path = $this->sandbox($path);
120 120
 
121
-	    $file_exists = is_file($path);
121
+		$file_exists = is_file($path);
122 122
 
123
-        // Does file already exist?
124
-        if ($file_exists)
125
-        {
126
-	        if (! $overwrite) {
127
-		        CLI::write( CLI::color("\t". strtolower(lang('exists')) .": ", 'blue') . str_replace(APPPATH, '', $path ) );
128
-		        return true;
129
-	        }
123
+		// Does file already exist?
124
+		if ($file_exists)
125
+		{
126
+			if (! $overwrite) {
127
+				CLI::write( CLI::color("\t". strtolower(lang('exists')) .": ", 'blue') . str_replace(APPPATH, '', $path ) );
128
+				return true;
129
+			}
130 130
 
131
-	        unlink($path);
132
-        }
131
+			unlink($path);
132
+		}
133 133
 
134
-	    // Do we need to create the directory?
135
-	    $segments = explode('/', $path);
134
+		// Do we need to create the directory?
135
+		$segments = explode('/', $path);
136 136
 		array_pop($segments);
137 137
 		$folder = implode('/', $segments);
138 138
 
139
-	    if (! is_dir($folder))
140
-	    {
141
-		    $this->createDirectory($folder);
142
-	    }
139
+		if (! is_dir($folder))
140
+		{
141
+			$this->createDirectory($folder);
142
+		}
143 143
 
144
-        get_instance()->load->helper('file');
144
+		get_instance()->load->helper('file');
145 145
 
146
-        if (! write_file($path, $contents))
147
-        {
148
-            throw new \RuntimeException( sprintf( lang('errors.writing_file'),  $path) );
149
-        }
146
+		if (! write_file($path, $contents))
147
+		{
148
+			throw new \RuntimeException( sprintf( lang('errors.writing_file'),  $path) );
149
+		}
150 150
 
151
-        chmod($path, $perms);
151
+		chmod($path, $perms);
152 152
 
153
-	    if ($overwrite && $file_exists)
154
-	    {
155
-		    CLI::write( CLI::color("\t". strtolower( lang('overwrote') ) ." ", 'light_red') . str_replace(APPPATH, '', $path ) );
156
-	    }
157
-	    else
158
-	    {
159
-		    CLI::write( CLI::color("\t". strtolower( lang('created') ) ." ", 'yellow') . str_replace(APPPATH, '', $path ) );
160
-	    }
153
+		if ($overwrite && $file_exists)
154
+		{
155
+			CLI::write( CLI::color("\t". strtolower( lang('overwrote') ) ." ", 'light_red') . str_replace(APPPATH, '', $path ) );
156
+		}
157
+		else
158
+		{
159
+			CLI::write( CLI::color("\t". strtolower( lang('created') ) ." ", 'yellow') . str_replace(APPPATH, '', $path ) );
160
+		}
161 161
 
162
-        return $this;
163
-    }
162
+		return $this;
163
+	}
164 164
     
165
-    //--------------------------------------------------------------------
166
-
167
-    /**
168
-     * Creates a new directory at the specified path.
169
-     *
170
-     * @param $path
171
-     * @param int|string $perms
172
-     *
173
-     * @return bool
174
-     */
175
-    public function createDirectory($path, $perms=0755)
176
-    {
177
-	    $path = $this->sandbox($path);
178
-
179
-        if (is_dir($path))
180
-        {
181
-            return $this;
182
-        }
183
-
184
-        if (! mkdir($path, $perms, true) )
185
-        {
186
-            throw new \RuntimeException( sprintf( lang('errors.creating_dir'), $path) );
187
-        }
188
-
189
-        return $this;
190
-    }
191
-
192
-    //--------------------------------------------------------------------
193
-
194
-    /**
195
-     * Copies a file from the current template group to the destination.
196
-     *
197
-     * @param $source
198
-     * @param $destination
199
-     * @param bool $overwrite
200
-     *
201
-     * @return bool
202
-     */
203
-    public function copyFile($source, $destination, $overwrite=false)
204
-    {
205
-	    $source = $this->sandbox($source);
206
-
207
-	    if (! file_exists($source))
208
-	    {
209
-		    return null;
210
-	    }
211
-
212
-	    $content = file_get_contents($source);
213
-
214
-	    return $this->createFile($destination, $content, $overwrite);
215
-    }
216
-
217
-    //--------------------------------------------------------------------
218
-
219
-    /**
220
-     * Attempts to locate a template within the current template group,
221
-     * parses it with the passed in data, and writes to the new location.
222
-     *
223
-     * @param $template
224
-     * @param $destination
225
-     * @param array $data
226
-     * @param bool $overwrite
227
-     *
228
-     * @return $this
229
-     */
230
-    public function copyTemplate($template, $destination, $data=[], $overwrite=false)
231
-    {
232
-	    if (! is_array($data))
233
-	    {
234
-		    $data = array($data);
235
-	    }
236
-
237
-        $content = $this->render($template, $data);
238
-
239
-        return $this->createFile($destination, $content, $overwrite);
240
-    }
241
-
242
-    //--------------------------------------------------------------------
243
-
244
-
245
-    /**
246
-     * Injects a block of code into an existing file. Using options
247
-     * you can specify where the code should be inserted. Available options
248
-     * are:
249
-     *      prepend         - Place at beginning of file
250
-     *      append          - Place at end of file
251
-     *      before  => ''   - Insert just prior to this line of text (don't forget the line ending "\n")
252
-     *      after   => ''   - Insert just after this line of text (don't forget the line ending "\n")
253
-     *      replace => ''   - a simple string to be replaced. All locations will be replaced.
254
-     *      regex   => ''   - a pregex pattern to use to replace all locations.
255
-     *
256
-     * @param $path
257
-     * @param $content
258
-     * @param array $options
259
-     *
260
-     * @return $this
261
-     */
262
-    public function injectIntoFile($path, $content, $options='append')
263
-    {
264
-        $kit = new FileKit();
265
-
266
-        if (is_string($options))
267
-        {
268
-            $action = $options;
269
-        }
270
-        else if (is_array($options) && count($options))
271
-        {
272
-            $keys = array_keys($options);
273
-            $action = array_shift( $keys );
274
-            $param = $options[$action];
275
-        }
276
-
277
-        switch ( strtolower($action) )
278
-        {
279
-            case 'prepend':
280
-                $success = $kit->prepend($path, $content);
281
-                break;
282
-            case 'before':
283
-                $success = $kit->before($path, $param, $content);
284
-                break;
285
-            case 'after':
286
-                $success = $kit->after($path, $param, $content);
287
-                break;
288
-            case 'replace':
289
-                $success = $kit->replaceIn($path, $param, $content);
290
-                break;
291
-            case 'regex':
292
-                $success = $kit->replaceWithRegex($path, $param, $content);
293
-                break;
294
-            case 'append':
295
-            default:
296
-                $success = $kit->append($path, $content);
297
-                break;
298
-        }
299
-
300
-        if ($success)
301
-        {
302
-            CLI::write( CLI::color("\t". strtolower( lang('modified') ) ." ", 'cyan') . str_replace(APPPATH, '', $path ) );
303
-        }
304
-        else
305
-        {
306
-            CLI::write( CLI::color("\t". strtolower( lang('error') ) ." ", 'light_red') . str_replace(APPPATH, '', $path ) );
307
-        }
308
-
309
-        return $this;
310
-    }
165
+	//--------------------------------------------------------------------
166
+
167
+	/**
168
+	 * Creates a new directory at the specified path.
169
+	 *
170
+	 * @param $path
171
+	 * @param int|string $perms
172
+	 *
173
+	 * @return bool
174
+	 */
175
+	public function createDirectory($path, $perms=0755)
176
+	{
177
+		$path = $this->sandbox($path);
178
+
179
+		if (is_dir($path))
180
+		{
181
+			return $this;
182
+		}
183
+
184
+		if (! mkdir($path, $perms, true) )
185
+		{
186
+			throw new \RuntimeException( sprintf( lang('errors.creating_dir'), $path) );
187
+		}
188
+
189
+		return $this;
190
+	}
191
+
192
+	//--------------------------------------------------------------------
193
+
194
+	/**
195
+	 * Copies a file from the current template group to the destination.
196
+	 *
197
+	 * @param $source
198
+	 * @param $destination
199
+	 * @param bool $overwrite
200
+	 *
201
+	 * @return bool
202
+	 */
203
+	public function copyFile($source, $destination, $overwrite=false)
204
+	{
205
+		$source = $this->sandbox($source);
206
+
207
+		if (! file_exists($source))
208
+		{
209
+			return null;
210
+		}
211
+
212
+		$content = file_get_contents($source);
213
+
214
+		return $this->createFile($destination, $content, $overwrite);
215
+	}
216
+
217
+	//--------------------------------------------------------------------
218
+
219
+	/**
220
+	 * Attempts to locate a template within the current template group,
221
+	 * parses it with the passed in data, and writes to the new location.
222
+	 *
223
+	 * @param $template
224
+	 * @param $destination
225
+	 * @param array $data
226
+	 * @param bool $overwrite
227
+	 *
228
+	 * @return $this
229
+	 */
230
+	public function copyTemplate($template, $destination, $data=[], $overwrite=false)
231
+	{
232
+		if (! is_array($data))
233
+		{
234
+			$data = array($data);
235
+		}
236
+
237
+		$content = $this->render($template, $data);
238
+
239
+		return $this->createFile($destination, $content, $overwrite);
240
+	}
241
+
242
+	//--------------------------------------------------------------------
243
+
244
+
245
+	/**
246
+	 * Injects a block of code into an existing file. Using options
247
+	 * you can specify where the code should be inserted. Available options
248
+	 * are:
249
+	 *      prepend         - Place at beginning of file
250
+	 *      append          - Place at end of file
251
+	 *      before  => ''   - Insert just prior to this line of text (don't forget the line ending "\n")
252
+	 *      after   => ''   - Insert just after this line of text (don't forget the line ending "\n")
253
+	 *      replace => ''   - a simple string to be replaced. All locations will be replaced.
254
+	 *      regex   => ''   - a pregex pattern to use to replace all locations.
255
+	 *
256
+	 * @param $path
257
+	 * @param $content
258
+	 * @param array $options
259
+	 *
260
+	 * @return $this
261
+	 */
262
+	public function injectIntoFile($path, $content, $options='append')
263
+	{
264
+		$kit = new FileKit();
265
+
266
+		if (is_string($options))
267
+		{
268
+			$action = $options;
269
+		}
270
+		else if (is_array($options) && count($options))
271
+		{
272
+			$keys = array_keys($options);
273
+			$action = array_shift( $keys );
274
+			$param = $options[$action];
275
+		}
276
+
277
+		switch ( strtolower($action) )
278
+		{
279
+			case 'prepend':
280
+				$success = $kit->prepend($path, $content);
281
+				break;
282
+			case 'before':
283
+				$success = $kit->before($path, $param, $content);
284
+				break;
285
+			case 'after':
286
+				$success = $kit->after($path, $param, $content);
287
+				break;
288
+			case 'replace':
289
+				$success = $kit->replaceIn($path, $param, $content);
290
+				break;
291
+			case 'regex':
292
+				$success = $kit->replaceWithRegex($path, $param, $content);
293
+				break;
294
+			case 'append':
295
+			default:
296
+				$success = $kit->append($path, $content);
297
+				break;
298
+		}
299
+
300
+		if ($success)
301
+		{
302
+			CLI::write( CLI::color("\t". strtolower( lang('modified') ) ." ", 'cyan') . str_replace(APPPATH, '', $path ) );
303
+		}
304
+		else
305
+		{
306
+			CLI::write( CLI::color("\t". strtolower( lang('error') ) ." ", 'light_red') . str_replace(APPPATH, '', $path ) );
307
+		}
308
+
309
+		return $this;
310
+	}
311 311
     
312
-    //--------------------------------------------------------------------
312
+	//--------------------------------------------------------------------
313 313
 
314 314
 	/**
315 315
 	 * Runs another generator. The first parameter is the name of the
@@ -320,130 +320,130 @@  discard block
 block discarded – undo
320 320
 	 * @param $command
321 321
 	 * @param null $options
322 322
 	 */
323
-    public function generate($command, $options = '', $quiet=false)
324
-    {
323
+	public function generate($command, $options = '', $quiet=false)
324
+	{
325 325
 		$orig_options = CLI::optionString();
326
-	    $options = $orig_options .' '. $options;
327
-
328
-	    if ($quiet === true)
329
-	    {
330
-		    $options .= ' -quiet';
331
-	    }
332
-
333
-	    if ($this->overwrite === true)
334
-	    {
335
-		    $options .= ' -overwrite';
336
-	    }
337
-
338
-	    passthru( "php sprint forge {$command} {$options}" );
339
-    }
340
-
341
-    //--------------------------------------------------------------------
342
-
343
-    /**
344
-     * Adds a new route to the application's route file.
345
-     *
346
-     * @param $left
347
-     * @param $right
348
-     *
349
-     * @return \Myth\Forge\BaseGenerator
350
-     */
351
-    public function route($left, $right, $options=[], $method='any')
352
-    {
353
-        $option_str = '[';
354
-
355
-        foreach ($options as $key => $value)
356
-        {
357
-            $option_str .= "";
358
-        }
359
-
360
-        $option_str .= ']';
361
-
362
-        $content = "\$routes->{$method}('{$left}', '{$right}', {$option_str});\n";
363
-
364
-        return $this->injectIntoFile(APPPATH .'config/routes.php', $content, ['after' => "// Auto-generated routes go here\n"]);
365
-    }
326
+		$options = $orig_options .' '. $options;
327
+
328
+		if ($quiet === true)
329
+		{
330
+			$options .= ' -quiet';
331
+		}
332
+
333
+		if ($this->overwrite === true)
334
+		{
335
+			$options .= ' -overwrite';
336
+		}
337
+
338
+		passthru( "php sprint forge {$command} {$options}" );
339
+	}
340
+
341
+	//--------------------------------------------------------------------
342
+
343
+	/**
344
+	 * Adds a new route to the application's route file.
345
+	 *
346
+	 * @param $left
347
+	 * @param $right
348
+	 *
349
+	 * @return \Myth\Forge\BaseGenerator
350
+	 */
351
+	public function route($left, $right, $options=[], $method='any')
352
+	{
353
+		$option_str = '[';
354
+
355
+		foreach ($options as $key => $value)
356
+		{
357
+			$option_str .= "";
358
+		}
359
+
360
+		$option_str .= ']';
361
+
362
+		$content = "\$routes->{$method}('{$left}', '{$right}', {$option_str});\n";
363
+
364
+		return $this->injectIntoFile(APPPATH .'config/routes.php', $content, ['after' => "// Auto-generated routes go here\n"]);
365
+	}
366 366
     
367
-    //--------------------------------------------------------------------
367
+	//--------------------------------------------------------------------
368 368
 
369
-    /**
370
-     * Outputs the contents of the file in the template's source path.
371
-     */
372
-    public function readme($file='readme.txt')
373
-    {
374
-	    $name = str_replace('Generator', '', get_class($this));
369
+	/**
370
+	 * Outputs the contents of the file in the template's source path.
371
+	 */
372
+	public function readme($file='readme.txt')
373
+	{
374
+		$name = str_replace('Generator', '', get_class($this));
375 375
 
376
-	    $path = $this->locateGenerator($name);
376
+		$path = $this->locateGenerator($name);
377 377
 
378
-        if (! file_exists($path . $file))
379
-        {
380
-            CLI::error(sprintf( lang('forge.cant_find_readme'), $file) );
381
-        }
378
+		if (! file_exists($path . $file))
379
+		{
380
+			CLI::error(sprintf( lang('forge.cant_find_readme'), $file) );
381
+		}
382 382
 
383
-	    $contents = file_get_contents($path . $file);
383
+		$contents = file_get_contents($path . $file);
384 384
 
385
-        CLI::new_line(2);
386
-        CLI::write( CLI::wrap($contents), 'green' );
387
-        CLI::new_line();
388
-    }
385
+		CLI::new_line(2);
386
+		CLI::write( CLI::wrap($contents), 'green' );
387
+		CLI::new_line();
388
+	}
389 389
 
390
-    //--------------------------------------------------------------------
390
+	//--------------------------------------------------------------------
391 391
 
392
-    /**
393
-     * Renders a single generator template. The file must be in a folder
394
-     * under the template group named the same as $this->generator_name.
395
-     * The file must have a '.tpl.php' file extension.
396
-     *
397
-     * @param $template_name
398
-     * @param array $data
399
-     *
400
-     * @return string The rendered template
401
-     */
402
-    public function render($template_name, $data=[], $folder=null)
403
-    {
404
-        if (empty($this->themer))
405
-        {
406
-            $this->setupThemer();
407
-        }
392
+	/**
393
+	 * Renders a single generator template. The file must be in a folder
394
+	 * under the template group named the same as $this->generator_name.
395
+	 * The file must have a '.tpl.php' file extension.
396
+	 *
397
+	 * @param $template_name
398
+	 * @param array $data
399
+	 *
400
+	 * @return string The rendered template
401
+	 */
402
+	public function render($template_name, $data=[], $folder=null)
403
+	{
404
+		if (empty($this->themer))
405
+		{
406
+			$this->setupThemer();
407
+		}
408 408
 
409
-	    $data['uikit'] = $this->loadUIKit();
409
+		$data['uikit'] = $this->loadUIKit();
410 410
 
411
-        $output = null;
411
+		$output = null;
412 412
 
413
-	    $view = $template_name .'.tpl';
413
+		$view = $template_name .'.tpl';
414 414
 
415
-        $groups = config_item('forge.collections');
415
+		$groups = config_item('forge.collections');
416 416
 
417
-	    $name = str_replace('Generator', '', get_class($this) );
417
+		$name = str_replace('Generator', '', get_class($this) );
418 418
 
419
-        foreach ($groups as $group => $path)
420
-        {
421
-	        $path = rtrim($path, '/ ') .'/';
422
-	        $folders = scandir($path);
419
+		foreach ($groups as $group => $path)
420
+		{
421
+			$path = rtrim($path, '/ ') .'/';
422
+			$folders = scandir($path);
423 423
 
424
-	        if (! $i = array_search(ucfirst($name), $folders))
425
-	        {
426
-		        continue;
427
-	        }
424
+			if (! $i = array_search(ucfirst($name), $folders))
425
+			{
426
+				continue;
427
+			}
428 428
 
429
-	        $view = $folders[$i] . '/'. $view;
429
+			$view = $folders[$i] . '/'. $view;
430 430
 
431
-            if (realpath($path . $view .'.php'))
432
-            {
433
-                $output = $this->themer->display($group .':'. $view, $data);
434
-                break;
435
-            }
436
-        }
431
+			if (realpath($path . $view .'.php'))
432
+			{
433
+				$output = $this->themer->display($group .':'. $view, $data);
434
+				break;
435
+			}
436
+		}
437 437
 
438
-	    // To allow for including any PHP code in the templates,
439
-	    // replace any '@php' and '@=' tags with their correct PHP syntax.
440
-	    $output = str_replace('@php', '<?php', $output);
441
-	    $output = str_replace('@=', '<?=', $output);
438
+		// To allow for including any PHP code in the templates,
439
+		// replace any '@php' and '@=' tags with their correct PHP syntax.
440
+		$output = str_replace('@php', '<?php', $output);
441
+		$output = str_replace('@=', '<?=', $output);
442 442
 
443
-        return $output;
444
-    }
443
+		return $output;
444
+	}
445 445
 
446
-    //--------------------------------------------------------------------
446
+	//--------------------------------------------------------------------
447 447
 
448 448
 	/**
449 449
 	 * Forces a path to exist within the current application's folder.
@@ -458,7 +458,7 @@  discard block
 block discarded – undo
458 458
 	 */
459 459
 	public function sandbox($path)
460 460
 	{
461
-        $path = $this->normalizePath($path);
461
+		$path = $this->normalizePath($path);
462 462
 
463 463
 		// If it's writing to BASEPATH - FIX IT
464 464
 		if (strpos($path, $this->normalizePath(BASEPATH) ) === 0)
@@ -478,37 +478,37 @@  discard block
 block discarded – undo
478 478
 			return $path;
479 479
 		}
480 480
 
481
-	    return APPPATH . $path;
481
+		return APPPATH . $path;
482 482
 	}
483 483
 
484 484
 	//--------------------------------------------------------------------
485 485
 
486 486
 
487 487
 
488
-    //--------------------------------------------------------------------
489
-    // Private Methods
490
-    //--------------------------------------------------------------------
488
+	//--------------------------------------------------------------------
489
+	// Private Methods
490
+	//--------------------------------------------------------------------
491 491
 
492
-    protected function setupThemer()
493
-    {
494
-        $themer_name = config_item('forge.themer');
492
+	protected function setupThemer()
493
+	{
494
+		$themer_name = config_item('forge.themer');
495 495
 
496
-        if (! $themer_name)
497
-        {
498
-            throw new \RuntimeException( lang('forge.no_themer') );
499
-        }
496
+		if (! $themer_name)
497
+		{
498
+			throw new \RuntimeException( lang('forge.no_themer') );
499
+		}
500 500
 
501
-        $this->themer = new $themer_name( get_instance() );
501
+		$this->themer = new $themer_name( get_instance() );
502 502
 
503
-        // Register our paths with the themer
504
-        $paths = config_item('forge.collections');
503
+		// Register our paths with the themer
504
+		$paths = config_item('forge.collections');
505 505
 
506
-        foreach ($paths as $key => $path) {
507
-            $this->themer->addThemePath($key, $path);
508
-        }
509
-    }
506
+		foreach ($paths as $key => $path) {
507
+			$this->themer->addThemePath($key, $path);
508
+		}
509
+	}
510 510
 
511
-    //--------------------------------------------------------------------
511
+	//--------------------------------------------------------------------
512 512
 
513 513
 	public function loadUIKit()
514 514
 	{
@@ -521,7 +521,7 @@  discard block
 block discarded – undo
521 521
 
522 522
 		$uikit = new $kit_name();
523 523
 
524
-	    return $uikit;
524
+		return $uikit;
525 525
 	}
526 526
 
527 527
 	//--------------------------------------------------------------------
@@ -639,66 +639,66 @@  discard block
 block discarded – undo
639 639
 
640 640
 	//--------------------------------------------------------------------
641 641
 
642
-    /**
643
-     * Normalizes a path and cleans it up for healthy use within
644
-     * realpath() and helps to mitigate changes between Windows and *nix
645
-     * operating systems.
646
-     *
647
-     * Found at http://php.net/manual/en/function.realpath.php#112367
648
-     *
649
-     * @param $path
650
-     *
651
-     * @return string
652
-     */
653
-    protected function normalizePath($path)
654
-    {
655
-        // Array to build a new path from the good parts
656
-        $parts = array();
657
-
658
-        // Replace backslashes with forward slashes
659
-        $path = str_replace('\\', '/', $path);
660
-
661
-        // Combine multiple slashes into a single slash
662
-        $path = preg_replace('/\/+/', '/', $path);
663
-
664
-        // Collect path segments
665
-        $segments = explode('/', $path);
666
-
667
-        // Initialize testing variable
668
-        $test = '';
669
-
670
-        foreach($segments as $segment)
671
-        {
672
-            if($segment != '.')
673
-            {
674
-                $test = array_pop($parts);
675
-
676
-                if(is_null($test))
677
-                {
678
-                    $parts[] = $segment;
679
-                }
680
-                else if ($segment == '..')
681
-                {
682
-                    if ($test == '..')
683
-                    {
684
-                        $parts[] = $test;
685
-                    }
686
-
687
-                    if ($test == '..' || $test == '')
688
-                    {
689
-                        $parts[] = $segment;
690
-                    }
691
-                }
692
-                else
693
-                {
694
-                    $parts[] = $test;
695
-                    $parts[] = $segment;
696
-                }
697
-            }
698
-        }
699
-        return implode('/', $parts);
700
-    }
701
-
702
-    //--------------------------------------------------------------------
642
+	/**
643
+	 * Normalizes a path and cleans it up for healthy use within
644
+	 * realpath() and helps to mitigate changes between Windows and *nix
645
+	 * operating systems.
646
+	 *
647
+	 * Found at http://php.net/manual/en/function.realpath.php#112367
648
+	 *
649
+	 * @param $path
650
+	 *
651
+	 * @return string
652
+	 */
653
+	protected function normalizePath($path)
654
+	{
655
+		// Array to build a new path from the good parts
656
+		$parts = array();
657
+
658
+		// Replace backslashes with forward slashes
659
+		$path = str_replace('\\', '/', $path);
660
+
661
+		// Combine multiple slashes into a single slash
662
+		$path = preg_replace('/\/+/', '/', $path);
663
+
664
+		// Collect path segments
665
+		$segments = explode('/', $path);
666
+
667
+		// Initialize testing variable
668
+		$test = '';
669
+
670
+		foreach($segments as $segment)
671
+		{
672
+			if($segment != '.')
673
+			{
674
+				$test = array_pop($parts);
675
+
676
+				if(is_null($test))
677
+				{
678
+					$parts[] = $segment;
679
+				}
680
+				else if ($segment == '..')
681
+				{
682
+					if ($test == '..')
683
+					{
684
+						$parts[] = $test;
685
+					}
686
+
687
+					if ($test == '..' || $test == '')
688
+					{
689
+						$parts[] = $segment;
690
+					}
691
+				}
692
+				else
693
+				{
694
+					$parts[] = $test;
695
+					$parts[] = $segment;
696
+				}
697
+			}
698
+		}
699
+		return implode('/', $parts);
700
+	}
701
+
702
+	//--------------------------------------------------------------------
703 703
 
704 704
 }
Please login to merge, or discard this patch.
myth/Forge/FileKit.php 1 patch
Indentation   +197 added lines, -197 removed lines patch added patch discarded remove patch
@@ -32,206 +32,206 @@
 block discarded – undo
32 32
 
33 33
 class FileKit {
34 34
 
35
-    /**
36
-     * Appends data to the end of a file.
37
-     *
38
-     * @param $file
39
-     * @param $content
40
-     * @return bool|int
41
-     */
42
-    public function append($file, $content)
43
-    {
44
-        if (empty($content))
45
-        {
46
-            return true;
47
-        }
48
-
49
-        // Ensure that $content has a newline at the end
50
-        $content = rtrim($content) ."\n";
51
-
52
-        $fh = fopen($file, 'a');
53
-        $result = fwrite($fh, $content);
54
-        fclose($fh);
55
-
56
-        return $result;
57
-    }
58
-
59
-    //--------------------------------------------------------------------
60
-
61
-    /**
62
-     * Prepends string content to a file. For very large files
63
-     * this method could have memory issues, but the primary usage
64
-     * of source files shouldn't ever get large enough to cause issues.
65
-     *
66
-     * @param $file
67
-     * @param $content
68
-     * @return bool|int
69
-     */
70
-    public function prepend($file, $content)
71
-    {
72
-        if (empty($content))
73
-        {
74
-            return true;
75
-        }
76
-
77
-        // Ensure that $content has a newline at the end
78
-        $content = rtrim($content) ."\n";
79
-
80
-        $file_contents = file_get_contents($file);
81
-
82
-        if ($file_contents === false)
83
-        {
84
-            throw new \RuntimeException( sprintf(lang('errors.reading_file'), $file));
85
-        }
86
-
87
-        $result = file_put_contents($file, $content . $file_contents);
88
-
89
-        return (bool)$result;
90
-    }
91
-
92
-    //--------------------------------------------------------------------
93
-
94
-    /**
95
-     * Inserts $content before the line that matches $before. NOT case-
96
-     * sensitive.
97
-     *
98
-     * @param $file
99
-     * @param $before
100
-     * @param $content
101
-     * @return int
102
-     */
103
-    public function before($file, $before, $content)
104
-    {
105
-        if (empty($content))
106
-        {
107
-            return true;
108
-        }
109
-
110
-        // Ensure that $content has a newline at the end
111
-        $content = rtrim($content) ."\n";
112
-
113
-        $lines = file($file);
114
-
115
-        if ($lines === false)
116
-        {
117
-            throw new \RuntimeException( sprintf( lang('errors.file_not_found'), $file ));
118
-        }
119
-
120
-        // Where to insert the row.
121
-        $location = null;
122
-
123
-        foreach ($lines as $index => $line)
124
-        {
125
-            if (strtolower($line) == strtolower($before) )
126
-            {
127
-                $location = $index;
128
-                break;
129
-            }
130
-        }
131
-
132
-        array_splice($lines, $location, 0, $content);
133
-
134
-        $result = file_put_contents($file, $lines);
135
-
136
-        return (bool)$result;
137
-    }
138
-
139
-    //--------------------------------------------------------------------
140
-
141
-    public function after($file, $after, $content)
142
-    {
143
-        if (empty($content))
144
-        {
145
-            return true;
146
-        }
147
-
148
-        // Ensure that $content has a newline at the end
149
-        $content = rtrim($content) ."\n";
150
-
151
-        $lines = file($file);
152
-
153
-        if ($lines === false)
154
-        {
155
-            throw new \RuntimeException( sprintf( lang('errors.file_not_found'), $file ) );
156
-        }
157
-
158
-        // Where to insert the row.
159
-        $location = null;
160
-
161
-        foreach ($lines as $index => $line)
162
-        {
163
-            if (strtolower($line) == strtolower($after) )
164
-            {
165
-                $location = $index;
166
-                break;
167
-            }
168
-        }
169
-
170
-        array_splice($lines, $location +1, 0, $content);
171
-
172
-        $result = file_put_contents($file, $lines);
173
-
174
-        return (bool)$result;
175
-    }
176
-
177
-    //--------------------------------------------------------------------
178
-
179
-    /**
180
-     * Replaces all instances of $search in the file with $replace.
181
-     *
182
-     * @param $file
183
-     * @param $search
184
-     * @param $replace
185
-     * @return int
186
-     */
187
-    public function replaceIn($file, $search, $replace)
188
-    {
189
-        $file_contents = file_get_contents($file);
190
-
191
-        if ($file_contents === false)
192
-        {
193
-            throw new \RuntimeException( sprintf( lang('errors.reading_file'), $file ) );
194
-        }
195
-
196
-        $file_contents = str_replace($search, $replace, $file_contents);
197
-
198
-        $result = file_put_contents($file, $file_contents);
199
-
200
-        return (bool)$result;
201
-    }
202
-
203
-    //--------------------------------------------------------------------
204
-
205
-    /**
206
-     * Uses preg_replace to replace content within the file.
207
-     *
208
-     * @param $file
209
-     * @param $pattern
210
-     * @param $replace
211
-     * @return int
212
-     */
213
-    public function replaceWithRegex($file, $pattern, $replace)
214
-    {
215
-        $file_contents = file_get_contents($file);
216
-
217
-        if ($file_contents === false)
218
-        {
219
-            throw new \RuntimeException( sprintf( lang('errors.reading_file'), $file ) );
220
-        }
35
+	/**
36
+	 * Appends data to the end of a file.
37
+	 *
38
+	 * @param $file
39
+	 * @param $content
40
+	 * @return bool|int
41
+	 */
42
+	public function append($file, $content)
43
+	{
44
+		if (empty($content))
45
+		{
46
+			return true;
47
+		}
48
+
49
+		// Ensure that $content has a newline at the end
50
+		$content = rtrim($content) ."\n";
51
+
52
+		$fh = fopen($file, 'a');
53
+		$result = fwrite($fh, $content);
54
+		fclose($fh);
55
+
56
+		return $result;
57
+	}
58
+
59
+	//--------------------------------------------------------------------
60
+
61
+	/**
62
+	 * Prepends string content to a file. For very large files
63
+	 * this method could have memory issues, but the primary usage
64
+	 * of source files shouldn't ever get large enough to cause issues.
65
+	 *
66
+	 * @param $file
67
+	 * @param $content
68
+	 * @return bool|int
69
+	 */
70
+	public function prepend($file, $content)
71
+	{
72
+		if (empty($content))
73
+		{
74
+			return true;
75
+		}
76
+
77
+		// Ensure that $content has a newline at the end
78
+		$content = rtrim($content) ."\n";
79
+
80
+		$file_contents = file_get_contents($file);
81
+
82
+		if ($file_contents === false)
83
+		{
84
+			throw new \RuntimeException( sprintf(lang('errors.reading_file'), $file));
85
+		}
86
+
87
+		$result = file_put_contents($file, $content . $file_contents);
88
+
89
+		return (bool)$result;
90
+	}
91
+
92
+	//--------------------------------------------------------------------
93
+
94
+	/**
95
+	 * Inserts $content before the line that matches $before. NOT case-
96
+	 * sensitive.
97
+	 *
98
+	 * @param $file
99
+	 * @param $before
100
+	 * @param $content
101
+	 * @return int
102
+	 */
103
+	public function before($file, $before, $content)
104
+	{
105
+		if (empty($content))
106
+		{
107
+			return true;
108
+		}
109
+
110
+		// Ensure that $content has a newline at the end
111
+		$content = rtrim($content) ."\n";
112
+
113
+		$lines = file($file);
114
+
115
+		if ($lines === false)
116
+		{
117
+			throw new \RuntimeException( sprintf( lang('errors.file_not_found'), $file ));
118
+		}
119
+
120
+		// Where to insert the row.
121
+		$location = null;
122
+
123
+		foreach ($lines as $index => $line)
124
+		{
125
+			if (strtolower($line) == strtolower($before) )
126
+			{
127
+				$location = $index;
128
+				break;
129
+			}
130
+		}
131
+
132
+		array_splice($lines, $location, 0, $content);
133
+
134
+		$result = file_put_contents($file, $lines);
135
+
136
+		return (bool)$result;
137
+	}
138
+
139
+	//--------------------------------------------------------------------
140
+
141
+	public function after($file, $after, $content)
142
+	{
143
+		if (empty($content))
144
+		{
145
+			return true;
146
+		}
147
+
148
+		// Ensure that $content has a newline at the end
149
+		$content = rtrim($content) ."\n";
150
+
151
+		$lines = file($file);
152
+
153
+		if ($lines === false)
154
+		{
155
+			throw new \RuntimeException( sprintf( lang('errors.file_not_found'), $file ) );
156
+		}
157
+
158
+		// Where to insert the row.
159
+		$location = null;
160
+
161
+		foreach ($lines as $index => $line)
162
+		{
163
+			if (strtolower($line) == strtolower($after) )
164
+			{
165
+				$location = $index;
166
+				break;
167
+			}
168
+		}
169
+
170
+		array_splice($lines, $location +1, 0, $content);
171
+
172
+		$result = file_put_contents($file, $lines);
173
+
174
+		return (bool)$result;
175
+	}
176
+
177
+	//--------------------------------------------------------------------
178
+
179
+	/**
180
+	 * Replaces all instances of $search in the file with $replace.
181
+	 *
182
+	 * @param $file
183
+	 * @param $search
184
+	 * @param $replace
185
+	 * @return int
186
+	 */
187
+	public function replaceIn($file, $search, $replace)
188
+	{
189
+		$file_contents = file_get_contents($file);
190
+
191
+		if ($file_contents === false)
192
+		{
193
+			throw new \RuntimeException( sprintf( lang('errors.reading_file'), $file ) );
194
+		}
195
+
196
+		$file_contents = str_replace($search, $replace, $file_contents);
197
+
198
+		$result = file_put_contents($file, $file_contents);
199
+
200
+		return (bool)$result;
201
+	}
202
+
203
+	//--------------------------------------------------------------------
204
+
205
+	/**
206
+	 * Uses preg_replace to replace content within the file.
207
+	 *
208
+	 * @param $file
209
+	 * @param $pattern
210
+	 * @param $replace
211
+	 * @return int
212
+	 */
213
+	public function replaceWithRegex($file, $pattern, $replace)
214
+	{
215
+		$file_contents = file_get_contents($file);
216
+
217
+		if ($file_contents === false)
218
+		{
219
+			throw new \RuntimeException( sprintf( lang('errors.reading_file'), $file ) );
220
+		}
221 221
 
222
-        $file_contents = preg_replace($pattern, $replace, $file_contents);
223
-
224
-        $result = false;
222
+		$file_contents = preg_replace($pattern, $replace, $file_contents);
223
+
224
+		$result = false;
225 225
 
226
-        // Don't let us erase a file!
227
-        if (! empty($file_contents))
228
-        {
229
-            $result = file_put_contents( $file, $file_contents );
230
-        }
226
+		// Don't let us erase a file!
227
+		if (! empty($file_contents))
228
+		{
229
+			$result = file_put_contents( $file, $file_contents );
230
+		}
231 231
 
232
-        return (bool)$result;
233
-    }
232
+		return (bool)$result;
233
+	}
234 234
 
235
-    //--------------------------------------------------------------------
235
+	//--------------------------------------------------------------------
236 236
 
237 237
 }
Please login to merge, or discard this patch.