Completed
Push — master ( 7eba8f...c52d76 )
by Iman
18s queued 10s
created

CRUDBooster::isColumnExists()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
nc 1
nop 2
dl 0
loc 3
c 0
b 0
f 0
cc 1
rs 10
1
<?php
2
3
namespace crocodicstudio\crudbooster\helpers;
4
5
use crocodicstudio\crudbooster\CBCoreModule\CbUsersRepo;
6
use crocodicstudio\crudbooster\helpers\Cache as LaravelCache;
7
use crocodicstudio\crudbooster\Modules\LogsModule\LogsRepository;
8
use crocodicstudio\crudbooster\Modules\ModuleGenerator\ControllerGenerator;
9
use Session;
10
use Request;
11
use Schema;
12
use Cache;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, crocodicstudio\crudbooster\helpers\Cache. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
13
use DB;
14
use Route;
15
use Config;
16
use Validator;
17
18
class CRUDBooster
19
{
20
    public static function get($table, $string_conditions = null, $orderby = null, $limit = null, $skip = null)
21
    {
22
        $table = self::parseSqlTable($table);
23
        $table = $table['table'];
24
        $query = DB::table($table);
25
        if ($string_conditions) {
26
            $query->whereraw($string_conditions);
27
        }
28
        if ($orderby) {
29
            $query->orderbyraw($orderby);
30
        }
31
        if ($limit) {
32
            $query->take($limit);
33
        }
34
        if ($skip) {
35
            $query->skip($skip);
36
        }
37
38
        return $query->get();
39
    }
40
41
    public static function parseSqlTable($table)
42
    {
43
        $f = explode('.', $table);
44
45
        if (count($f) == 1) {
46
            return ["table" => $f[0], "database" => cbConfig('MAIN_DB_DATABASE')];
47
        }
48
        if (count($f) == 2) {
49
            return ["database" => $f[0], "table" => $f[1]];
50
        }
51
52
        if (count($f) == 3) {
53
            return ["table" => $f[0], "schema" => $f[1], "table" => $f[2]];
54
        }
55
56
        return false;
57
    }
58
59
    public static function me()
60
    {
61
        return CbUsersRepo::find(session('admin_id'));
62
    }
63
64
    public static function myName()
65
    {
66
        return session('admin_name');
67
    }
68
69
    public static function myPhoto()
70
    {
71
        return session('admin_photo');
72
    }
73
74
    public static function myPrivilege()
75
    {
76
        $roles = session('admin_privileges_roles');
77
        if (! $roles) {
78
            return;
79
        }
80
        foreach ($roles as $role) {
81
            if ($role->path == self::getModulePath()) {
82
                return $role;
83
            }
84
        }
85
    }
86
87
    private static function getModulePath()
88
    {
89
        $adminPathSegments = count(explode('/',cbConfig('ADMIN_PATH')));
90
        return Request::segment(1 + $adminPathSegments);
91
    }
92
93
    public static function isLocked()
94
    {
95
        return session('admin_lock');
96
    }
97
98
    public static function isSuperadmin()
99
    {
100
        return session('admin_is_superadmin');
101
    }
102
103
    public static function canView()
104
    {
105
        return self::canDo('is_visible');
106
    }
107
108
    public static function canUpdate()
109
    {
110
        return self::canDo('is_edit');
111
    }
112
113
    public static function canCreate()
114
    {
115
        return self::canDo('is_create');
116
    }
117
118
    public static function canRead()
119
    {
120
        return self::canDo('is_read');
121
    }
122
123
    public static function canDelete()
124
    {
125
        return self::canDo('is_delete');
126
    }
127
128
    public static function canCRUD()
129
    {
130
        if (self::isSuperadmin()) {
131
            return true;
132
        }
133
134
        $session = session('admin_privileges_roles');
135
        foreach ($session as $v) {
136
            if ($v->path !== self::getModulePath()) {
137
                continue;
138
            }
139
            if ($v->is_visible && $v->is_create && $v->is_read && $v->is_edit && $v->is_delete) {
140
                return true;
141
            }
142
143
            return false;
144
        }
145
    }
146
147
    public static function getCurrentModule()
148
    {
149
        return GetCurrentX::getCurrentModule();
150
    }
151
152
    public static function getCurrentDashboardId()
153
    {
154
        return GetCurrentX::getCurrentDashboardId();
155
    }
156
157
    public static function getCurrentMenuId()
158
    {
159
        return GetCurrentX::getCurrentMenuId();
160
    }
161
162
    public static function myPrivilegeId()
163
    {
164
        return session('admin_privileges');
165
    }
166
167
    public static function adminPath($path = null)
168
    {
169
        return url(cbAdminPath().'/'.$path);
170
    }
171
172
    public static function myPrivilegeName()
173
    {
174
        return session('admin_privileges_name');
175
    }
176
177
    public static function deleteConfirm($redirectTo)
178
    {
179
        echo 'swal({   
180
				title: "'.cbTrans('delete_title_confirm').'",   
0 ignored issues
show
Bug introduced by
Are you sure cbTrans('delete_title_confirm') of type null|string|array can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

180
				title: "'./** @scrutinizer ignore-type */ cbTrans('delete_title_confirm').'",   
Loading history...
181
				text: "'.cbTrans('delete_description_confirm').'",   
0 ignored issues
show
Bug introduced by
Are you sure cbTrans('delete_description_confirm') of type null|string|array can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

181
				text: "'./** @scrutinizer ignore-type */ cbTrans('delete_description_confirm').'",   
Loading history...
182
				type: "warning",   
183
				showCancelButton: true,   
184
				confirmButtonColor: "#ff0000",   
185
				confirmButtonText: "'.cbTrans('confirmation_yes').'",  
0 ignored issues
show
Bug introduced by
Are you sure cbTrans('confirmation_yes') of type null|string|array can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

185
				confirmButtonText: "'./** @scrutinizer ignore-type */ cbTrans('confirmation_yes').'",  
Loading history...
186
				cancelButtonText: "'.cbTrans('confirmation_no').'",  
0 ignored issues
show
Bug introduced by
Are you sure cbTrans('confirmation_no') of type null|string|array can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

186
				cancelButtonText: "'./** @scrutinizer ignore-type */ cbTrans('confirmation_no').'",  
Loading history...
187
				closeOnConfirm: false }, 
188
				function(){  location.href="'.$redirectTo.'" });';
189
    }
190
191
    public static function getCurrentId()
192
    {
193
        return GetCurrentX::getCurrentId();
194
    }
195
196
    public static function getCurrentMethod()
197
    {
198
        return GetCurrentX::getCurrentMethod();
199
    }
200
201
    public static function clearCache($name)
202
    {
203
        return Cache::forget($name);
204
    }
205
206
    public static function isColumnNULL($table, $field)
207
    {
208
        return DbInspector::isColNull($table, $field);
209
    }
210
211
    public static function getValueFilter($field)
212
    {
213
        $filter = request('filter_column');
214
        if ($filter[$field]) {
215
            return $filter[$field]['value'];
216
        }
217
    }
218
219
    private static function getFilter($field, $index)
220
    {
221
        $filter = request('filter_column');
222
        if ($filter[$field]) {
223
            return $filter[$field][$index];
224
        }
225
    }
226
227
    public static function getSortingFilter($field)
228
    {
229
        return self::getFilter($field, 'sorting');
230
    }
231
232
    public static function getTypeFilter($field)
233
    {
234
        return self::getFilter($field, 'type');
235
    }
236
237
    public static function stringBetween($string, $start, $end)
238
    {
239
        $string = ' '.$string;
240
        $ini = strpos($string, $start);
241
        if ($ini == 0) {
242
            return '';
243
        }
244
        $ini += strlen($start);
245
        $len = strpos($string, $end, $ini) - $ini;
246
247
        return substr($string, $ini, $len);
248
    }
249
250
    public static function timeAgo($datetime_to, $datetime_from = null, $full = false)
251
    {
252
        $datetime_from = ($datetime_from) ?: date('Y-m-d H:i:s');
253
        $now = new \DateTime;
254
        if ($datetime_from != '') {
255
            $now = new \DateTime($datetime_from);
256
        }
257
        $ago = new \DateTime($datetime_to);
258
        $diff = $now->diff($ago);
259
260
        $diff->w = floor($diff->d / 7);
0 ignored issues
show
Bug introduced by
The property w does not seem to exist on DateInterval.
Loading history...
261
        $diff->d -= $diff->w * 7;
262
263
        $string = [
264
            'y' => 'year',
265
            'm' => 'month',
266
            'w' => 'week',
267
            'd' => 'day',
268
            'h' => 'hour',
269
            'i' => 'minute',
270
            's' => 'second',
271
        ];
272
        foreach ($string as $k => &$v) {
273
            if ($diff->$k) {
274
                $v = $diff->$k.' '.$v.($diff->$k > 1 ? 's' : '');
275
            } else {
276
                unset($string[$k]);
277
            }
278
        }
279
280
        if (! $full) {
281
            $string = array_slice($string, 0, 1);
282
        }
283
284
        return $string ? implode(', ', $string).' ' : 'just now';
285
    }
286
287
    public static function sendEmailQueue($queue)
288
    {
289
        return (new Mailer())->sendEmailQueue($queue);
0 ignored issues
show
Bug introduced by
Are you sure the usage of new crocodicstudio\crudb...>sendEmailQueue($queue) targeting crocodicstudio\crudboost...ailer::sendEmailQueue() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
290
    }
291
292
    public static function sendEmail($config = [])
293
    {
294
        return (new Mailer())->send($config);
295
    }
296
297
    public static function first($table, $id)
298
    {
299
        $table = self::parseSqlTable($table)['table'];
300
        if (! is_array($id)) {
301
            $pk = self::pk($table);
302
303
            return DB::table($table)->where($pk, $id)->first();
304
        }
305
306
        $first = DB::table($table);
307
        foreach ($id as $k => $v) {
308
            $first->where($k, $v);
309
        }
310
311
        return $first->first();
312
    }
313
314
    public static function pk($table)
315
    {
316
        return self::findPrimaryKey($table);
317
    }
318
319
    public static function findPrimaryKey($table)
320
    {
321
        return DbInspector::findPK($table);
322
    }
323
324
    public static function getCache($section, $cacheName)
325
    {
326
        return LaravelCache::get($section, $cacheName);
327
    }
328
329
    public static function putCache($section, $cacheName, $cacheValue)
330
    {
331
        return LaravelCache::put($section, $cacheName, $cacheValue);
332
    }
333
334
    public static function valid($arr = [], $type = 'json')
335
    {
336
        $input_arr = request()->all();
337
338
        foreach ($arr as $a => $b) {
339
            if (is_int($a)) {
340
                $arr[$b] = 'required';
341
            } else {
342
                $arr[$a] = $b;
343
            }
344
        }
345
346
        $validator = Validator::make($input_arr, $arr);
347
348
        if (!$validator->fails()) {
349
            return true;
350
        }
351
        $message = $validator->errors()->all();
352
353
        if ($type == 'json') {
354
            $result = [];
355
            $result['api_status'] = 0;
356
            $result['api_message'] = implode(', ', $message);
357
            sendAndTerminate(response()->json($result, 200));
0 ignored issues
show
Bug introduced by
The method json() does not exist on Symfony\Component\HttpFoundation\Response. It seems like you code against a sub-type of Symfony\Component\HttpFoundation\Response such as Illuminate\Http\Response or Illuminate\Http\JsonResponse or Illuminate\Http\RedirectResponse. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

357
            sendAndTerminate(response()->/** @scrutinizer ignore-call */ json($result, 200));
Loading history...
358
        }
359
360
        $res = redirect()->back()->with(['message' => implode('<br/>', $message), 'message_type' => 'warning'])->withInput();
361
        sendAndTerminate($res);
362
    }
363
364
    public static function flushCache()
365
    {
366
        Cache::flush();
367
    }
368
369
    public static function forgetCache($section, $cacheName)
370
    {
371
        return LaravelCache::forgetCache($section, $cacheName);
372
    }
373
374
    public static function getForeignKey($parent_table, $child_table)
375
    {
376
        $parent_table = CRUDBooster::parseSqlTable($parent_table)['table'];
377
        $child_table = CRUDBooster::parseSqlTable($child_table)['table'];
378
379
        if (\Schema::hasColumn($child_table, 'id_'.$parent_table)) {
380
            return 'id_'.$parent_table;
381
        }
382
        return $parent_table.'_id';
383
    }
384
385
    public static function getTableForeignKey($fieldName)
386
    {
387
        if (substr($fieldName, 0, 3) == 'id_' || substr($fieldName, -3) == '_id') {
388
            return str_replace(['_id', 'id_'], '', $fieldName);
389
        }
390
    }
391
392
    public static function isForeignKey($fieldName)
393
    {
394
        return DbInspector::isForeignKeey($fieldName);
395
    }
396
397
    public static function urlFilterColumn($key, $type, $value = '', $singleSorting = true)
398
    {
399
        $params = request()->all();
400
        $mainpath = trim(self::mainpath(), '/');
401
402
        if ($params['filter_column'] && $singleSorting) {
403
            foreach ($params['filter_column'] as $k => $filter) {
404
                foreach ($filter as $t => $val) {
405
                    if ($t == 'sorting') {
406
                        unset($params['filter_column'][$k]['sorting']);
407
                    }
408
                }
409
            }
410
        }
411
412
        $params['filter_column'][$key][$type] = $value;
413
414
        if (isset($params)) {
415
            return $mainpath.'?'.http_build_query($params);
416
        }
417
        return $mainpath.'?filter_column['.$key.']['.$type.']='.$value;
418
419
    }
420
421
    public static function mainpath($path = null)
422
    {
423
        $controllerName = strtok(Route::currentRouteAction(), '@');
424
        // $controllerName = array_pop(explode('\\', $controllerName));
425
        $controllerName = basename($controllerName);
426
        $route_url = route($controllerName.'GetIndex');
427
428
        if (! $path) {
429
            return trim($route_url, '/');
430
        }
431
432
        if (substr($path, 0, 1) == '?') {
433
            return trim($route_url, '/').$path;
434
        }
435
436
        return $route_url.'/'.$path;
437
    }
438
439
    public static function insertLog($description)
440
    {
441
        LogsRepository::insertLog($description, self::myId());
442
    }
443
444
    public static function insertTryLog($action, $name = '')
445
    {
446
        self::insertLog(trans("logging.log_try_".$action, ['name' => $name, 'module' => self::getCurrentModule()]));
447
    }
448
449
    public static function myId()
450
    {
451
        return session('admin_id');
452
    }
453
454
    public static function referer()
455
    {
456
        return Request::server('HTTP_REFERER');
457
    }
458
459
    public static function listTables()
460
    {
461
        return DbInspector::listTables();
462
    }
463
464
    public static function listCbTables()
465
    {
466
        $tablesList = [];
467
        foreach (self::listTables() as $tableObj) {
468
469
            $tableName = $tableObj->TABLE_NAME;
470
            if ($tableName == config('database.migrations')) {
471
                continue;
472
            }
473
            if (substr($tableName, 0, 4) == 'cms_' && $tableName != 'cms_users') {
474
                continue;
475
            }
476
477
            $tablesList[] = $tableName;
478
        }
479
480
        return $tablesList;
481
    }
482
483
    public static function getUrlParameters($exception = null)
484
    {
485
        @$get = $_GET;
486
        $inputhtml = '';
487
488
        if (! $get) {
489
            return $inputhtml;
490
        }
491
        if (is_array($exception)) {
492
            foreach ($exception as $e) {
493
                unset($get[$e]);
494
            }
495
        }
496
497
        $string_parameters = http_build_query($get);
498
        foreach (explode('&', $string_parameters) as $s) {
499
            $part = explode('=', $s);
500
            $name = urldecode($part[0]);
501
            $value = urldecode($part[1]);
502
            $inputhtml .= "<input type='hidden' name='$name' value='$value'/>";
503
        }
504
505
        return $inputhtml;
506
    }
507
508
    public static function sendFCM($regID = [], $data)
509
    {
510
        return (new GoogleFCM)->send($regID, $data);
511
    }
512
513
    public static function isExistsController($table)
514
    {
515
        $ctrlName = ucwords(str_replace('_', ' ', $table));
516
        $ctrlName = str_replace(' ', '', $ctrlName).'Controller.php';
517
        $path = base_path(controllers_dir());
518
        $path2 = base_path(controllers_dir()."ControllerMaster/");
519
520
        if (file_exists($path.'Admin'.$ctrlName) || file_exists($path2.'Admin'.$ctrlName) || file_exists($path2.$ctrlName)) {
521
            return true;
522
        }
523
524
        return false;
525
    }
526
527
    public static function generateController($table, $name = null)
528
    {
529
        return ControllerGenerator::generateController($table, $name);
530
    }
531
532
    public static function getTableColumns($table)
533
    {
534
        return DbInspector::getTableCols($table);
535
    }
536
537
    public static function getNameTable($columns)
538
    {
539
        return DbInspector::colName($columns);
540
    }
541
542
    public static function getFieldType($table, $field)
543
    {
544
        return DbInspector::getFieldTypes($table, $field);
545
    }
546
547
    public static function backWithMsg($msg, $type = 'success')
548
    {
549
        return redirect()->back()->with(['message_type' => $type, 'message' => $msg]);
550
    }
551
552
    public static function routeController($prefix, $controller, $namespace = null)
553
    {
554
        $prefix = trim($prefix, '/').'/';
555
556
        $namespace = ($namespace) ?: ctrlNamespace();
557
558
        try {
559
            Route::get($prefix, ['uses' => $controller.'@getIndex', 'as' => $controller.'GetIndex']);
560
561
            $controller_class = new \ReflectionClass($namespace.'\\'.$controller);
562
            $controller_methods = $controller_class->getMethods(\ReflectionMethod::IS_PUBLIC);
563
            $wildcards = '/{one?}/{two?}/{three?}/{four?}/{five?}';
564
            foreach ($controller_methods as $method) {
565
566
                if ($method->class == 'Illuminate\Routing\Controller' || $method->name == 'getIndex') {
567
                    continue;
568
                }
569
                if (substr($method->name, 0, 3) == 'get') {
570
                    $method_name = substr($method->name, 3);
571
                    $slug = array_filter(preg_split('/(?=[A-Z])/', $method_name));
0 ignored issues
show
Bug introduced by
It seems like preg_split('/(?=[A-Z])/', $method_name) can also be of type false; however, parameter $input of array_filter() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

571
                    $slug = array_filter(/** @scrutinizer ignore-type */ preg_split('/(?=[A-Z])/', $method_name));
Loading history...
572
                    $slug = strtolower(implode('-', $slug));
573
                    $slug = ($slug == 'index') ? '' : $slug;
574
                    Route::get($prefix.$slug.$wildcards, ['uses' => $controller.'@'.$method->name, 'as' => $controller.'Get'.$method_name]);
575
                } elseif (substr($method->name, 0, 4) == 'post') {
576
                    $method_name = substr($method->name, 4);
577
                    $slug = array_filter(preg_split('/(?=[A-Z])/', $method_name));
578
                    Route::post($prefix.strtolower(implode('-', $slug)).$wildcards, [
579
                            'uses' => $controller.'@'.$method->name,
580
                            'as' => $controller.'Post'.$method_name,
581
                        ]);
582
                }
583
            }
584
        } catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
585
586
        }
587
    }
588
589
    /*
590
    | -------------------------------------------------------------
591
    | Alternate route for Laravel Route::controller
592
    | -------------------------------------------------------------
593
    | $prefix       = path of route
594
    | $controller   = controller name
595
    | $namespace    = namespace of controller (optional)
596
    |
597
    */
598
599
    public static function denyAccess()
600
    {
601
        static::redirect(static::adminPath(), cbTrans('denied_access'));
602
    }
603
604
    public static function redirect($to, $message, $type = 'warning')
605
    {
606
        if (Request::ajax()) {
607
            sendAndTerminate(response()->json(['message' => $message, 'message_type' => $type, 'redirect_url' => $to]));
608
        }
609
610
        sendAndTerminate(redirect($to)->with(['message' => $message, 'message_type' => $type]));
0 ignored issues
show
Bug introduced by
It seems like redirect($to)->with(arra...essage_type' => $type)) can also be of type Illuminate\Routing\Redirector; however, parameter $response of sendAndTerminate() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

610
        sendAndTerminate(/** @scrutinizer ignore-type */ redirect($to)->with(['message' => $message, 'message_type' => $type]));
Loading history...
611
    }
612
613
    public static function icon($icon)
614
    {
615
        return '<i class=\'fa fa-'.$icon.'\'></i>';
616
    }
617
618
    private static function canDo($verb)
619
    {
620
        if (self::isSuperadmin()) {
621
            return true;
622
        }
623
624
        foreach (session('admin_privileges_roles') as $role) {
625
            if ($role->path == self::getModulePath()) {
626
                return (bool) $role->{$verb};
627
            }
628
        }
629
    }
630
631
    public static function componentsPath($type = '')
632
    {
633
        $componentPath = implode(DIRECTORY_SEPARATOR, ['vendor', 'crocodicstudio', 'crudbooster', 'src', 'views', 'default', 'type_components', $type]);
634
        return base_path($componentPath);
635
636
    }
637
638
    public static function PublishedComponentsPath($type = '')
639
    {
640
        $Path = implode(DIRECTORY_SEPARATOR, ['views', 'vendor', 'crudbooster', 'type_components', $type]);
641
        return resource_path($Path);
642
    }
643
644
    public static function extractBetween($raw, $mark)
645
    {
646
        list($before, $_rest) = explode("# START $mark DO NOT REMOVE THIS LINE", $raw);
647
        list($_middle, $after) = explode("# END $mark DO NOT REMOVE THIS LINE", $_rest);
648
649
        return [trim($before), trim($_middle), trim($after)];
650
    }
651
652
    /**
653
     * @param $phpCode
654
     * @param $mark
655
     * @param $newCode
656
     * @return string
657
     */
658
    public static function replaceBetweenMark($phpCode, $mark, $newCode)
659
    {
660
        list($top, $_middle, $bottom) = self::extractBetween($phpCode, $mark);
661
662
        $_code = $top."\n\n";
663
        $_code .= "            # START $mark DO NOT REMOVE THIS LINE\n";
664
        $_code .= $newCode."\n";
665
        $_code .= "            # END $mark DO NOT REMOVE THIS LINE\n\n";
666
        $_code .= '            '.$bottom;
667
668
        return $_code;
669
    }
670
}
671