├── .env.example ├── .gitignore ├── README.md ├── app ├── Controllers │ └── HomeController.php └── Models │ └── User.php ├── config └── database.php ├── database ├── .gitignore └── Migrations │ └── UserMigration.php ├── kurumi ├── public ├── .htaccess ├── css │ └── styles.css ├── index.php ├── js │ └── welcome.js ├── logo.png └── manifest.json ├── resources └── views │ ├── layouts │ └── main.kurumi.php │ └── welcome.kurumi.php ├── routes └── web.php ├── storage └── framework │ └── views │ └── .gitignore ├── vendor ├── autoload.php ├── kurumi │ ├── Consoles │ │ └── Kurumi.php │ ├── Functions │ │ ├── dd.php │ │ ├── load.php │ │ ├── redirect.php │ │ └── view.php │ ├── Http │ │ ├── Add.php │ │ ├── Parser.php │ │ ├── Route.php │ │ ├── RouteInterface.php │ │ ├── Start.php │ │ └── pages │ │ │ └── 404.php │ ├── Kurumi │ │ ├── Component.php │ │ ├── File.php │ │ ├── Haniel.php │ │ ├── Layouts.php │ │ └── TemplateInheritance.php │ └── Variable │ │ └── define.php ├── rasiel │ ├── Connect.php │ └── Migration │ │ ├── Migrate.php │ │ └── MigrationQuery.php ├── whoops │ ├── Exception │ │ ├── ErrorException.php │ │ ├── Formatter.php │ │ ├── Frame.php │ │ ├── FrameCollection.php │ │ └── Inspector.php │ ├── Handler │ │ ├── CallbackHandler.php │ │ ├── Handler.php │ │ ├── HandlerInterface.php │ │ ├── JsonResponseHandler.php │ │ ├── PlainTextHandler.php │ │ ├── PrettyPageHandler.php │ │ └── XmlResponseHandler.php │ ├── Resources │ │ ├── css │ │ │ ├── prism.css │ │ │ └── whoops.base.css │ │ ├── images │ │ │ └── bg-header.jpg │ │ ├── js │ │ │ ├── clipboard.min.js │ │ │ ├── prism.js │ │ │ ├── whoops.base.js │ │ │ └── zepto.min.js │ │ └── views │ │ │ ├── env_details.html.php │ │ │ ├── frame_code.html.php │ │ │ ├── frame_list.html.php │ │ │ ├── frames_container.html.php │ │ │ ├── frames_description.html.php │ │ │ ├── header.html.php │ │ │ ├── header_outer.html.php │ │ │ ├── layout.html.php │ │ │ ├── panel_details.html.php │ │ │ ├── panel_details_outer.html.php │ │ │ ├── panel_left.html.php │ │ │ └── panel_left_outer.html.php │ ├── Run.php │ ├── RunInterface.php │ └── Util │ │ ├── HtmlDumperOutput.php │ │ ├── Misc.php │ │ ├── SystemFacade.php │ │ └── TemplateHelper.php └── zafkiel │ └── Classloader.php └── zafkiel.php /.env.example: -------------------------------------------------------------------------------- 1 | DATABASE_NAME= 2 | DATABASE_USER=root 3 | DATABASE_PASSWORD= 4 | DATABASE_HOST=127.0.0.1 5 | DIALECT=mysql 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | /node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Kurumi Framework

2 | 3 | 4 |

5 | Kurumi 6 |

7 | 8 |

9 | 10 | 11 | 12 | ## 📕 Pengenalan Framework 13 | 14 | **Kurumi** adalah sebuah Framework sederhana yang namanya terinspirasi dari sebuah karakter anime yaitu **Tokisaki Kurumi** Kami membuat Framework ini bertujuan untuk memberi kemudahan kepada user untuk membuat sebuah web aplikasi mengunakan bahasa **PHP NATIVE** 15 | 16 | 17 | 18 | ## ⚠️ Warning!! 19 | 20 | _Kami mengembangkan Framework ini tanpa mengunakan [composer](https://getcomposer.org)_ 21 | 22 |

23 | 24 | 25 | 26 | ## 🧐 Fitur Framework 27 | 28 | **Fitur-Fitur yang tersedia:** 29 | 30 | - [Routing](#-routing) 31 | - [View](#-view) 32 | - [Kurumi Template Engine](#-kurumi-template-engine) 33 | - [Database Query](#) 34 | 35 |

36 | 37 | 38 | 39 | ## 🛠️ Instalasi Framework 40 | 41 | Kami menyediakan 2 cara instalasi, yaitu dengan : 42 | 43 | **1. Clone repository** 44 | 45 | Kamu dapat membuka terminal dan menggunakan perintah berikut. 46 | 47 | ``` 48 | git clone https://github.com/bydefaultiloveyou/Kurumi.git && cd Kurumi && rm -rf .git 49 | ``` 50 | 51 | Secara otomatis akan melakukan cloning pada source code yang ada di branch default ( `master` ), jika ingin mengunduh versi stable bisa menambahkan `-b 1.x` di depan clone. 52 | 53 | **2. Unduh file ZIP** 54 | 55 | Kamu juga bisa mengunduhnya secara manual dengan menekan tombol di samping. [`Download`](https://github.com/iqbalthex/Kurumi/archive/refs/heads/haniel.zip) 56 | 57 |

58 | 59 | ## 🛠️ Penggunaan 60 | 61 | Setelah melakukan cloning repo atau download zip, masuk ke repo/folder 'Kurumi' melalui terminal dengan menjalankan perintah: 62 | 63 | ``` 64 | cd Kurumi 65 | ``` 66 | 67 | Untuk menjalankan server, jalankan perintah: 68 | 69 | ``` 70 | php kurumi server 71 | ``` 72 | 73 | Kemudian, buka `localhost:3000` pada browser. 74 | 75 |

76 | 77 | 78 | 79 | ## 🔫 Kurumi 80 | 81 | Kami mempunyai `kurumi`, dia adalah sebuah program simple yang akan membantu masa development aplikasi kalian. Di dalamnya ada berbagai macam command yang bisa kalian gunakan. 82 | 83 | 84 | 85 | ## 📁 Pengenalan Struktur Folder 86 | 87 | - `app` Folder paling penting, sebagian besar komponen dari aplikasimu tersimpan disini. 88 | - `config` Berisi file konfigurasi yang dapat diatur sesuai keinginanmu, dapat mempermudah pengaturan seperti database, aktivasi fitur, lokasi input dan output untuk view dan sebagainya. 89 | - `public` Berisi file-file yang boleh dilihat oleh user maupun developer secara publik. 90 | - `resources` Folder resources mengandung view yang sebagai mentahanmu, tidak di compile asset seperti CSS atau JavaScript 91 | - `routes` Berisi konfigurasi rute yang dapat diakses pada aplikasimu beserta handler-nya (fungsi atau controller). 92 | - `storage` Berisi file yang dibuat secara otomatis oleh kurumi framework. 93 | - `vendor` Berisi file sistem dari framework ini. Disarankan tidak mengubah apapun yang ada di dalam sini. 94 | 95 |

96 | 97 | 98 | 99 | ## 📍 Routing 100 | 101 | **Kurumi** Mengadaptasi konsep URI dan closure, menyediakan sebuah ekpresi simple dan method yang mendefinisikan routing tanpa komplikasi file konfigurasi routing 102 | 103 | ```php 104 | use Kurumi\Http\Route; 105 | 106 | Route::get('/greeting', function () { 107 | echo 'Hello World'; 108 | }); 109 | 110 | ``` 111 | 112 | Semua routing **Kurumi** di definisikan di file routing mu, yang berlokasi di `routes directory`, file ini otomatis dijalankan oleh aplikasimu. File routes/web.php itu mendefinisikan sebuah tampilan web mu. 113 | 114 | Kamu akan mendefinikan di file routes/web.php dan akan di akses setiap kamu mengunjungi url di browsermu. Seperti contoh, kamu mungkin mengakses routing mengikuti navigasi seperti http://kurumi.com/user di browser mu : 115 | 116 | ```php 117 | use App\Controllers\UserController; 118 | 119 | Route::get('/user', [UserController::class, 'index']); 120 | ``` 121 | 122 | ini akan secara otomatis akan di akses jika kamu mengunjung route `/user` di web browsermu 123 | 124 | ### 🥳 Routing Yang Tersedia 125 | 126 | Kurumi menyediakan beberapa pilihan routing seperti 127 | 128 | ```php 129 | Route::get($uri, $callback); 130 | Route::post($uri, $callback); 131 | Route::put($uri, $callback); 132 | Route::delete($uri, $callback); 133 | ``` 134 | 135 | #### GET 136 | 137 | ```php 138 | Route::get($uri, $callback); 139 | ``` 140 | 141 | Method GET biasanya digunakan hanya mengambil data. Disini juga tempat untuk menampilan halaman website mu dengan : 142 | 143 | ```php 144 | view($filename) 145 | ``` 146 | 147 | #### POST 148 | 149 | ```php 150 | Route::post($uri, $callback); 151 | ``` 152 | 153 | Method POST digunakan untuk mengirimkan data ke server yang ditentukan, sering menyebabkan perubahan pada keadaan atau efek samping pada server. bahasa simple nya nginsert data ke Database 154 | 155 | #### PUT 156 | 157 | ```php 158 | Route::put($uri, $callback); 159 | ``` 160 | 161 | Method PUT menggantikan data yang ada dengan data yang dikirimkan / ngerubah data di Database. 162 | 163 | #### DELETE 164 | 165 | ```php 166 | Route::delete($uri, $callback); 167 | ``` 168 | 169 | Method DELETE untuk menghapus data yang ada di Database. 170 | 171 |

172 | 173 | 174 | 175 | ## 🗿 View 176 | 177 | View adalah sebuah fungsi untuk menampilkan halaman web. Secara default file mengarah ke folder `resources/views` sebagai contoh 178 | di dalam folder 179 | 180 | ```bash 181 | . 182 | └── resources 183 | └── views 184 | ├── components 185 | │ └── layouts.kurumi.php 186 | └── welcome.kurumi.php 187 | ``` 188 | 189 | fungsi view secara otomatis akan menampilkan isi dari file `welcome.kurumi.php` cukup dengan menulisnya seperti di bawah ini 190 | 191 | ```php 192 | view('welcome') 193 | ``` 194 | 195 | kamu juga dapat mengirimkan data ke halaman view dengan mengirim data tersebut sebagai parameter kedua 196 | 197 | ```php 198 | view('welcome', [ 'waifu' => 'Kurumi' ]) 199 | ``` 200 | 201 | #### ⚠️ Warning Sayangku 202 | 203 | Kurumi mengadaptasi `.` sebagai lambang folder. Sebagai Contoh jika kamu ingin menampilkan file yang ada di sub directory kamu harus menyertakan format `folder.file` contoh : 204 | 205 | ```php 206 | view('components.layouts') 207 | ``` 208 | 209 | maka isi dari file `components/layouts.kurumi.php` akan ditampilkan 210 | 211 |

212 | 213 | ## 🔫 Haniel 214 | 215 | Haniel adalah nama angel milik Natsumi yang dapat merubah wujud benda apapun. Dia dapat merubah expression dan directive pada template html kamu menjadi kode php. Di bawah ini beberapa expression dan directive yang dapat digunakan : 216 | 217 | - **normal expression** 218 | 219 | ```blade 220 | { $waifu = 'kurumi' } 221 | ``` 222 | 223 | baris di atas akan diterjemahkan menjadi 224 | 225 | ```php 226 | 227 | ``` 228 | 229 |
230 | 231 | - **normal echo expression** (memunculkan nilai dari variabel) 232 | 233 | ```blade 234 | {! $waifu !} 235 | ``` 236 | 237 |
238 | 239 | - **special echo expression** (memunculkan nilai dari variabel yang dibungkus fungsi built-in php yaitu `htmlspecialchars` ) 240 | 241 | ```blade 242 | {{ $waifu }} 243 | ``` 244 | 245 |
246 | 247 | # 248 | 249 | Note: directive diawali dengan tanda `@` 250 | 251 | ### @if, @elif, @else & @endif 252 | 253 | ```blade 254 |
255 | @if ( $kurumi === "sayang lutfi" ): 256 |

😍 eh abang sayang

257 | @elseif ( $nakanoNino === "istri miko" ): 258 |

Betsuniiii >////<

259 | @else: 260 |

ayangku siapa? 🗿

261 | @endif 262 |
263 | ``` 264 | 265 |
266 | 267 | ### @each & endeach 268 | 269 | ```blade 270 | @each ( $waifus as $name ): 271 |

{{ $name }}

272 | @endeach 273 | ``` 274 | 275 |
276 | 277 | ### @include 278 | 279 | Sama seperti fungsi built-in milik php yakni include, namun tidak perlu menggunakan tag pembuka ``. @include secara default memanggil file pada folder `resources/views`. Dan perlu diingat bahwa kurumi membaca tanda titik `.` sebagai tanda garis miring `/` yang biasa menjadi pemisah antara folder. 280 | 281 | ```blade 282 | @include ('components.header') 283 | @include ('components.navbar') 284 | ``` 285 | 286 |
287 | 288 | ### @asset 289 | 290 | Dapat digunakan untuk mengambil file dari folder `public` misal kamu memiliki file css dan javascript di dalamnya. 291 | 292 | ```blade 293 | @asset ('css/style.css') 294 | @asset ('js/script.js') 295 | ``` 296 | 297 |
298 | 299 | ### @method 300 | 301 | Melengkapi form menggunakan method selain bawaan html ( `GET` dan `POST` ) seperti `PUT` dan `DELETE`. 302 | 303 | ```blade 304 |
305 | @method(DELETE) 306 | 307 | 308 |
309 | ``` 310 | 311 |

312 | 313 | ### 🎉 Template 314 | 315 | kami menyediakan template yang sederhana, template ini didorong oleh inheritance. Semua template ini harus menggunakan extension `.kurumi.php`. 316 | 317 | ## menentukan layout 318 | 319 | ```blade 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | @css ("https://fonts.googleapis.com/css2?family=Radio+Canada&display=swap" rel="stylesheet") 330 | @css ("https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css") 331 | @css ("css/styles.css") 332 | 333 | 334 | 335 | 336 | @deus ("layouts") 337 | 338 | @javascript ("https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js") 339 | 340 | 341 | 342 | ``` 343 | 344 |
345 | 346 | ### menggunakan layouts 347 | 348 | ```blade 349 | @section ("layouts") 350 | 351 |
352 |
353 | Kurumi 354 |

WELCOME TO KURUMI FRAMEWORK

355 |
356 |

Simple framework for Koneksi.php

357 | 363 |
364 |
365 |
366 | 367 | @endsection 368 | 369 | @extends ("layouts.main") 370 | ``` 371 | 372 | Perhatikan bahwa `@deus` berfungsi sebagai parent dari layout, `@deus('layouts)'` akan di isi oleh child dari layout yang telah di tentukan di `@section ('layouts')`. 373 | 374 | untuk parameter dari parent `@deus` nya harus sama dengan child di `@section`. 375 | 376 | Perhatikan juga `@extends ('layouts.main')` ini parameter nya adalah `path` dari file parent layout yang kamu punya, untuk penulisan `@extends` harus ditulis dipaling bawah code kamu. 377 | 378 |
379 | 380 | ### Component 381 | 382 | Component akan memudahkan kamu dalam menerapkan layouting, kamu dapat memecah bagian-bagian web menjadi komponen yang lebih kecil sehingga 1 komponen hanya mewakili bagian tertentu misalnya header, footer, navigation bar, hidden element dan lain-lain. 383 | 384 | Contoh pada file view utama yang terletak di `resources/views/welcome.kurumi.php` 385 | 386 | ```blade 387 | @section ("layouts") 388 | 389 | 390 | 391 |
392 |

Halo semua

393 |
394 | 395 | @endsection 396 | 397 | @extends ("layouts.main") 398 | ``` 399 | 400 | Seperti yang kamu lihat terdapat tag yang diawali 'x-' seperti berikut 401 | 402 | ```blade 403 | 404 | ``` 405 | 406 | Maka bagian tersebut akan diisi oleh komponen yang terletak di `resources/views/components/header.kurumi.php` . Selain itu, atribut yang diawali 'x-' dapat digunakan pada file ini juga. 407 | 408 | ```blade 409 |
410 |

Welcome to {{ $title }} Framework!

411 |
412 | ``` 413 | -------------------------------------------------------------------------------- /app/Controllers/HomeController.php: -------------------------------------------------------------------------------- 1 | $config_list['DATABASE_HOST'] ?? 'localhost', 22 | 23 | /** 24 | * database [default = 'kurumi'] 25 | * nama database yang digunakan 26 | */ 27 | 'database' => $config_list['DATABASE_NAME'] ?? 'kurumi', 28 | 29 | /** 30 | * user [default = 'root'] 31 | * username dari server database yang digunakan 32 | */ 33 | 'user' => $config_list['DATABASE_USER'] ?? 'root', 34 | 35 | /** 36 | * password [default = ''] 37 | * password dari server database yang digunakan 38 | */ 39 | 'password' => $config_list['DATABASE_PASSWORD'] ?? "", 40 | 41 | /** 42 | * dialect [default = mysql] 43 | * jenis dbms yang digunakan 44 | */ 45 | 'dialect' => $config_list['DIALECT'] ?? 'mysql', 46 | ]; 47 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bydefaultiloveyou/Kurumi/f4c44a4288fcd718261fcf1993e2385d806d9bdb/database/.gitignore -------------------------------------------------------------------------------- /database/Migrations/UserMigration.php: -------------------------------------------------------------------------------- 1 | createTable(function ($field) { 10 | 11 | $field->id(); 12 | $field->string('username', 100) 13 | ->unique() 14 | ->notNull() 15 | ->end(); 16 | $field->string('email', 100) 17 | ->unique() 18 | ->notNull() 19 | ->end(); 20 | $field->string('password') 21 | ->notNull() 22 | ->end(); 23 | $field->boolean('isAdmin') 24 | ->default(false) 25 | ->end(); 26 | 27 | // jangan hapus code ini 28 | $field->create(); 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /kurumi: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /public/css/styles.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: 'Radio Canada'; 3 | list-style: none; 4 | } 5 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | @css ("https://fonts.googleapis.com/css2?family=Radio+Canada&display=swap" rel="stylesheet") 11 | @css ("https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css") 12 | @css ("css/styles.css") 13 | 14 | 15 | 16 | 17 | @deus ("layouts") 18 | 19 | @javascript ("https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js") 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /resources/views/welcome.kurumi.php: -------------------------------------------------------------------------------- 1 | @section ("layouts") 2 | 3 |
4 |
5 | Kurumi 6 |

WELCOME TO KURUMI FRAMEWORK

7 |
8 |

Simple framework for Koneksi.php

9 | 15 |
16 |
17 |
18 | 19 | @endsection 20 | 21 | @extends ("layouts.main") 22 | -------------------------------------------------------------------------------- /routes/web.php: -------------------------------------------------------------------------------- 1 | rute, url yang dimasukkan pada browser 14 | | contoh: 15 | | - '/' - '/page' 16 | | - '/about' - '/user' 17 | | 18 | | => handler, dapat berupa fungsi biasa, 19 | | fungsi anonim atau controller 20 | | contoh: 21 | | - function(){} 22 | | - [Controller::class, 'method'] 23 | | 24 | | contoh lengkap: 25 | | - Route::get('/', [PageController::class, 'home']) 26 | | - Route::get('/about', [HomeController::class, 'about']) 27 | | 28 | */ 29 | 30 | 31 | Route::get('/', [HomeController::class, 'home']); 32 | 33 | Route::get('/about', function () { 34 | echo "Hello World!"; 35 | }); 36 | 37 | // jangan hapus kode di bawah sini 38 | Route::run(); 39 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | Intialize(); 10 | 11 | 12 | /** -------------------------------------------------- 13 | * Run Whoops 14 | */ 15 | $whoops = new \Whoops\Run; 16 | $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler); 17 | $whoops->register(); 18 | 19 | /** -------------------------------------------------- 20 | * Run define variable 21 | */ 22 | $_define = new \Kurumi\Variable\define; 23 | 24 | /** ------------------------------------------------- 25 | * Require Function 26 | */ 27 | require __DIR__ . '/kurumi/Functions/load.php'; 28 | 29 | 30 | /** ----------------------------------------------- 31 | * Require Routes 32 | */ 33 | require __DIR__ . '/../routes/web.php'; 34 | -------------------------------------------------------------------------------- /vendor/kurumi/Consoles/Kurumi.php: -------------------------------------------------------------------------------- 1 | argv = $argv; 19 | 20 | /** 21 | * hentikan program bila tidak ada argumen yang diberikan 22 | */ 23 | if (!isset($this->argv[1]) or $this->argv[1] === "help") { 24 | $this->handleError(); 25 | } 26 | 27 | /** 28 | * membuat file controller 29 | */ 30 | if (@$this->argv[1] === "make:controller" or @$this->argv[1] === "-c") { 31 | $this->createController(@$this->argv[2]); 32 | } 33 | 34 | /* 35 | * membuat file migration 36 | */ 37 | if (@$this->argv[1] === "make:migrate") { 38 | $this->createMigrate(@$this->argv[2]); 39 | } 40 | 41 | /** 42 | * membuat file model 43 | */ 44 | if (@$this->argv[1] === "make:model" or @$this->argv[1] === "-m") { 45 | $this->createModel(@$this->argv[2]); 46 | } 47 | 48 | /** 49 | * menjalankan server 50 | */ 51 | if (@$this->argv[1] === 'server') { 52 | $portserve = @$this->argv[2] !== null && (@$this->argv[2] === '-p') ? @$this->argv[3] : 3000; 53 | $this->server($portserve); 54 | } 55 | 56 | /** 57 | * menjalankan migration 58 | */ 59 | if (@$this->argv[1] === 'migrate') { 60 | system("php ./vendor/rasiel/Migration/Migrate.php"); 61 | } 62 | } 63 | 64 | 65 | /** 66 | * memunculkan pesan bila tidak ada argumen yang diberikan 67 | * @return void 68 | */ 69 | public function handleError(): void 70 | { 71 | echo " 72 | Welcome to Kurumi Framework 73 | 74 | ======================== kurumi command list ======================== 75 | 76 | \033[0;32m server \033[0;0m Jalanin Server 77 | 78 | \033[0;32m server -p \033[0;0m Jalanin server dengan custom port 79 | 80 | \033[0;32m make:controller \033[0;0m membuat controller handler 81 | 82 | \033[0;32m make:model \033[0;0m membuat model 83 | 84 | \033[0;32m make:migration \033[0;0m membuat migration 85 | "; 86 | } 87 | 88 | /** 89 | * jalankan server sambil memberikan kata-kata mutiara :v 90 | * @return string 91 | */ 92 | public function randQuotes(): string 93 | { 94 | $quotes = [ 95 | "jika mereka menolak untuk menerima mu \nmaka aku akan menerimamu apa adanya!.\n", 96 | "apapun yang kamu lalukan pastikan \nitu membuat kamu bahagia.\n", 97 | "untuk mencapai tujuan kita \nkita harus mengejarnya sendiri.\n", 98 | "aku ingin memiliki kenangan bersama mu \ndan juga aku ingin kau juga memiliki kenangan bersamaku.\n" 99 | ]; 100 | 101 | return $quotes[array_rand($quotes)]; 102 | } 103 | 104 | public function createMigrate(string $migrate_name): void 105 | { 106 | 107 | if (file_exists("./database/Migrations/$migrate_name.php")) { 108 | echo "\nMigrations `$migrate_name` sudah ada!\n"; 109 | die; 110 | } 111 | 112 | try { 113 | $newFile = fopen("./database/Migrations/$migrate_name.php", 'w'); 114 | $table_name = str_replace('Migration', '', $migrate_name); 115 | $table_name = strtolower($table_name . "s"); 116 | $string = 'createTable(function ($query) { 125 | 126 | // jangan hapus code ini 127 | $query->create(); 128 | }); 129 | } 130 | } 131 | '; 132 | fwrite($newFile, $string); 133 | fclose($newFile); 134 | echo "\nMigration `$migrate_name` berhasil dibuat!\n"; 135 | } catch (\Throwable $th) { 136 | $last_trace = $th->getTrace()[0]; 137 | 138 | echo " 139 | gagal membuat Migrate! 140 | 141 | {$th->getMessage()} 142 | 143 | {$last_trace['file']} 144 | from `{$last_trace['function']}` in line: {$last_trace['line']}"; 145 | } 146 | } 147 | 148 | /** 149 | * membuat controller dengan nama yang diberikan di konsol 150 | * @param string $controller_name 151 | * @return void 152 | */ 153 | public function createController(string $controller_name): void 154 | { 155 | if (file_exists("./app/Controllers/$controller_name.php")) { 156 | echo "\ncontroller `$controller_name` sudah ada!\n"; 157 | die; 158 | } 159 | 160 | try { 161 | $newFile = fopen("./app/Controllers/$controller_name.php", 'w'); 162 | $string = "getTrace()[0]; 179 | 180 | echo " 181 | gagal membuat controller! 182 | 183 | {$th->getMessage()} 184 | 185 | {$last_trace['file']} 186 | from `{$last_trace['function']}` in line: {$last_trace['line']}"; 187 | } 188 | } 189 | 190 | 191 | /** 192 | * membuat model (sekaligus tabel) dengan nama yang diberikan di konsol 193 | * @param string $model_name 194 | * @return void 195 | */ 196 | public function createModel(string $model_name): void 197 | { 198 | if (file_exists("./app/Models/$model_name.php")) { 199 | echo "\nmodel `$model_name` sudah ada!\n"; 200 | die; 201 | } 202 | 203 | try { 204 | // matikan komentar untuk tes pesan error 205 | $newFile = fopen("./app/Models/$model_name.php", 'w'); 206 | 207 | // memaksa nama tabel berbentuk jamak 208 | $table_name = strtolower($model_name) . 's'; 209 | $string = "getTrace()[0]; 229 | 230 | echo " 231 | gagal membuat model! 232 | 233 | {$th->getMessage()} 234 | 235 | {$last_trace['file']} 236 | from `{$last_trace['function']}` in line: {$last_trace['line']}"; 237 | } 238 | } 239 | 240 | 241 | public function server($port) 242 | { 243 | echo " 244 | Kurumi server is running: 245 | 246 | \033[0;32m local: http://localhost:{$port}/ 247 | \033[0;32m ip: http://127.0.0.1:{$port}/ 248 | \033[0;0m 249 | 250 | Tokisaki Kurumi: 251 | {$this->randQuotes()}"; 252 | 253 | $commandExec = "cd public/ && php -S localhost:{$port}"; 254 | 255 | exec($commandExec); 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /vendor/kurumi/Functions/dd.php: -------------------------------------------------------------------------------- 1 | path ke folder storage 14 | | @_path_php -> path ke folder resources 15 | | 16 | | @_file -> membuat file baru dengan modifikasi pada directive yang ada pada file 17 | | 18 | */ 19 | 20 | 21 | function view(string $filename, array $data = []) 22 | { 23 | $_path = __DIR__ . PATH_VIEW_STORAGE . $filename . ".kurumi.php"; 24 | $_path_php = __DIR__ . PATH_VIEW_RESOURCES . $filename . ".php"; 25 | $_file = new Kurumi\Kurumi\File; 26 | 27 | if (file_exists($_path_php)) { 28 | include_once $_path_php; 29 | } elseif (file_exists($_path)) { 30 | new Kurumi\Kurumi\Layouts($filename, $data); 31 | } else { 32 | throw new Exception("view `{$filename}` tidak ditemukan!"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /vendor/kurumi/Http/Add.php: -------------------------------------------------------------------------------- 1 | $method, 21 | "path" => Parser::segmen($path), 22 | "callback" => $callback 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /vendor/kurumi/Http/Parser.php: -------------------------------------------------------------------------------- 1 | include __DIR__ . '/pages/404.php'; 40 | 41 | // jalankan $callbacknya 42 | call_user_func_array($callback, [ 43 | [ 44 | array_merge($_GET, $_POST), 45 | $param 46 | ] 47 | ]); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /vendor/kurumi/Http/pages/404.php: -------------------------------------------------------------------------------- 1 |

404

-------------------------------------------------------------------------------- /vendor/kurumi/Kurumi/Component.php: -------------------------------------------------------------------------------- 1 | name component to the @extendContent 23 | * 24 | */ 25 | protected $component; 26 | 27 | /** 28 | * 29 | * @data -> method khusus untuk menangani data 30 | * 31 | */ 32 | protected $data; 33 | 34 | /** 35 | * 36 | * @extendContent string -> method untuk mengirimkan name component 37 | * ke @component 38 | * @component string 39 | * 40 | */ 41 | public function extendContent(string $component, $data = []) 42 | { 43 | $this->component = $component; 44 | $this->data = $data; 45 | $this->render(); 46 | } 47 | 48 | /** 49 | * 50 | * @render -> method untuk merender @component ( name_compoent ) 51 | * 52 | * 53 | */ 54 | 55 | public function render() 56 | { 57 | foreach ($this->data as $key => $value) { 58 | $$key = $value; 59 | } 60 | 61 | $path = __DIR__ . PATH_VIEW_STORAGE . "components." . trim($this->component) . ".kurumi.php"; 62 | if (file_exists($path)) { 63 | include $path; 64 | } else { 65 | throw new Exception("component `<" . trim($this->component) . "/> tidak ditemukan!"); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /vendor/kurumi/Kurumi/File.php: -------------------------------------------------------------------------------- 1 | input_files = array_merge( 40 | glob("{$this->input_directory}*.kurumi.php"), 41 | glob("{$this->input_directory}**/*.kurumi.php"), 42 | glob("{$this->input_directory}**/**/*.kurumi.php"), 43 | glob("{$this->input_directory}**/**/**/*.kurumi.php"), 44 | ); 45 | $this->output_files = glob("{$this->output_directory}*.php"); 46 | 47 | $this->sterilize(); 48 | $this->generate(); 49 | } 50 | 51 | 52 | /** 53 | * Menyesuaikan file input dan output 54 | * -> ambil nama file yang berakhiran '.kurumi.php' # (str_replace) 55 | * -> cek adakah file input # (file_exists) 56 | * -> hapus file output bila tidak ada di folder input # (unlink) 57 | * @return void 58 | */ 59 | public function sterilize(): void 60 | { 61 | foreach ($this->output_files as $file) { 62 | $base_name = str_replace('.kurumi.php', '', basename($file)); 63 | 64 | $output_dir = $this->output_directory . $base_name; 65 | $input_dir = $this->input_directory . str_replace('.', '/', $base_name); 66 | 67 | if (!file_exists("$input_dir.kurumi.php")) { 68 | unlink("$output_dir.kurumi.php"); 69 | } 70 | } 71 | } 72 | 73 | 74 | /** 75 | * Method untuk membuat file baru dengan 76 | * directive yang telah diubah menjadi kode php oleh Haniel. 77 | * -> ambil nama file tanpa direktorinya 78 | * -> ubah simbol / menjadi . # (str_replace) 79 | * -> ambil isi file # (file_get_contents) 80 | * -> buat file di folder output # (fopen, fwrite, fclose) 81 | * @return void 82 | */ 83 | public function generate(): void 84 | { 85 | foreach ($this->input_files as $file) { 86 | $filename = str_replace($this->input_directory, '', $file); 87 | $filename = str_replace('/', '.', $filename); 88 | 89 | $contents = file_get_contents($file); 90 | 91 | $file_new = fopen($this->output_directory . $filename, 'w'); 92 | fwrite($file_new, Haniel::transform($contents)); 93 | fclose($file_new); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /vendor/kurumi/Kurumi/Haniel.php: -------------------------------------------------------------------------------- 1 | {{ 'hello' }} ==> 16 | | -> {! 'hello' !} ==> 17 | | -> { $var = 123 } ==> 18 | | -> @if (true): ==> 19 | | -> @elif (true): ==> 20 | | -> @else: ==> 21 | | -> @endif ==> 22 | | -> @each ($items as $i): ==> 23 | | -> @endeach ==> 24 | | -> @include ('home') ==> 25 | | -> @asset ('style.css') ==> 26 | | -> @slot ==> 27 | | -> @method ("put") ==> 28 | | -> @css ("index.css") ==> 29 | | -> @javascript ("main.js") ==> 30 | */ 31 | 32 | class Haniel 33 | { 34 | private static string $contents; 35 | 36 | private static function _parse($pattern, $replace, bool $isPHP = TRUE): void 37 | { 38 | if ($isPHP) { 39 | $replace = "\n"; 40 | } 41 | 42 | self::$contents = preg_replace($pattern, $replace, self::$contents); 43 | } 44 | 45 | public static function transform(string $contents): string 46 | { 47 | self::$contents = $contents; 48 | 49 | self::_parse('/\{{([\s\S]*?)\}}/', 'echo htmlspecialchars($1)'); 50 | self::_parse('/\{!([\s\S]*?)\!}/', 'echo $1'); 51 | self::_parse('/\{([\s\S]*?)\}/', '$1'); 52 | self::_parse('/@if\s*\((.*)\)\s*:\s*/', 'if ($1):'); 53 | self::_parse('/@elif\s*\((.*)\)\s*:\s*/', 'elseif ($1):'); 54 | self::_parse('/\@else\s*:\s*/', 'else:'); 55 | self::_parse('/@endif/', 'endif;'); 56 | self::_parse('/@each\s*\((.*)\)\s*:\s*/', 'foreach($1):'); 57 | self::_parse('/@endeach/', 'endforeach;'); 58 | self::_parse('/@include\s*\((.*)\)\s*/', 'require __DIR__ . "/" . $1 . ".kurumi.php"'); 59 | self::_parse('/\@asset\s*\((.*)\)\s*/', 'echo $1'); 60 | self::_parse('/@slot(.*)/', 'include $slot'); 61 | self::_parse('/@method\s*\((.*)\)\s*/', '', FALSE); 62 | self::_parse('/@css\s*\((.*)\)\s*/', '', FALSE); 63 | self::_parse('/@javascript\s*\((.*)\)\s*/', '', FALSE); 64 | self::_parse('/@deus\s*\((.*)\)\s*/', '$this->deusContent($1)'); 65 | self::_parse('/@extends\s*\((.*)\)\s*/', '$__deus->extendContent($1)'); 66 | self::_parse('/@section\s*\((.*)\)\s*/', '$__deus->startContent($1)'); 67 | self::_parse('/@endsection/', '$__deus->stopContent()'); 68 | self::_parse('/@component\s*\((.*)\)\s*/', '$this->slot($1)'); 69 | // self::_parse('//', '$__comp->extendContent("$1",$3)'); 70 | 71 | self::$contents = preg_replace_callback('/\s*/', function ($m) { 72 | $matches = trim($m[1]); 73 | $matches = explode(' ', $matches); 74 | $name = $matches[0]; 75 | unset($matches[0]); 76 | 77 | $data = []; 78 | foreach ($matches as $match) { 79 | if (preg_match('/x-(.*)/', $match)) { 80 | $match = str_replace('x-', '', $match); 81 | $match = preg_replace('/(.*)="(.*)"/', '"$1"=>"$2"', $match); 82 | array_push($data, $match); 83 | } 84 | } 85 | 86 | $data = implode(', ', $data); 87 | $result = "\nextendContent(\"$name\", [$data]) ?>\n"; 88 | return $result; 89 | }, self::$contents); 90 | 91 | return self::$contents; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /vendor/kurumi/Kurumi/Layouts.php: -------------------------------------------------------------------------------- 1 | looping data dan jadikan variabel biasa 21 | * 22 | */ 23 | 24 | public function __construct(string $filename, array $data = []) 25 | { 26 | foreach ($data as $key => $value) { 27 | eval('$$key = $value;'); 28 | } 29 | 30 | $__deus = new \Kurumi\Kurumi\TemplateInheritance; 31 | $__comp = new \Kurumi\Kurumi\Component; 32 | include __DIR__ . PATH_VIEW_STORAGE . $filename . '.kurumi.php'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /vendor/kurumi/Kurumi/TemplateInheritance.php: -------------------------------------------------------------------------------- 1 | berisi nama file dari @extendContent 21 | * 22 | */ 23 | 24 | protected $template; 25 | 26 | /** 27 | * 28 | * @layout -> berisi nama layout dari @startContent 29 | * 30 | */ 31 | 32 | protected $layout; 33 | 34 | /** 35 | * 36 | * @key -> berisi key nama layout dari @startContent 37 | * -> property ini khusus untuk membuat key buffer 38 | * 39 | */ 40 | 41 | protected $key; 42 | 43 | /** 44 | * 45 | * @buffer -> berisi buffer dari @stopSection 46 | * 47 | */ 48 | 49 | protected $buffer; 50 | 51 | /** 52 | * 53 | * @deusContent -> method untuk mengirim nama layouts 54 | * ke property $layout 55 | * @layout string 56 | * 57 | */ 58 | 59 | public function deusContent(string $layout) 60 | { 61 | if (array_key_exists($layout, $this->layout)) { 62 | if ($this->layout[$layout] === $layout) { 63 | echo $this->buffer[$layout]; 64 | } 65 | } 66 | } 67 | 68 | /** 69 | * 70 | * @extendContent -> method untuk mengirim nama filetemplate 71 | * ke property $template 72 | * @template string 73 | * 74 | */ 75 | 76 | public function extendContent(string $template) 77 | { 78 | $this->template = $template; 79 | $this->render(); 80 | } 81 | 82 | /** 83 | * 84 | * @startContent -> method untuk memulai buffer dan mengirim 85 | * nama layout ke property @layout 86 | * dan mengirim key ke property @key 87 | * @layout array 88 | * 89 | */ 90 | 91 | public function startContent(string $layout) 92 | { 93 | $this->layout[$layout] = $layout; 94 | $this->key = $layout; 95 | return ob_start(); 96 | } 97 | 98 | /** 99 | * 100 | * @stopSection -> method untuk menutup buffer dan 101 | * mengirim kan buffer ke property buffer 102 | * 103 | */ 104 | 105 | public function stopContent() 106 | { 107 | $this->buffer[$this->key] = ob_get_clean(); 108 | } 109 | 110 | /** 111 | * 112 | * @render -> method untuk merender layout 113 | * 114 | */ 115 | 116 | public function render() 117 | { 118 | $path = __DIR__ . PATH_VIEW_STORAGE . $this->template . '.kurumi.php'; 119 | include $path; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /vendor/kurumi/Variable/define.php: -------------------------------------------------------------------------------- 1 | table = $table; 21 | $databaseConfig = require __DIR__ . "/../../config/database.php"; 22 | $this->connection = new PDO( 23 | "$databaseConfig[dialect]: 24 | host=$databaseConfig[host]; 25 | dbname=$databaseConfig[database]", 26 | $databaseConfig['user'], 27 | $databaseConfig['password'] 28 | ); 29 | } 30 | 31 | public function column(string $column = "*") 32 | { 33 | $this->column = $column; 34 | return $this; 35 | } 36 | 37 | public function where(string $column, string $operator, string $value) 38 | { 39 | $this->query .= " WHERE $column $operator '$value' "; 40 | return $this; 41 | } 42 | 43 | public function not(string $condition) 44 | { 45 | $this->query = " WHERE NOT $condition"; 46 | return $this; 47 | } 48 | 49 | public function order(string $column) 50 | { 51 | $this->query .= "ORDER BY $column"; 52 | return $this; 53 | } 54 | 55 | public function limit($limit) 56 | { 57 | $this->query .= " LIMIT " . (string)$limit; 58 | return $this; 59 | } 60 | 61 | public function offset($offset) 62 | { 63 | $this->query .= " OFFSET " . (string)$offset; 64 | return $this; 65 | } 66 | 67 | public function join(string $table, array $condition, string $type = "INNER") 68 | { 69 | $this->query = "{$type} JOIN {$table} ON {$condition[0]} {$condition[1]} {$condition[0]}"; 70 | return $this; 71 | } 72 | 73 | public function get() 74 | { 75 | $result = $this->connection->prepare("SELECT {$this->column} FROM tasks {$this->query};"); 76 | $result->execute(); 77 | return $result->fetchAll(); 78 | } 79 | 80 | public function fetch() 81 | { 82 | $result = $this->connection->prepare("SELECT {$this->column} FROM tasks {$this->query};"); 83 | $result->execute(); 84 | return $result->fetch(); 85 | } 86 | 87 | public function create(array $values) 88 | { 89 | $value = implode("' , '", array_values($values)); 90 | $key = implode(" , ", array_keys($values)); 91 | $query = " INSERT INTO {$this->table} ( $key ) VALUES ( '$value' )"; 92 | return $this->connection->exec("$query;"); 93 | } 94 | 95 | public function update(array $values) 96 | { 97 | foreach ($values as $key => $value) { 98 | $query = "UPDATE $this->table SET $key = '$value' {$this->query}"; 99 | $result = $this->connection->prepare($query); 100 | $result->execute(); 101 | } 102 | } 103 | 104 | public function delete() 105 | { 106 | $query = "DELETE FROM {$this->table} {$this->query}"; 107 | $result = $this->connection->exec($query); 108 | } 109 | 110 | public function createTable(callable $callback) 111 | { 112 | $callback(new MigrationQuery($this->table, $this->connection)); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /vendor/rasiel/Migration/Migrate.php: -------------------------------------------------------------------------------- 1 | up(); 25 | echo "Finish \n"; 26 | } 27 | 28 | echo "All table migrate successfull"; 29 | -------------------------------------------------------------------------------- /vendor/rasiel/Migration/MigrationQuery.php: -------------------------------------------------------------------------------- 1 | table = $table; 12 | $this->connection = $connection; 13 | } 14 | 15 | public function end() 16 | { 17 | $this->query .= ","; 18 | } 19 | 20 | public function id($count = 255) 21 | { 22 | $this->query .= "`id` bigint({$count}) NOT NULL AUTO_INCREMENT,"; 23 | } 24 | 25 | public function string($column, $count = 255) 26 | { 27 | $toString = (string)$count; 28 | $this->query .= " `{$column}` varchar({$toString})"; 29 | return $this; 30 | } 31 | 32 | public function int(string $column, $count = 255) 33 | { 34 | $toString = (string)$count; 35 | $this->query .= " `{$column}` int({$toString})"; 36 | return $this; 37 | } 38 | 39 | public function boolean(string $column) 40 | { 41 | $this->query .= " `{$column}` BOOLEAN "; 42 | return $this; 43 | } 44 | 45 | public function default($value) 46 | { 47 | if (gettype($value) === "boolean") { 48 | switch ($value) { 49 | case true: 50 | $this->query .= " DEFAULT 1"; 51 | break; 52 | case false: 53 | $this->query .= " DEFAULT 0"; 54 | break; 55 | }; 56 | return $this; 57 | } 58 | $this->query .= " DEFAULT '$value' "; 59 | return $this; 60 | } 61 | 62 | public function bigInt(string $column, $count = 255) 63 | { 64 | $toString = (string)$count; 65 | $this->query .= " `{$column}` bigint({$toString}) "; 66 | return $this; 67 | } 68 | 69 | public function notNull() 70 | { 71 | $this->query .= " NOT NULL"; 72 | return $this; 73 | } 74 | 75 | public function unique() 76 | { 77 | $this->query .= " UNIQUE"; 78 | return $this; 79 | } 80 | public function create() 81 | { 82 | $sql = "CREATE TABLE IF NOT EXISTS `{$this->table}` ({$this->query} PRIMARY KEY (`id`)) ENGINE = InnoDB;"; 83 | // echo $sql; 84 | $this->connection->exec($sql); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /vendor/whoops/Exception/ErrorException.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Exception; 8 | 9 | use ErrorException as BaseErrorException; 10 | 11 | /** 12 | * Wraps ErrorException; mostly used for typing (at least now) 13 | * to easily cleanup the stack trace of redundant info. 14 | */ 15 | class ErrorException extends BaseErrorException 16 | { 17 | } 18 | -------------------------------------------------------------------------------- /vendor/whoops/Exception/Formatter.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Exception; 8 | 9 | class Formatter 10 | { 11 | /** 12 | * Returns all basic information about the exception in a simple array 13 | * for further convertion to other languages 14 | * @param Inspector $inspector 15 | * @param bool $shouldAddTrace 16 | * @return array 17 | */ 18 | public static function formatExceptionAsDataArray(Inspector $inspector, $shouldAddTrace) 19 | { 20 | $exception = $inspector->getException(); 21 | $response = [ 22 | 'type' => get_class($exception), 23 | 'message' => $exception->getMessage(), 24 | 'code' => $exception->getCode(), 25 | 'file' => $exception->getFile(), 26 | 'line' => $exception->getLine(), 27 | ]; 28 | 29 | if ($shouldAddTrace) { 30 | $frames = $inspector->getFrames(); 31 | $frameData = []; 32 | 33 | foreach ($frames as $frame) { 34 | /** @var Frame $frame */ 35 | $frameData[] = [ 36 | 'file' => $frame->getFile(), 37 | 'line' => $frame->getLine(), 38 | 'function' => $frame->getFunction(), 39 | 'class' => $frame->getClass(), 40 | 'args' => $frame->getArgs(), 41 | ]; 42 | } 43 | 44 | $response['trace'] = $frameData; 45 | } 46 | 47 | return $response; 48 | } 49 | 50 | public static function formatExceptionPlain(Inspector $inspector) 51 | { 52 | $message = $inspector->getException()->getMessage(); 53 | $frames = $inspector->getFrames(); 54 | 55 | $plain = $inspector->getExceptionName(); 56 | $plain .= ' thrown with message "'; 57 | $plain .= $message; 58 | $plain .= '"'."\n\n"; 59 | 60 | $plain .= "Stacktrace:\n"; 61 | foreach ($frames as $i => $frame) { 62 | $plain .= "#". (count($frames) - $i - 1). " "; 63 | $plain .= $frame->getClass() ?: ''; 64 | $plain .= $frame->getClass() && $frame->getFunction() ? ":" : ""; 65 | $plain .= $frame->getFunction() ?: ''; 66 | $plain .= ' in '; 67 | $plain .= ($frame->getFile() ?: '<#unknown>'); 68 | $plain .= ':'; 69 | $plain .= (int) $frame->getLine(). "\n"; 70 | } 71 | 72 | return $plain; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /vendor/whoops/Exception/Frame.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Exception; 8 | 9 | use InvalidArgumentException; 10 | use Serializable; 11 | 12 | class Frame implements Serializable 13 | { 14 | /** 15 | * @var array 16 | */ 17 | protected $frame; 18 | 19 | /** 20 | * @var string 21 | */ 22 | protected $fileContentsCache; 23 | 24 | /** 25 | * @var array[] 26 | */ 27 | protected $comments = []; 28 | 29 | /** 30 | * @var bool 31 | */ 32 | protected $application; 33 | 34 | /** 35 | * @param array[] 36 | */ 37 | public function __construct(array $frame) 38 | { 39 | $this->frame = $frame; 40 | } 41 | 42 | /** 43 | * @param bool $shortened 44 | * @return string|null 45 | */ 46 | public function getFile($shortened = false) 47 | { 48 | if (empty($this->frame['file'])) { 49 | return null; 50 | } 51 | 52 | $file = $this->frame['file']; 53 | 54 | // Check if this frame occurred within an eval(). 55 | // @todo: This can be made more reliable by checking if we've entered 56 | // eval() in a previous trace, but will need some more work on the upper 57 | // trace collector(s). 58 | if (preg_match('/^(.*)\((\d+)\) : (?:eval\(\)\'d|assert) code$/', $file, $matches)) { 59 | $file = $this->frame['file'] = $matches[1]; 60 | $this->frame['line'] = (int) $matches[2]; 61 | } 62 | 63 | if ($shortened && is_string($file)) { 64 | // Replace the part of the path that all frames have in common, and add 'soft hyphens' for smoother line-breaks. 65 | $dirname = dirname(dirname(dirname(dirname(dirname(dirname(__DIR__)))))); 66 | if ($dirname !== '/') { 67 | $file = str_replace($dirname, "…", $file); 68 | } 69 | $file = str_replace("/", "/­", $file); 70 | } 71 | 72 | return $file; 73 | } 74 | 75 | /** 76 | * @return int|null 77 | */ 78 | public function getLine() 79 | { 80 | return isset($this->frame['line']) ? $this->frame['line'] : null; 81 | } 82 | 83 | /** 84 | * @return string|null 85 | */ 86 | public function getClass() 87 | { 88 | return isset($this->frame['class']) ? $this->frame['class'] : null; 89 | } 90 | 91 | /** 92 | * @return string|null 93 | */ 94 | public function getFunction() 95 | { 96 | return isset($this->frame['function']) ? $this->frame['function'] : null; 97 | } 98 | 99 | /** 100 | * @return array 101 | */ 102 | public function getArgs() 103 | { 104 | return isset($this->frame['args']) ? (array) $this->frame['args'] : []; 105 | } 106 | 107 | /** 108 | * Returns the full contents of the file for this frame, 109 | * if it's known. 110 | * @return string|null 111 | */ 112 | public function getFileContents() 113 | { 114 | if ($this->fileContentsCache === null && $filePath = $this->getFile()) { 115 | // Leave the stage early when 'Unknown' or '[internal]' is passed 116 | // this would otherwise raise an exception when 117 | // open_basedir is enabled. 118 | if ($filePath === "Unknown" || $filePath === '[internal]') { 119 | return null; 120 | } 121 | 122 | try { 123 | $this->fileContentsCache = file_get_contents($filePath); 124 | } catch (ErrorException $exception) { 125 | // Internal file paths of PHP extensions cannot be opened 126 | } 127 | } 128 | 129 | return $this->fileContentsCache; 130 | } 131 | 132 | /** 133 | * Adds a comment to this frame, that can be received and 134 | * used by other handlers. For example, the PrettyPage handler 135 | * can attach these comments under the code for each frame. 136 | * 137 | * An interesting use for this would be, for example, code analysis 138 | * & annotations. 139 | * 140 | * @param string $comment 141 | * @param string $context Optional string identifying the origin of the comment 142 | */ 143 | public function addComment($comment, $context = 'global') 144 | { 145 | $this->comments[] = [ 146 | 'comment' => $comment, 147 | 'context' => $context, 148 | ]; 149 | } 150 | 151 | /** 152 | * Returns all comments for this frame. Optionally allows 153 | * a filter to only retrieve comments from a specific 154 | * context. 155 | * 156 | * @param string $filter 157 | * @return array[] 158 | */ 159 | public function getComments($filter = null) 160 | { 161 | $comments = $this->comments; 162 | 163 | if ($filter !== null) { 164 | $comments = array_filter($comments, function ($c) use ($filter) { 165 | return $c['context'] == $filter; 166 | }); 167 | } 168 | 169 | return $comments; 170 | } 171 | 172 | /** 173 | * Returns the array containing the raw frame data from which 174 | * this Frame object was built 175 | * 176 | * @return array 177 | */ 178 | public function getRawFrame() 179 | { 180 | return $this->frame; 181 | } 182 | 183 | /** 184 | * Returns the contents of the file for this frame as an 185 | * array of lines, and optionally as a clamped range of lines. 186 | * 187 | * NOTE: lines are 0-indexed 188 | * 189 | * @example 190 | * Get all lines for this file 191 | * $frame->getFileLines(); // => array( 0 => ' '...', ...) 192 | * @example 193 | * Get one line for this file, starting at line 10 (zero-indexed, remember!) 194 | * $frame->getFileLines(9, 1); // array( 9 => '...' ) 195 | * 196 | * @throws InvalidArgumentException if $length is less than or equal to 0 197 | * @param int $start 198 | * @param int $length 199 | * @return string[]|null 200 | */ 201 | public function getFileLines($start = 0, $length = null) 202 | { 203 | if (null !== ($contents = $this->getFileContents())) { 204 | $lines = explode("\n", $contents); 205 | 206 | // Get a subset of lines from $start to $end 207 | if ($length !== null) { 208 | $start = (int) $start; 209 | $length = (int) $length; 210 | if ($start < 0) { 211 | $start = 0; 212 | } 213 | 214 | if ($length <= 0) { 215 | throw new InvalidArgumentException( 216 | "\$length($length) cannot be lower or equal to 0" 217 | ); 218 | } 219 | 220 | $lines = array_slice($lines, $start, $length, true); 221 | } 222 | 223 | return $lines; 224 | } 225 | } 226 | 227 | /** 228 | * Implements the Serializable interface, with special 229 | * steps to also save the existing comments. 230 | * 231 | * @see Serializable::serialize 232 | * @return string 233 | */ 234 | public function serialize() 235 | { 236 | $frame = $this->frame; 237 | if (!empty($this->comments)) { 238 | $frame['_comments'] = $this->comments; 239 | } 240 | 241 | return serialize($frame); 242 | } 243 | 244 | public function __serialize() 245 | { 246 | $frame = $this->frame; 247 | if (!empty($this->comments)) { 248 | $frame['_comments'] = $this->comments; 249 | } 250 | return $frame; 251 | } 252 | 253 | /** 254 | * Unserializes the frame data, while also preserving 255 | * any existing comment data. 256 | * 257 | * @see Serializable::unserialize 258 | * @param string $serializedFrame 259 | */ 260 | public function unserialize($serializedFrame) 261 | { 262 | $frame = unserialize($serializedFrame); 263 | 264 | if (!empty($frame['_comments'])) { 265 | $this->comments = $frame['_comments']; 266 | unset($frame['_comments']); 267 | } 268 | 269 | $this->frame = $frame; 270 | } 271 | 272 | public function __unserialize($frame) 273 | { 274 | if (!empty($frame['_comments'])) { 275 | $this->comments = $frame['_comments']; 276 | unset($frame['_comments']); 277 | } 278 | 279 | $this->frame = $frame; 280 | } 281 | 282 | /** 283 | * Compares Frame against one another 284 | * @param Frame $frame 285 | * @return bool 286 | */ 287 | public function equals(Frame $frame) 288 | { 289 | if (!$this->getFile() || $this->getFile() === 'Unknown' || !$this->getLine()) { 290 | return false; 291 | } 292 | return $frame->getFile() === $this->getFile() && $frame->getLine() === $this->getLine(); 293 | } 294 | 295 | /** 296 | * Returns whether this frame belongs to the application or not. 297 | * 298 | * @return boolean 299 | */ 300 | public function isApplication() 301 | { 302 | return $this->application; 303 | } 304 | 305 | /** 306 | * Mark as an frame belonging to the application. 307 | * 308 | * @param boolean $application 309 | */ 310 | public function setApplication($application) 311 | { 312 | $this->application = $application; 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /vendor/whoops/Exception/FrameCollection.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Exception; 8 | 9 | use ArrayAccess; 10 | use ArrayIterator; 11 | use Countable; 12 | use IteratorAggregate; 13 | use ReturnTypeWillChange; 14 | use Serializable; 15 | use UnexpectedValueException; 16 | 17 | /** 18 | * Exposes a fluent interface for dealing with an ordered list 19 | * of stack-trace frames. 20 | */ 21 | class FrameCollection implements ArrayAccess, IteratorAggregate, Serializable, Countable 22 | { 23 | /** 24 | * @var array[] 25 | */ 26 | private $frames; 27 | 28 | /** 29 | * @param array $frames 30 | */ 31 | public function __construct(array $frames) 32 | { 33 | $this->frames = array_map(function ($frame) { 34 | return new Frame($frame); 35 | }, $frames); 36 | } 37 | 38 | /** 39 | * Filters frames using a callable, returns the same FrameCollection 40 | * 41 | * @param callable $callable 42 | * @return FrameCollection 43 | */ 44 | public function filter($callable) 45 | { 46 | $this->frames = array_values(array_filter($this->frames, $callable)); 47 | return $this; 48 | } 49 | 50 | /** 51 | * Map the collection of frames 52 | * 53 | * @param callable $callable 54 | * @return FrameCollection 55 | */ 56 | public function map($callable) 57 | { 58 | // Contain the map within a higher-order callable 59 | // that enforces type-correctness for the $callable 60 | $this->frames = array_map(function ($frame) use ($callable) { 61 | $frame = call_user_func($callable, $frame); 62 | 63 | if (!$frame instanceof Frame) { 64 | throw new UnexpectedValueException( 65 | "Callable to " . __CLASS__ . "::map must return a Frame object" 66 | ); 67 | } 68 | 69 | return $frame; 70 | }, $this->frames); 71 | 72 | return $this; 73 | } 74 | 75 | /** 76 | * Returns an array with all frames, does not affect 77 | * the internal array. 78 | * 79 | * @todo If this gets any more complex than this, 80 | * have getIterator use this method. 81 | * @see FrameCollection::getIterator 82 | * @return array 83 | */ 84 | public function getArray() 85 | { 86 | return $this->frames; 87 | } 88 | 89 | /** 90 | * @see IteratorAggregate::getIterator 91 | * @return ArrayIterator 92 | */ 93 | #[ReturnTypeWillChange] 94 | public function getIterator() 95 | { 96 | return new ArrayIterator($this->frames); 97 | } 98 | 99 | /** 100 | * @see ArrayAccess::offsetExists 101 | * @param int $offset 102 | */ 103 | #[ReturnTypeWillChange] 104 | public function offsetExists($offset) 105 | { 106 | return isset($this->frames[$offset]); 107 | } 108 | 109 | /** 110 | * @see ArrayAccess::offsetGet 111 | * @param int $offset 112 | */ 113 | #[ReturnTypeWillChange] 114 | public function offsetGet($offset) 115 | { 116 | return $this->frames[$offset]; 117 | } 118 | 119 | /** 120 | * @see ArrayAccess::offsetSet 121 | * @param int $offset 122 | */ 123 | #[ReturnTypeWillChange] 124 | public function offsetSet($offset, $value) 125 | { 126 | throw new \Exception(__CLASS__ . ' is read only'); 127 | } 128 | 129 | /** 130 | * @see ArrayAccess::offsetUnset 131 | * @param int $offset 132 | */ 133 | #[ReturnTypeWillChange] 134 | public function offsetUnset($offset) 135 | { 136 | throw new \Exception(__CLASS__ . ' is read only'); 137 | } 138 | 139 | /** 140 | * @see Countable::count 141 | * @return int 142 | */ 143 | #[ReturnTypeWillChange] 144 | public function count() 145 | { 146 | return count($this->frames); 147 | } 148 | 149 | /** 150 | * Count the frames that belongs to the application. 151 | * 152 | * @return int 153 | */ 154 | public function countIsApplication() 155 | { 156 | return count(array_filter($this->frames, function (Frame $f) { 157 | return $f->isApplication(); 158 | })); 159 | } 160 | 161 | /** 162 | * @see Serializable::serialize 163 | * @return string 164 | */ 165 | #[ReturnTypeWillChange] 166 | public function serialize() 167 | { 168 | return serialize($this->frames); 169 | } 170 | 171 | /** 172 | * @see Serializable::unserialize 173 | * @param string $serializedFrames 174 | */ 175 | #[ReturnTypeWillChange] 176 | public function unserialize($serializedFrames) 177 | { 178 | $this->frames = unserialize($serializedFrames); 179 | } 180 | 181 | public function __serialize() 182 | { 183 | return $this->frames; 184 | } 185 | 186 | public function __unserialize(array $serializedFrames) 187 | { 188 | $this->frames = $serializedFrames; 189 | } 190 | 191 | /** 192 | * @param Frame[] $frames Array of Frame instances, usually from $e->getPrevious() 193 | */ 194 | public function prependFrames(array $frames) 195 | { 196 | $this->frames = array_merge($frames, $this->frames); 197 | } 198 | 199 | /** 200 | * Gets the innermost part of stack trace that is not the same as that of outer exception 201 | * 202 | * @param FrameCollection $parentFrames Outer exception frames to compare tail against 203 | * @return Frame[] 204 | */ 205 | public function topDiff(FrameCollection $parentFrames) 206 | { 207 | $diff = $this->frames; 208 | 209 | $parentFrames = $parentFrames->getArray(); 210 | $p = count($parentFrames)-1; 211 | 212 | for ($i = count($diff)-1; $i >= 0 && $p >= 0; $i--) { 213 | /** @var Frame $tailFrame */ 214 | $tailFrame = $diff[$i]; 215 | if ($tailFrame->equals($parentFrames[$p])) { 216 | unset($diff[$i]); 217 | } 218 | $p--; 219 | } 220 | return $diff; 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /vendor/whoops/Exception/Inspector.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Exception; 8 | 9 | use Whoops\Util\Misc; 10 | 11 | class Inspector 12 | { 13 | /** 14 | * @var \Throwable 15 | */ 16 | private $exception; 17 | 18 | /** 19 | * @var \Whoops\Exception\FrameCollection 20 | */ 21 | private $frames; 22 | 23 | /** 24 | * @var \Whoops\Exception\Inspector 25 | */ 26 | private $previousExceptionInspector; 27 | 28 | /** 29 | * @var \Throwable[] 30 | */ 31 | private $previousExceptions; 32 | 33 | /** 34 | * @param \Throwable $exception The exception to inspect 35 | */ 36 | public function __construct($exception) 37 | { 38 | $this->exception = $exception; 39 | } 40 | 41 | /** 42 | * @return \Throwable 43 | */ 44 | public function getException() 45 | { 46 | return $this->exception; 47 | } 48 | 49 | /** 50 | * @return string 51 | */ 52 | public function getExceptionName() 53 | { 54 | return get_class($this->exception); 55 | } 56 | 57 | /** 58 | * @return string 59 | */ 60 | public function getExceptionMessage() 61 | { 62 | return $this->extractDocrefUrl($this->exception->getMessage())['message']; 63 | } 64 | 65 | /** 66 | * @return string[] 67 | */ 68 | public function getPreviousExceptionMessages() 69 | { 70 | return array_map(function ($prev) { 71 | /** @var \Throwable $prev */ 72 | return $this->extractDocrefUrl($prev->getMessage())['message']; 73 | }, $this->getPreviousExceptions()); 74 | } 75 | 76 | /** 77 | * @return int[] 78 | */ 79 | public function getPreviousExceptionCodes() 80 | { 81 | return array_map(function ($prev) { 82 | /** @var \Throwable $prev */ 83 | return $prev->getCode(); 84 | }, $this->getPreviousExceptions()); 85 | } 86 | 87 | /** 88 | * Returns a url to the php-manual related to the underlying error - when available. 89 | * 90 | * @return string|null 91 | */ 92 | public function getExceptionDocrefUrl() 93 | { 94 | return $this->extractDocrefUrl($this->exception->getMessage())['url']; 95 | } 96 | 97 | private function extractDocrefUrl($message) 98 | { 99 | $docref = [ 100 | 'message' => $message, 101 | 'url' => null, 102 | ]; 103 | 104 | // php embbeds urls to the manual into the Exception message with the following ini-settings defined 105 | // http://php.net/manual/en/errorfunc.configuration.php#ini.docref-root 106 | if (!ini_get('html_errors') || !ini_get('docref_root')) { 107 | return $docref; 108 | } 109 | 110 | $pattern = "/\[(?:[^<]+)<\/a>\]/"; 111 | if (preg_match($pattern, $message, $matches)) { 112 | // -> strip those automatically generated links from the exception message 113 | $docref['message'] = preg_replace($pattern, '', $message, 1); 114 | $docref['url'] = $matches[1]; 115 | } 116 | 117 | return $docref; 118 | } 119 | 120 | /** 121 | * Does the wrapped Exception has a previous Exception? 122 | * @return bool 123 | */ 124 | public function hasPreviousException() 125 | { 126 | return $this->previousExceptionInspector || $this->exception->getPrevious(); 127 | } 128 | 129 | /** 130 | * Returns an Inspector for a previous Exception, if any. 131 | * @todo Clean this up a bit, cache stuff a bit better. 132 | * @return Inspector 133 | */ 134 | public function getPreviousExceptionInspector() 135 | { 136 | if ($this->previousExceptionInspector === null) { 137 | $previousException = $this->exception->getPrevious(); 138 | 139 | if ($previousException) { 140 | $this->previousExceptionInspector = new Inspector($previousException); 141 | } 142 | } 143 | 144 | return $this->previousExceptionInspector; 145 | } 146 | 147 | 148 | /** 149 | * Returns an array of all previous exceptions for this inspector's exception 150 | * @return \Throwable[] 151 | */ 152 | public function getPreviousExceptions() 153 | { 154 | if ($this->previousExceptions === null) { 155 | $this->previousExceptions = []; 156 | 157 | $prev = $this->exception->getPrevious(); 158 | while ($prev !== null) { 159 | $this->previousExceptions[] = $prev; 160 | $prev = $prev->getPrevious(); 161 | } 162 | } 163 | 164 | return $this->previousExceptions; 165 | } 166 | 167 | /** 168 | * Returns an iterator for the inspected exception's 169 | * frames. 170 | * @return \Whoops\Exception\FrameCollection 171 | */ 172 | public function getFrames() 173 | { 174 | if ($this->frames === null) { 175 | $frames = $this->getTrace($this->exception); 176 | 177 | // Fill empty line/file info for call_user_func_array usages (PHP Bug #44428) 178 | foreach ($frames as $k => $frame) { 179 | if (empty($frame['file'])) { 180 | // Default values when file and line are missing 181 | $file = '[internal]'; 182 | $line = 0; 183 | 184 | $next_frame = !empty($frames[$k + 1]) ? $frames[$k + 1] : []; 185 | 186 | if ($this->isValidNextFrame($next_frame)) { 187 | $file = $next_frame['file']; 188 | $line = $next_frame['line']; 189 | } 190 | 191 | $frames[$k]['file'] = $file; 192 | $frames[$k]['line'] = $line; 193 | } 194 | } 195 | 196 | // Find latest non-error handling frame index ($i) used to remove error handling frames 197 | $i = 0; 198 | foreach ($frames as $k => $frame) { 199 | if ($frame['file'] == $this->exception->getFile() && $frame['line'] == $this->exception->getLine()) { 200 | $i = $k; 201 | } 202 | } 203 | 204 | // Remove error handling frames 205 | if ($i > 0) { 206 | array_splice($frames, 0, $i); 207 | } 208 | 209 | $firstFrame = $this->getFrameFromException($this->exception); 210 | array_unshift($frames, $firstFrame); 211 | 212 | $this->frames = new FrameCollection($frames); 213 | 214 | if ($previousInspector = $this->getPreviousExceptionInspector()) { 215 | // Keep outer frame on top of the inner one 216 | $outerFrames = $this->frames; 217 | $newFrames = clone $previousInspector->getFrames(); 218 | // I assume it will always be set, but let's be safe 219 | if (isset($newFrames[0])) { 220 | $newFrames[0]->addComment( 221 | $previousInspector->getExceptionMessage(), 222 | 'Exception message:' 223 | ); 224 | } 225 | $newFrames->prependFrames($outerFrames->topDiff($newFrames)); 226 | $this->frames = $newFrames; 227 | } 228 | } 229 | 230 | return $this->frames; 231 | } 232 | 233 | /** 234 | * Gets the backtrace from an exception. 235 | * 236 | * If xdebug is installed 237 | * 238 | * @param \Throwable $e 239 | * @return array 240 | */ 241 | protected function getTrace($e) 242 | { 243 | $traces = $e->getTrace(); 244 | 245 | // Get trace from xdebug if enabled, failure exceptions only trace to the shutdown handler by default 246 | if (!$e instanceof \ErrorException) { 247 | return $traces; 248 | } 249 | 250 | if (!Misc::isLevelFatal($e->getSeverity())) { 251 | return $traces; 252 | } 253 | 254 | if (!extension_loaded('xdebug') || !function_exists('xdebug_is_enabled') || !xdebug_is_enabled()) { 255 | return $traces; 256 | } 257 | 258 | // Use xdebug to get the full stack trace and remove the shutdown handler stack trace 259 | $stack = array_reverse(xdebug_get_function_stack()); 260 | $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); 261 | $traces = array_diff_key($stack, $trace); 262 | 263 | return $traces; 264 | } 265 | 266 | /** 267 | * Given an exception, generates an array in the format 268 | * generated by Exception::getTrace() 269 | * @param \Throwable $exception 270 | * @return array 271 | */ 272 | protected function getFrameFromException($exception) 273 | { 274 | return [ 275 | 'file' => $exception->getFile(), 276 | 'line' => $exception->getLine(), 277 | 'class' => get_class($exception), 278 | 'args' => [ 279 | $exception->getMessage(), 280 | ], 281 | ]; 282 | } 283 | 284 | /** 285 | * Given an error, generates an array in the format 286 | * generated by ErrorException 287 | * @param ErrorException $exception 288 | * @return array 289 | */ 290 | protected function getFrameFromError(ErrorException $exception) 291 | { 292 | return [ 293 | 'file' => $exception->getFile(), 294 | 'line' => $exception->getLine(), 295 | 'class' => null, 296 | 'args' => [], 297 | ]; 298 | } 299 | 300 | /** 301 | * Determine if the frame can be used to fill in previous frame's missing info 302 | * happens for call_user_func and call_user_func_array usages (PHP Bug #44428) 303 | * 304 | * @param array $frame 305 | * @return bool 306 | */ 307 | protected function isValidNextFrame(array $frame) 308 | { 309 | if (empty($frame['file'])) { 310 | return false; 311 | } 312 | 313 | if (empty($frame['line'])) { 314 | return false; 315 | } 316 | 317 | if (empty($frame['function']) || !stristr($frame['function'], 'call_user_func')) { 318 | return false; 319 | } 320 | 321 | return true; 322 | } 323 | } 324 | -------------------------------------------------------------------------------- /vendor/whoops/Handler/CallbackHandler.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Handler; 8 | 9 | use InvalidArgumentException; 10 | 11 | /** 12 | * Wrapper for Closures passed as handlers. Can be used 13 | * directly, or will be instantiated automagically by Whoops\Run 14 | * if passed to Run::pushHandler 15 | */ 16 | class CallbackHandler extends Handler 17 | { 18 | /** 19 | * @var callable 20 | */ 21 | protected $callable; 22 | 23 | /** 24 | * @throws InvalidArgumentException If argument is not callable 25 | * @param callable $callable 26 | */ 27 | public function __construct($callable) 28 | { 29 | if (!is_callable($callable)) { 30 | throw new InvalidArgumentException( 31 | 'Argument to ' . __METHOD__ . ' must be valid callable' 32 | ); 33 | } 34 | 35 | $this->callable = $callable; 36 | } 37 | 38 | /** 39 | * @return int|null 40 | */ 41 | public function handle() 42 | { 43 | $exception = $this->getException(); 44 | $inspector = $this->getInspector(); 45 | $run = $this->getRun(); 46 | $callable = $this->callable; 47 | 48 | // invoke the callable directly, to get simpler stacktraces (in comparison to call_user_func). 49 | // this assumes that $callable is a properly typed php-callable, which we check in __construct(). 50 | return $callable($exception, $inspector, $run); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /vendor/whoops/Handler/Handler.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Handler; 8 | 9 | use Whoops\Exception\Inspector; 10 | use Whoops\RunInterface; 11 | 12 | /** 13 | * Abstract implementation of a Handler. 14 | */ 15 | abstract class Handler implements HandlerInterface 16 | { 17 | /* 18 | Return constants that can be returned from Handler::handle 19 | to message the handler walker. 20 | */ 21 | const DONE = 0x10; // returning this is optional, only exists for 22 | // semantic purposes 23 | /** 24 | * The Handler has handled the Throwable in some way, and wishes to skip any other Handler. 25 | * Execution will continue. 26 | */ 27 | const LAST_HANDLER = 0x20; 28 | /** 29 | * The Handler has handled the Throwable in some way, and wishes to quit/stop execution 30 | */ 31 | const QUIT = 0x30; 32 | 33 | /** 34 | * @var RunInterface 35 | */ 36 | private $run; 37 | 38 | /** 39 | * @var Inspector $inspector 40 | */ 41 | private $inspector; 42 | 43 | /** 44 | * @var \Throwable $exception 45 | */ 46 | private $exception; 47 | 48 | /** 49 | * @param RunInterface $run 50 | */ 51 | public function setRun(RunInterface $run) 52 | { 53 | $this->run = $run; 54 | } 55 | 56 | /** 57 | * @return RunInterface 58 | */ 59 | protected function getRun() 60 | { 61 | return $this->run; 62 | } 63 | 64 | /** 65 | * @param Inspector $inspector 66 | */ 67 | public function setInspector(Inspector $inspector) 68 | { 69 | $this->inspector = $inspector; 70 | } 71 | 72 | /** 73 | * @return Inspector 74 | */ 75 | protected function getInspector() 76 | { 77 | return $this->inspector; 78 | } 79 | 80 | /** 81 | * @param \Throwable $exception 82 | */ 83 | public function setException($exception) 84 | { 85 | $this->exception = $exception; 86 | } 87 | 88 | /** 89 | * @return \Throwable 90 | */ 91 | protected function getException() 92 | { 93 | return $this->exception; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /vendor/whoops/Handler/HandlerInterface.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Handler; 8 | 9 | use Whoops\Exception\Inspector; 10 | use Whoops\RunInterface; 11 | 12 | interface HandlerInterface 13 | { 14 | /** 15 | * @return int|null A handler may return nothing, or a Handler::HANDLE_* constant 16 | */ 17 | public function handle(); 18 | 19 | /** 20 | * @param RunInterface $run 21 | * @return void 22 | */ 23 | public function setRun(RunInterface $run); 24 | 25 | /** 26 | * @param \Throwable $exception 27 | * @return void 28 | */ 29 | public function setException($exception); 30 | 31 | /** 32 | * @param Inspector $inspector 33 | * @return void 34 | */ 35 | public function setInspector(Inspector $inspector); 36 | } 37 | -------------------------------------------------------------------------------- /vendor/whoops/Handler/JsonResponseHandler.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Handler; 8 | 9 | use Whoops\Exception\Formatter; 10 | 11 | /** 12 | * Catches an exception and converts it to a JSON 13 | * response. Additionally can also return exception 14 | * frames for consumption by an API. 15 | */ 16 | class JsonResponseHandler extends Handler 17 | { 18 | /** 19 | * @var bool 20 | */ 21 | private $returnFrames = false; 22 | 23 | /** 24 | * @var bool 25 | */ 26 | private $jsonApi = false; 27 | 28 | /** 29 | * Returns errors[[]] instead of error[] to be in compliance with the json:api spec 30 | * @param bool $jsonApi Default is false 31 | * @return static 32 | */ 33 | public function setJsonApi($jsonApi = false) 34 | { 35 | $this->jsonApi = (bool) $jsonApi; 36 | return $this; 37 | } 38 | 39 | /** 40 | * @param bool|null $returnFrames 41 | * @return bool|static 42 | */ 43 | public function addTraceToOutput($returnFrames = null) 44 | { 45 | if (func_num_args() == 0) { 46 | return $this->returnFrames; 47 | } 48 | 49 | $this->returnFrames = (bool) $returnFrames; 50 | return $this; 51 | } 52 | 53 | /** 54 | * @return int 55 | */ 56 | public function handle() 57 | { 58 | if ($this->jsonApi === true) { 59 | $response = [ 60 | 'errors' => [ 61 | Formatter::formatExceptionAsDataArray( 62 | $this->getInspector(), 63 | $this->addTraceToOutput() 64 | ), 65 | ] 66 | ]; 67 | } else { 68 | $response = [ 69 | 'error' => Formatter::formatExceptionAsDataArray( 70 | $this->getInspector(), 71 | $this->addTraceToOutput() 72 | ), 73 | ]; 74 | } 75 | 76 | echo json_encode($response, defined('JSON_PARTIAL_OUTPUT_ON_ERROR') ? JSON_PARTIAL_OUTPUT_ON_ERROR : 0); 77 | 78 | return Handler::QUIT; 79 | } 80 | 81 | /** 82 | * @return string 83 | */ 84 | public function contentType() 85 | { 86 | return 'application/json'; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /vendor/whoops/Handler/PlainTextHandler.php: -------------------------------------------------------------------------------- 1 | 5 | * Plaintext handler for command line and logs. 6 | * @author Pierre-Yves Landuré 7 | */ 8 | 9 | namespace Whoops\Handler; 10 | 11 | use InvalidArgumentException; 12 | use Psr\Log\LoggerInterface; 13 | use Whoops\Exception\Frame; 14 | 15 | /** 16 | * Handler outputing plaintext error messages. Can be used 17 | * directly, or will be instantiated automagically by Whoops\Run 18 | * if passed to Run::pushHandler 19 | */ 20 | class PlainTextHandler extends Handler 21 | { 22 | const VAR_DUMP_PREFIX = ' | '; 23 | 24 | /** 25 | * @var \Psr\Log\LoggerInterface 26 | */ 27 | protected $logger; 28 | 29 | /** 30 | * @var callable 31 | */ 32 | protected $dumper; 33 | 34 | /** 35 | * @var bool 36 | */ 37 | private $addTraceToOutput = true; 38 | 39 | /** 40 | * @var bool|integer 41 | */ 42 | private $addTraceFunctionArgsToOutput = false; 43 | 44 | /** 45 | * @var integer 46 | */ 47 | private $traceFunctionArgsOutputLimit = 1024; 48 | 49 | /** 50 | * @var bool 51 | */ 52 | private $addPreviousToOutput = true; 53 | 54 | /** 55 | * @var bool 56 | */ 57 | private $loggerOnly = false; 58 | 59 | /** 60 | * Constructor. 61 | * @throws InvalidArgumentException If argument is not null or a LoggerInterface 62 | * @param \Psr\Log\LoggerInterface|null $logger 63 | */ 64 | public function __construct($logger = null) 65 | { 66 | $this->setLogger($logger); 67 | } 68 | 69 | /** 70 | * Set the output logger interface. 71 | * @throws InvalidArgumentException If argument is not null or a LoggerInterface 72 | * @param \Psr\Log\LoggerInterface|null $logger 73 | */ 74 | public function setLogger($logger = null) 75 | { 76 | if (! (is_null($logger) 77 | || $logger instanceof LoggerInterface)) { 78 | throw new InvalidArgumentException( 79 | 'Argument to ' . __METHOD__ . 80 | " must be a valid Logger Interface (aka. Monolog), " . 81 | get_class($logger) . ' given.' 82 | ); 83 | } 84 | 85 | $this->logger = $logger; 86 | } 87 | 88 | /** 89 | * @return \Psr\Log\LoggerInterface|null 90 | */ 91 | public function getLogger() 92 | { 93 | return $this->logger; 94 | } 95 | 96 | /** 97 | * Set var dumper callback function. 98 | * 99 | * @param callable $dumper 100 | * @return static 101 | */ 102 | public function setDumper(callable $dumper) 103 | { 104 | $this->dumper = $dumper; 105 | return $this; 106 | } 107 | 108 | /** 109 | * Add error trace to output. 110 | * @param bool|null $addTraceToOutput 111 | * @return bool|static 112 | */ 113 | public function addTraceToOutput($addTraceToOutput = null) 114 | { 115 | if (func_num_args() == 0) { 116 | return $this->addTraceToOutput; 117 | } 118 | 119 | $this->addTraceToOutput = (bool) $addTraceToOutput; 120 | return $this; 121 | } 122 | 123 | /** 124 | * Add previous exceptions to output. 125 | * @param bool|null $addPreviousToOutput 126 | * @return bool|static 127 | */ 128 | public function addPreviousToOutput($addPreviousToOutput = null) 129 | { 130 | if (func_num_args() == 0) { 131 | return $this->addPreviousToOutput; 132 | } 133 | 134 | $this->addPreviousToOutput = (bool) $addPreviousToOutput; 135 | return $this; 136 | } 137 | 138 | /** 139 | * Add error trace function arguments to output. 140 | * Set to True for all frame args, or integer for the n first frame args. 141 | * @param bool|integer|null $addTraceFunctionArgsToOutput 142 | * @return static|bool|integer 143 | */ 144 | public function addTraceFunctionArgsToOutput($addTraceFunctionArgsToOutput = null) 145 | { 146 | if (func_num_args() == 0) { 147 | return $this->addTraceFunctionArgsToOutput; 148 | } 149 | 150 | if (! is_integer($addTraceFunctionArgsToOutput)) { 151 | $this->addTraceFunctionArgsToOutput = (bool) $addTraceFunctionArgsToOutput; 152 | } else { 153 | $this->addTraceFunctionArgsToOutput = $addTraceFunctionArgsToOutput; 154 | } 155 | return $this; 156 | } 157 | 158 | /** 159 | * Set the size limit in bytes of frame arguments var_dump output. 160 | * If the limit is reached, the var_dump output is discarded. 161 | * Prevent memory limit errors. 162 | * @var integer 163 | * @return static 164 | */ 165 | public function setTraceFunctionArgsOutputLimit($traceFunctionArgsOutputLimit) 166 | { 167 | $this->traceFunctionArgsOutputLimit = (integer) $traceFunctionArgsOutputLimit; 168 | return $this; 169 | } 170 | 171 | /** 172 | * Create plain text response and return it as a string 173 | * @return string 174 | */ 175 | public function generateResponse() 176 | { 177 | $exception = $this->getException(); 178 | $message = $this->getExceptionOutput($exception); 179 | 180 | if ($this->addPreviousToOutput) { 181 | $previous = $exception->getPrevious(); 182 | while ($previous) { 183 | $message .= "\n\nCaused by\n" . $this->getExceptionOutput($previous); 184 | $previous = $previous->getPrevious(); 185 | } 186 | } 187 | 188 | 189 | return $message . $this->getTraceOutput() . "\n"; 190 | } 191 | 192 | /** 193 | * Get the size limit in bytes of frame arguments var_dump output. 194 | * If the limit is reached, the var_dump output is discarded. 195 | * Prevent memory limit errors. 196 | * @return integer 197 | */ 198 | public function getTraceFunctionArgsOutputLimit() 199 | { 200 | return $this->traceFunctionArgsOutputLimit; 201 | } 202 | 203 | /** 204 | * Only output to logger. 205 | * @param bool|null $loggerOnly 206 | * @return static|bool 207 | */ 208 | public function loggerOnly($loggerOnly = null) 209 | { 210 | if (func_num_args() == 0) { 211 | return $this->loggerOnly; 212 | } 213 | 214 | $this->loggerOnly = (bool) $loggerOnly; 215 | return $this; 216 | } 217 | 218 | /** 219 | * Test if handler can output to stdout. 220 | * @return bool 221 | */ 222 | private function canOutput() 223 | { 224 | return !$this->loggerOnly(); 225 | } 226 | 227 | /** 228 | * Get the frame args var_dump. 229 | * @param \Whoops\Exception\Frame $frame [description] 230 | * @param integer $line [description] 231 | * @return string 232 | */ 233 | private function getFrameArgsOutput(Frame $frame, $line) 234 | { 235 | if ($this->addTraceFunctionArgsToOutput() === false 236 | || $this->addTraceFunctionArgsToOutput() < $line) { 237 | return ''; 238 | } 239 | 240 | // Dump the arguments: 241 | ob_start(); 242 | $this->dump($frame->getArgs()); 243 | if (ob_get_length() > $this->getTraceFunctionArgsOutputLimit()) { 244 | // The argument var_dump is to big. 245 | // Discarded to limit memory usage. 246 | ob_clean(); 247 | return sprintf( 248 | "\n%sArguments dump length greater than %d Bytes. Discarded.", 249 | self::VAR_DUMP_PREFIX, 250 | $this->getTraceFunctionArgsOutputLimit() 251 | ); 252 | } 253 | 254 | return sprintf( 255 | "\n%s", 256 | preg_replace('/^/m', self::VAR_DUMP_PREFIX, ob_get_clean()) 257 | ); 258 | } 259 | 260 | /** 261 | * Dump variable. 262 | * 263 | * @param mixed $var 264 | * @return void 265 | */ 266 | protected function dump($var) 267 | { 268 | if ($this->dumper) { 269 | call_user_func($this->dumper, $var); 270 | } else { 271 | var_dump($var); 272 | } 273 | } 274 | 275 | /** 276 | * Get the exception trace as plain text. 277 | * @return string 278 | */ 279 | private function getTraceOutput() 280 | { 281 | if (! $this->addTraceToOutput()) { 282 | return ''; 283 | } 284 | $inspector = $this->getInspector(); 285 | $frames = $inspector->getFrames(); 286 | 287 | $response = "\nStack trace:"; 288 | 289 | $line = 1; 290 | foreach ($frames as $frame) { 291 | /** @var Frame $frame */ 292 | $class = $frame->getClass(); 293 | 294 | $template = "\n%3d. %s->%s() %s:%d%s"; 295 | if (! $class) { 296 | // Remove method arrow (->) from output. 297 | $template = "\n%3d. %s%s() %s:%d%s"; 298 | } 299 | 300 | $response .= sprintf( 301 | $template, 302 | $line, 303 | $class, 304 | $frame->getFunction(), 305 | $frame->getFile(), 306 | $frame->getLine(), 307 | $this->getFrameArgsOutput($frame, $line) 308 | ); 309 | 310 | $line++; 311 | } 312 | 313 | return $response; 314 | } 315 | 316 | /** 317 | * Get the exception as plain text. 318 | * @param \Throwable $exception 319 | * @return string 320 | */ 321 | private function getExceptionOutput($exception) 322 | { 323 | return sprintf( 324 | "%s: %s in file %s on line %d", 325 | get_class($exception), 326 | $exception->getMessage(), 327 | $exception->getFile(), 328 | $exception->getLine() 329 | ); 330 | } 331 | 332 | /** 333 | * @return int 334 | */ 335 | public function handle() 336 | { 337 | $response = $this->generateResponse(); 338 | 339 | if ($this->getLogger()) { 340 | $this->getLogger()->error($response); 341 | } 342 | 343 | if (! $this->canOutput()) { 344 | return Handler::DONE; 345 | } 346 | 347 | echo $response; 348 | 349 | return Handler::QUIT; 350 | } 351 | 352 | /** 353 | * @return string 354 | */ 355 | public function contentType() 356 | { 357 | return 'text/plain'; 358 | } 359 | } 360 | -------------------------------------------------------------------------------- /vendor/whoops/Handler/XmlResponseHandler.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Handler; 8 | 9 | use SimpleXMLElement; 10 | use Whoops\Exception\Formatter; 11 | 12 | /** 13 | * Catches an exception and converts it to an XML 14 | * response. Additionally can also return exception 15 | * frames for consumption by an API. 16 | */ 17 | class XmlResponseHandler extends Handler 18 | { 19 | /** 20 | * @var bool 21 | */ 22 | private $returnFrames = false; 23 | 24 | /** 25 | * @param bool|null $returnFrames 26 | * @return bool|static 27 | */ 28 | public function addTraceToOutput($returnFrames = null) 29 | { 30 | if (func_num_args() == 0) { 31 | return $this->returnFrames; 32 | } 33 | 34 | $this->returnFrames = (bool) $returnFrames; 35 | return $this; 36 | } 37 | 38 | /** 39 | * @return int 40 | */ 41 | public function handle() 42 | { 43 | $response = [ 44 | 'error' => Formatter::formatExceptionAsDataArray( 45 | $this->getInspector(), 46 | $this->addTraceToOutput() 47 | ), 48 | ]; 49 | 50 | echo self::toXml($response); 51 | 52 | return Handler::QUIT; 53 | } 54 | 55 | /** 56 | * @return string 57 | */ 58 | public function contentType() 59 | { 60 | return 'application/xml'; 61 | } 62 | 63 | /** 64 | * @param SimpleXMLElement $node Node to append data to, will be modified in place 65 | * @param array|\Traversable $data 66 | * @return SimpleXMLElement The modified node, for chaining 67 | */ 68 | private static function addDataToNode(\SimpleXMLElement $node, $data) 69 | { 70 | assert(is_array($data) || $data instanceof Traversable); 71 | 72 | foreach ($data as $key => $value) { 73 | if (is_numeric($key)) { 74 | // Convert the key to a valid string 75 | $key = "unknownNode_". (string) $key; 76 | } 77 | 78 | // Delete any char not allowed in XML element names 79 | $key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key); 80 | 81 | if (is_array($value)) { 82 | $child = $node->addChild($key); 83 | self::addDataToNode($child, $value); 84 | } else { 85 | $value = str_replace('&', '&', print_r($value, true)); 86 | $node->addChild($key, $value); 87 | } 88 | } 89 | 90 | return $node; 91 | } 92 | 93 | /** 94 | * The main function for converting to an XML document. 95 | * 96 | * @param array|\Traversable $data 97 | * @return string XML 98 | */ 99 | private static function toXml($data) 100 | { 101 | assert(is_array($data) || $data instanceof Traversable); 102 | 103 | $node = simplexml_load_string(""); 104 | 105 | return self::addDataToNode($node, $data)->asXML(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /vendor/whoops/Resources/css/prism.css: -------------------------------------------------------------------------------- 1 | /* PrismJS 1.29.0 2 | https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+markup-templating+php&plugins=line-highlight+line-numbers */ 3 | /*code[class*=language-],pre[class*=language-]{color:#ccc;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}*/ 4 | code[class*=language-],pre[class*=language-]{background:#272b33;color:#aab1bf;text-shadow:0 1px rgba(0,0,0,.3);font-family:"Fira Code","Fira Mono",Menlo,Consolas,"DejaVu Sans Mono",monospace;direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;line-height:1.5;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection{background:#3e4450;color:inherit;text-shadow:none}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection{background:#3e4450;color:inherit;text-shadow:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-]{padding:.2em .3em;border-radius:.3em;white-space:normal}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}.token.cdata,.token.comment,.token.prolog{color:#5b6270}.token.doctype,.token.entity,.token.punctuation{color:#aab1bf}.token.atrule,.token.attr-name,.token.boolean,.token.class-name,.token.constant,.token.number{color:#d19965}.token.keyword{color:#c578dd}.token.deleted,.token.important,.token.property,.token.symbol,.token.tag{color:#df6b75}.token.attr-value,.token.attr-value>.token.punctuation,.token.builtin,.token.char,.token.inserted,.token.regex,.token.selector,.token.string{color:#97c279}.token.function,.token.operator,.token.variable{color:#61afef}.token.url{color:#56b5c2}.token.attr-value>.token.punctuation.attr-equals,.token.special-attr>.token.attr-value>.token.value.css{color:#aab1bf}.language-css .token.selector{color:#df6b75}.language-css .token.property{color:#aab1bf}.language-css .token.function,.language-css .token.url>.token.function{color:#56b5c2}.language-css .token.url>.token.string.url{color:#97c279}.language-css .token.atrule .token.rule,.language-css .token.important{color:#c578dd}.language-javascript .token.operator{color:#c578dd}.language-javascript .token.template-string>.token.interpolation>.token.interpolation-punctuation.punctuation{color:#be5046}.language-json .token.operator{color:#aab1bf}.language-json .token.null.keyword{color:#d19965}.language-markdown .token.url,.language-markdown .token.url-reference.url>.token.string,.language-markdown .token.url>.token.operator{color:#aab1bf}.language-markdown .token.url>.token.content{color:#61afef}.language-markdown .token.url-reference.url,.language-markdown .token.url>.token.url{color:#56b5c2}.language-markdown .token.blockquote.punctuation,.language-markdown .token.hr.punctuation{color:#5b6270;font-style:italic}.language-markdown .token.code-snippet{color:#97c279}.language-markdown .token.bold .token.content{color:#d19965}.language-markdown .token.italic .token.content{color:#c578dd}.language-markdown .token.list.punctuation,.language-markdown .token.strike .token.content,.language-markdown .token.strike .token.punctuation,.language-markdown .token.title.important>.token.punctuation{color:#df6b75}.token.bold{font-weight:700}.token.comment,.token.italic{font-style:italic}.token.entity{cursor:help}.token.namespace{opacity:.8}.token.token.cr:before,.token.token.lf:before,.token.token.space:before,.token.token.tab:not(:empty):before{color:hsla(220,14%,71%,.15);text-shadow:none}div.code-toolbar>.toolbar.toolbar>.toolbar-item{margin-right:.4em}div.code-toolbar>.toolbar.toolbar>.toolbar-item>a,div.code-toolbar>.toolbar.toolbar>.toolbar-item>button,div.code-toolbar>.toolbar.toolbar>.toolbar-item>span{background:#393f4a;color:#818896;padding:.1em .4em;border-radius:.3em}div.code-toolbar>.toolbar.toolbar>.toolbar-item>a:focus,div.code-toolbar>.toolbar.toolbar>.toolbar-item>a:hover,div.code-toolbar>.toolbar.toolbar>.toolbar-item>button:focus,div.code-toolbar>.toolbar.toolbar>.toolbar-item>button:hover,div.code-toolbar>.toolbar.toolbar>.toolbar-item>span:focus,div.code-toolbar>.toolbar.toolbar>.toolbar-item>span:hover{background:#3e4450;color:#aab1bf}.line-highlight.line-highlight{background:hsla(220,100%,80%,.04)}.line-highlight.line-highlight:before,.line-highlight.line-highlight[data-end]:after{background:#393f4a;color:#aab1bf;padding:.1em .6em;border-radius:.3em;box-shadow:0 2px 0 0 rgba(0,0,0,.2)}pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows>span:hover:before{background-color:hsla(220,100%,80%,.04)}.command-line .command-line-prompt,.line-numbers.line-numbers .line-numbers-rows{border-right-color:hsla(220,14%,71%,.15)}.command-line .command-line-prompt>span:before,.line-numbers .line-numbers-rows>span:before{color:#626d82}.rainbow-braces .token.token.punctuation.brace-level-1,.rainbow-braces .token.token.punctuation.brace-level-5,.rainbow-braces .token.token.punctuation.brace-level-9{color:#df6b75}.rainbow-braces .token.token.punctuation.brace-level-10,.rainbow-braces .token.token.punctuation.brace-level-2,.rainbow-braces .token.token.punctuation.brace-level-6{color:#97c279}.rainbow-braces .token.token.punctuation.brace-level-11,.rainbow-braces .token.token.punctuation.brace-level-3,.rainbow-braces .token.token.punctuation.brace-level-7{color:#61afef}.rainbow-braces .token.token.punctuation.brace-level-12,.rainbow-braces .token.token.punctuation.brace-level-4,.rainbow-braces .token.token.punctuation.brace-level-8{color:#c578dd}pre.diff-highlight>code .token.token.deleted:not(.prefix),pre>code.diff-highlight .token.token.deleted:not(.prefix){background-color:hsla(353,100%,66%,.15)}pre.diff-highlight>code .token.token.deleted:not(.prefix) ::-moz-selection,pre.diff-highlight>code .token.token.deleted:not(.prefix)::-moz-selection,pre>code.diff-highlight .token.token.deleted:not(.prefix) ::-moz-selection,pre>code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection{background-color:hsla(353,95%,66%,.25)}pre.diff-highlight>code .token.token.deleted:not(.prefix) ::selection,pre.diff-highlight>code .token.token.deleted:not(.prefix)::selection,pre>code.diff-highlight .token.token.deleted:not(.prefix) ::selection,pre>code.diff-highlight .token.token.deleted:not(.prefix)::selection{background-color:hsla(353,95%,66%,.25)}pre.diff-highlight>code .token.token.inserted:not(.prefix),pre>code.diff-highlight .token.token.inserted:not(.prefix){background-color:hsla(137,100%,55%,.15)}pre.diff-highlight>code .token.token.inserted:not(.prefix) ::-moz-selection,pre.diff-highlight>code .token.token.inserted:not(.prefix)::-moz-selection,pre>code.diff-highlight .token.token.inserted:not(.prefix) ::-moz-selection,pre>code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection{background-color:hsla(135,73%,55%,.25)}pre.diff-highlight>code .token.token.inserted:not(.prefix) ::selection,pre.diff-highlight>code .token.token.inserted:not(.prefix)::selection,pre>code.diff-highlight .token.token.inserted:not(.prefix) ::selection,pre>code.diff-highlight .token.token.inserted:not(.prefix)::selection{background-color:hsla(135,73%,55%,.25)}.prism-previewer-gradient.prism-previewer-gradient div,.prism-previewer.prism-previewer:before{border-color:#252830}.prism-previewer-color.prism-previewer-color:before,.prism-previewer-easing.prism-previewer-easing:before,.prism-previewer-gradient.prism-previewer-gradient div{border-radius:.3em}.prism-previewer.prism-previewer:after{border-top-color:#252830}.prism-previewer-flipped.prism-previewer-flipped.after{border-bottom-color:#252830}.prism-previewer-angle.prism-previewer-angle:before,.prism-previewer-easing.prism-previewer-easing,.prism-previewer-time.prism-previewer-time:before{background:#30353f}.prism-previewer-angle.prism-previewer-angle circle,.prism-previewer-time.prism-previewer-time circle{stroke:#aab1bf;stroke-opacity:1}.prism-previewer-easing.prism-previewer-easing circle,.prism-previewer-easing.prism-previewer-easing line,.prism-previewer-easing.prism-previewer-easing path{stroke:#aab1bf}.prism-previewer-easing.prism-previewer-easing circle{fill:transparent} 5 | pre[data-line]{position:relative;padding:1em 0 1em 3em}.line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:hsla(24,20%,50%,.08);background:linear-gradient(to right,hsla(24,20%,50%,.1) 70%,hsla(24,20%,50%,0));pointer-events:none;line-height:inherit;white-space:pre}@media print{.line-highlight{-webkit-print-color-adjust:exact;color-adjust:exact}}.line-highlight:before,.line-highlight[data-end]:after{content:attr(data-start);position:absolute;top:.4em;left:.6em;min-width:1em;padding:0 .5em;background-color:hsla(24,20%,50%,.4);color:#f4f1ef;font:bold 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}.line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}.line-numbers .line-highlight:after,.line-numbers .line-highlight:before{content:none}pre[id].linkable-line-numbers span.line-numbers-rows{pointer-events:all}pre[id].linkable-line-numbers span.line-numbers-rows>span:before{cursor:pointer}pre[id].linkable-line-numbers span.line-numbers-rows>span:hover:before{background-color:rgba(128,128,128,.2)} 6 | pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right} 7 | -------------------------------------------------------------------------------- /vendor/whoops/Resources/css/whoops.base.css: -------------------------------------------------------------------------------- 1 | body { 2 | font: 12px "Helvetica Neue", helvetica, arial, sans-serif; 3 | color: #131313; 4 | background: #F7F8FA; 5 | padding:0; 6 | margin: 0; 7 | max-height: 100%; 8 | 9 | text-rendering: optimizeLegibility; 10 | } 11 | a { 12 | text-decoration: none; 13 | } 14 | 15 | .Whoops.container { 16 | position: relative; 17 | z-index: 9999999999; 18 | } 19 | 20 | .panel { 21 | overflow-y: scroll; 22 | height: 100%; 23 | position: fixed; 24 | margin: 0; 25 | left: 0; 26 | top: 0; 27 | } 28 | 29 | .branding { 30 | position: absolute; 31 | top: 10px; 32 | right: 20px; 33 | color: #777777; 34 | font-size: 10px; 35 | z-index: 100; 36 | } 37 | .branding a { 38 | color: #e95353; 39 | } 40 | 41 | header { 42 | color: white; 43 | box-sizing: border-box; 44 | background-color:#282c34; 45 | padding: 40px 40px; 46 | max-height: 180px; 47 | overflow: hidden; 48 | transition: 0.5s; 49 | } 50 | 51 | header.header-expand { 52 | max-height: 1000px; 53 | } 54 | 55 | .exc-title { 56 | margin: 0; 57 | color: #bebebe; 58 | font-size: 14px; 59 | } 60 | .exc-title-primary, .exc-title-secondary { 61 | color: #e95353; 62 | } 63 | 64 | .exc-message { 65 | font-size: 20px; 66 | word-wrap: break-word; 67 | margin: 4px 0 0 0; 68 | color: white; 69 | } 70 | .exc-message span { 71 | display: block; 72 | } 73 | .exc-message-empty-notice { 74 | color: #a29d9d; 75 | font-weight: 300; 76 | } 77 | 78 | .prev-exc-title { 79 | margin: 10px 0; 80 | } 81 | 82 | .prev-exc-title + ul { 83 | margin: 0; 84 | padding: 0 0 0 20px; 85 | line-height: 12px; 86 | } 87 | 88 | .prev-exc-title + ul li { 89 | font: 12px "Helvetica Neue", helvetica, arial, sans-serif; 90 | } 91 | 92 | .prev-exc-title + ul li .prev-exc-code { 93 | display: inline-block; 94 | color: #bebebe; 95 | } 96 | 97 | .details-container { 98 | left: 30%; 99 | width: 70%; 100 | background: #fafafa; 101 | } 102 | .details { 103 | padding: 5px; 104 | } 105 | 106 | .details-heading { 107 | color: #4288CE; 108 | font-weight: 300; 109 | padding-bottom: 10px; 110 | margin-bottom: 10px; 111 | border-bottom: 1px solid rgba(0, 0, 0, .1); 112 | } 113 | 114 | .details pre.sf-dump { 115 | white-space: pre; 116 | word-wrap: inherit; 117 | } 118 | 119 | .details pre.sf-dump, 120 | .details pre.sf-dump .sf-dump-num, 121 | .details pre.sf-dump .sf-dump-const, 122 | .details pre.sf-dump .sf-dump-str, 123 | .details pre.sf-dump .sf-dump-note, 124 | .details pre.sf-dump .sf-dump-ref, 125 | .details pre.sf-dump .sf-dump-public, 126 | .details pre.sf-dump .sf-dump-protected, 127 | .details pre.sf-dump .sf-dump-private, 128 | .details pre.sf-dump .sf-dump-meta, 129 | .details pre.sf-dump .sf-dump-key, 130 | .details pre.sf-dump .sf-dump-index { 131 | color: #463C54; 132 | } 133 | 134 | .left-panel { 135 | width: 30%; 136 | background: #ded8d8; 137 | } 138 | 139 | .frames-description { 140 | /*background: rgba(0, 0, 0, .05);*/ 141 | padding: 9px 15px; 142 | color: #a29d9d; 143 | font-size: 13px; 144 | } 145 | 146 | .frames-description.frames-description-application { 147 | text-align: center; 148 | font-size: 12px; 149 | } 150 | .frames-container.frames-container-application .frame:not(.frame-application) { 151 | display: none; 152 | } 153 | 154 | .frames-tab { 155 | color: #a29d9d; 156 | display: inline-block; 157 | padding: 4px 8px; 158 | margin: 0 2px; 159 | border-radius: 3px; 160 | } 161 | 162 | .frames-tab.frames-tab-active { 163 | background-color: #2a2a2a; 164 | color: #bebebe; 165 | } 166 | 167 | .frame { 168 | padding: 14px; 169 | cursor: pointer; 170 | transition: all 0.1s ease; 171 | background: #eeeeee; 172 | } 173 | .frame:not(:last-child) { 174 | border-bottom: 1px solid rgba(0, 0, 0, .05); 175 | } 176 | 177 | .frame.active { 178 | box-shadow: inset -5px 0 0 0 #4288CE; 179 | color: #4288CE; 180 | } 181 | 182 | .frame:not(.active):hover { 183 | background: #BEE9EA; 184 | } 185 | 186 | .frame-method-info { 187 | margin-bottom: 10px; 188 | } 189 | 190 | .frame-class, .frame-function, .frame-index { 191 | font-size: 14px; 192 | } 193 | 194 | .frame-index { 195 | float: left; 196 | } 197 | 198 | .frame-method-info { 199 | margin-left: 24px; 200 | } 201 | 202 | .frame-index { 203 | font-size: 11px; 204 | color: #a29d9d; 205 | background-color: rgba(0, 0, 0, .05); 206 | height: 18px; 207 | width: 18px; 208 | line-height: 18px; 209 | border-radius: 5px; 210 | padding: 0 1px 0 1px; 211 | text-align: center; 212 | display: inline-block; 213 | } 214 | 215 | .frame-application .frame-index { 216 | background-color: #2a2a2a; 217 | color: #bebebe; 218 | } 219 | 220 | .frame-file { 221 | font-family: "Inconsolata", "Fira Mono", "Source Code Pro", Monaco, Consolas, "Lucida Console", monospace; 222 | color: #a29d9d; 223 | } 224 | 225 | .frame-file .editor-link { 226 | color: #a29d9d; 227 | } 228 | 229 | .frame-line { 230 | font-weight: bold; 231 | } 232 | 233 | .frame-line:before { 234 | content: ":"; 235 | } 236 | 237 | .frame-code { 238 | padding: 5px; 239 | background: #282c34; 240 | display: none; 241 | } 242 | 243 | .frame-code.active { 244 | display: block; 245 | } 246 | 247 | .frame-code .frame-file { 248 | color: #a29d9d; 249 | padding: 12px 6px; 250 | 251 | border-bottom: none; 252 | } 253 | 254 | .code-block { 255 | padding: 10px; 256 | margin: 0; 257 | border-radius: 6px; 258 | box-shadow: 0 3px 0 rgba(0, 0, 0, .05), 259 | 0 10px 30px rgba(0, 0, 0, .05), 260 | inset 0 0 1px 0 rgba(255, 255, 255, .07); 261 | -moz-tab-size: 4; 262 | -o-tab-size: 4; 263 | tab-size: 4; 264 | } 265 | 266 | .linenums { 267 | margin: 0; 268 | margin-left: 10px; 269 | } 270 | 271 | .frame-comments { 272 | border-top: none; 273 | margin-top: 15px; 274 | 275 | font-size: 12px; 276 | } 277 | 278 | .frame-comments.empty { 279 | } 280 | 281 | .frame-comments.empty:before { 282 | content: "No comments for this stack frame."; 283 | font-weight: 300; 284 | color: #a29d9d; 285 | } 286 | 287 | .frame-comment { 288 | padding: 10px; 289 | color: #e3e3e3; 290 | border-radius: 6px; 291 | background-color: rgba(255, 255, 255, .05); 292 | } 293 | .frame-comment a { 294 | font-weight: bold; 295 | text-decoration: none; 296 | } 297 | .frame-comment a:hover { 298 | color: #4bb1b1; 299 | } 300 | 301 | .frame-comment:not(:last-child) { 302 | border-bottom: 1px dotted rgba(0, 0, 0, .3); 303 | } 304 | 305 | .frame-comment-context { 306 | font-size: 10px; 307 | color: white; 308 | } 309 | 310 | .delimiter { 311 | display: inline-block; 312 | } 313 | 314 | .data-table-container label { 315 | font-size: 16px; 316 | color: #303030; 317 | font-weight: bold; 318 | margin: 10px 0; 319 | 320 | display: block; 321 | 322 | margin-bottom: 5px; 323 | padding-bottom: 5px; 324 | } 325 | .data-table { 326 | width: 100%; 327 | margin-bottom: 10px; 328 | } 329 | 330 | .data-table tbody { 331 | font: 13px "Inconsolata", "Fira Mono", "Source Code Pro", Monaco, Consolas, "Lucida Console", monospace; 332 | } 333 | 334 | .data-table thead { 335 | display: none; 336 | } 337 | 338 | .data-table tr { 339 | padding: 5px 0; 340 | } 341 | 342 | .data-table td:first-child { 343 | width: 20%; 344 | min-width: 130px; 345 | overflow: hidden; 346 | font-weight: bold; 347 | color: #463C54; 348 | padding-right: 5px; 349 | 350 | } 351 | 352 | .data-table td:last-child { 353 | width: 80%; 354 | -ms-word-break: break-all; 355 | word-break: break-all; 356 | word-break: break-word; 357 | -webkit-hyphens: auto; 358 | -moz-hyphens: auto; 359 | hyphens: auto; 360 | } 361 | 362 | .data-table span.empty { 363 | color: rgba(0, 0, 0, .3); 364 | font-weight: 300; 365 | } 366 | .data-table label.empty { 367 | display: inline; 368 | } 369 | 370 | .handler { 371 | padding: 4px 0; 372 | font: 14px "Inconsolata", "Fira Mono", "Source Code Pro", Monaco, Consolas, "Lucida Console", monospace; 373 | } 374 | 375 | #plain-exception { 376 | display: none; 377 | } 378 | 379 | .rightButton { 380 | cursor: pointer; 381 | border: 0; 382 | opacity: .8; 383 | background: none; 384 | 385 | color: rgba(255, 255, 255, 0.1); 386 | box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.1); 387 | 388 | border-radius: 3px; 389 | 390 | outline: none !important; 391 | } 392 | 393 | .rightButton:hover { 394 | box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.3); 395 | color: rgba(255, 255, 255, 0.3); 396 | } 397 | 398 | /* inspired by githubs kbd styles */ 399 | kbd { 400 | -moz-border-bottom-colors: none; 401 | -moz-border-left-colors: none; 402 | -moz-border-right-colors: none; 403 | -moz-border-top-colors: none; 404 | background-color: #fcfcfc; 405 | border-color: #ccc #ccc #bbb; 406 | border-image: none; 407 | border-style: solid; 408 | border-width: 1px; 409 | color: #555; 410 | display: inline-block; 411 | font-size: 11px; 412 | line-height: 10px; 413 | padding: 3px 5px; 414 | vertical-align: middle; 415 | } 416 | 417 | 418 | /* == Media queries */ 419 | 420 | /* Expand the spacing in the details section */ 421 | @media (min-width: 1000px) { 422 | .details, .frame-code { 423 | padding: 20px 40px; 424 | } 425 | 426 | .details-container { 427 | left: 32%; 428 | width: 68%; 429 | } 430 | 431 | .frames-container { 432 | margin: 5px; 433 | } 434 | 435 | .left-panel { 436 | width: 32%; 437 | } 438 | } 439 | 440 | /* Stack panels */ 441 | @media (max-width: 600px) { 442 | .panel { 443 | position: static; 444 | width: 100%; 445 | } 446 | } 447 | 448 | /* Stack details tables */ 449 | @media (max-width: 400px) { 450 | .data-table, 451 | .data-table tbody, 452 | .data-table tbody tr, 453 | .data-table tbody td { 454 | display: block; 455 | width: 100%; 456 | } 457 | 458 | .data-table tbody tr:first-child { 459 | padding-top: 0; 460 | } 461 | 462 | .data-table tbody td:first-child, 463 | .data-table tbody td:last-child { 464 | padding-left: 0; 465 | padding-right: 0; 466 | } 467 | 468 | .data-table tbody td:last-child { 469 | padding-top: 3px; 470 | } 471 | } 472 | 473 | .tooltipped { 474 | position: relative 475 | } 476 | .tooltipped:after { 477 | position: absolute; 478 | z-index: 1000000; 479 | display: none; 480 | padding: 5px 8px; 481 | color: #fff; 482 | text-align: center; 483 | text-decoration: none; 484 | text-shadow: none; 485 | text-transform: none; 486 | letter-spacing: normal; 487 | word-wrap: break-word; 488 | white-space: pre; 489 | pointer-events: none; 490 | content: attr(aria-label); 491 | background: rgba(0, 0, 0, 0.8); 492 | border-radius: 3px; 493 | -webkit-font-smoothing: subpixel-antialiased 494 | } 495 | .tooltipped:before { 496 | position: absolute; 497 | z-index: 1000001; 498 | display: none; 499 | width: 0; 500 | height: 0; 501 | color: rgba(0, 0, 0, 0.8); 502 | pointer-events: none; 503 | content: ""; 504 | border: 5px solid transparent 505 | } 506 | .tooltipped:hover:before, 507 | .tooltipped:hover:after, 508 | .tooltipped:active:before, 509 | .tooltipped:active:after, 510 | .tooltipped:focus:before, 511 | .tooltipped:focus:after { 512 | display: inline-block; 513 | text-decoration: none 514 | } 515 | .tooltipped-s:after { 516 | top: 100%; 517 | right: 50%; 518 | margin-top: 5px 519 | } 520 | .tooltipped-s:before { 521 | top: auto; 522 | right: 50%; 523 | bottom: -5px; 524 | margin-right: -5px; 525 | border-bottom-color: rgba(0, 0, 0, 0.8) 526 | } 527 | 528 | pre.sf-dump { 529 | padding: 0px !important; 530 | margin: 0px !important; 531 | } 532 | 533 | .search-for-help { 534 | width: 85%; 535 | padding: 0; 536 | margin: 10px 0; 537 | list-style-type: none; 538 | display: inline-block; 539 | } 540 | .search-for-help li { 541 | display: inline-block; 542 | margin-right: 5px; 543 | } 544 | .search-for-help li:last-child { 545 | margin-right: 0; 546 | } 547 | .search-for-help li a { 548 | 549 | } 550 | .search-for-help li a i { 551 | width: 16px; 552 | height: 16px; 553 | overflow: hidden; 554 | display: block; 555 | } 556 | .search-for-help li a svg { 557 | fill: #fff; 558 | } 559 | .search-for-help li a svg path { 560 | background-size: contain; 561 | } 562 | -------------------------------------------------------------------------------- /vendor/whoops/Resources/images/bg-header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bydefaultiloveyou/Kurumi/f4c44a4288fcd718261fcf1993e2385d806d9bdb/vendor/whoops/Resources/images/bg-header.jpg -------------------------------------------------------------------------------- /vendor/whoops/Resources/js/clipboard.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * clipboard.js v1.5.3 3 | * https://zenorocha.github.io/clipboard.js 4 | * 5 | * Licensed MIT © Zeno Rocha 6 | */ 7 | !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,r){function o(a,c){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!c&&s)return s(a,!0);if(i)return i(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ar;r++)n[r].fn.apply(n[r].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),r=n[t],o=[];if(r&&e)for(var i=0,a=r.length;a>i;i++)r[i].fn!==e&&r[i].fn._!==e&&o.push(r[i]);return o.length?n[t]=o:delete n[t],this}},e.exports=r},{}],8:[function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}n.__esModule=!0;var i=function(){function t(t,e){for(var n=0;n=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(jg.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); 4 | Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; 5 | !function(e){function n(e,n){return"___"+e.toUpperCase()+n+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(t,a,r,o){if(t.language===a){var c=t.tokenStack=[];t.code=t.code.replace(r,(function(e){if("function"==typeof o&&!o(e))return e;for(var r,i=c.length;-1!==t.code.indexOf(r=n(a,i));)++i;return c[i]=e,r})),t.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(t,a){if(t.language===a&&t.tokenStack){t.grammar=e.languages[a];var r=0,o=Object.keys(t.tokenStack);!function c(i){for(var u=0;u=o.length);u++){var g=i[u];if("string"==typeof g||g.content&&"string"==typeof g.content){var l=o[r],s=t.tokenStack[l],f="string"==typeof g?g:g.content,p=n(a,l),k=f.indexOf(p);if(k>-1){++r;var m=f.substring(0,k),d=new e.Token(a,e.tokenize(s,t.grammar),"language-"+a,s),h=f.substring(k+p.length),v=[];m&&v.push.apply(v,c([m])),v.push(d),h&&v.push.apply(v,c([h])),"string"==typeof g?i.splice.apply(i,[u,1].concat(v)):g.content=v}}else g.content&&c(g.content)}return i}(t.tokens)}}}})}(Prism); 6 | !function(e){var a=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,t=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],i=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,n=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,s=/[{}\[\](),:;]/;e.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:a,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|never|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|never|new|or|parent|print|private|protected|public|readonly|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s*)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:i,operator:n,punctuation:s};var l={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:e.languages.php},r=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:l}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:l}}];e.languages.insertBefore("php","variable",{string:r,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:a,string:r,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,number:i,operator:n,punctuation:s}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),e.hooks.add("before-tokenize",(function(a){/<\?/.test(a.code)&&e.languages["markup-templating"].buildPlaceholders(a,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g)})),e.hooks.add("after-tokenize",(function(a){e.languages["markup-templating"].tokenizePlaceholders(a,"php")}))}(Prism); 7 | !function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document&&document.querySelector){var e,t="line-numbers",i="linkable-line-numbers",n=/\n(?!$)/g,r=!0;Prism.plugins.lineHighlight={highlightLines:function(o,u,c){var h=(u="string"==typeof u?u:o.getAttribute("data-line")||"").replace(/\s+/g,"").split(",").filter(Boolean),d=+o.getAttribute("data-line-offset")||0,f=(function(){if(void 0===e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding="0",t.style.border="0",t.innerHTML=" 
 ",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}()?parseInt:parseFloat)(getComputedStyle(o).lineHeight),p=Prism.util.isActive(o,t),g=o.querySelector("code"),m=p?o:g||o,v=[],y=g.textContent.match(n),b=y?y.length+1:1,A=g&&m!=g?function(e,t){var i=getComputedStyle(e),n=getComputedStyle(t);function r(e){return+e.substr(0,e.length-2)}return t.offsetTop+r(n.borderTopWidth)+r(n.paddingTop)-r(i.paddingTop)}(o,g):0;h.forEach((function(e){var t=e.split("-"),i=+t[0],n=+t[1]||i;if(!((n=Math.min(b+d,n))i&&r.setAttribute("data-end",String(n)),r.style.top=(i-d-1)*f+A+"px",r.textContent=new Array(n-i+2).join(" \n")}));v.push((function(){r.style.width=o.scrollWidth+"px"})),v.push((function(){m.appendChild(r)}))}}));var P=o.id;if(p&&Prism.util.isActive(o,i)&&P){l(o,i)||v.push((function(){o.classList.add(i)}));var E=parseInt(o.getAttribute("data-start")||"1");s(".line-numbers-rows > span",o).forEach((function(e,t){var i=t+E;e.onclick=function(){var e=P+"."+i;r=!1,location.hash=e,setTimeout((function(){r=!0}),1)}}))}return function(){v.forEach(a)}}};var o=0;Prism.hooks.add("before-sanity-check",(function(e){var t=e.element.parentElement;if(u(t)){var i=0;s(".line-highlight",t).forEach((function(e){i+=e.textContent.length,e.parentNode.removeChild(e)})),i&&/^(?: \n)+$/.test(e.code.slice(-i))&&(e.code=e.code.slice(0,-i))}})),Prism.hooks.add("complete",(function e(i){var n=i.element.parentElement;if(u(n)){clearTimeout(o);var r=Prism.plugins.lineNumbers,s=i.plugins&&i.plugins.lineNumbers;l(n,t)&&r&&!s?Prism.hooks.add("line-numbers",e):(Prism.plugins.lineHighlight.highlightLines(n)(),o=setTimeout(c,1))}})),window.addEventListener("hashchange",c),window.addEventListener("resize",(function(){s("pre").filter(u).map((function(e){return Prism.plugins.lineHighlight.highlightLines(e)})).forEach(a)}))}function s(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function l(e,t){return e.classList.contains(t)}function a(e){e()}function u(e){return!!(e&&/pre/i.test(e.nodeName)&&(e.hasAttribute("data-line")||e.id&&Prism.util.isActive(e,i)))}function c(){var e=location.hash.slice(1);s(".temporary.line-highlight").forEach((function(e){e.parentNode.removeChild(e)}));var t=(e.match(/\.([\d,-]+)$/)||[,""])[1];if(t&&!document.getElementById(e)){var i=e.slice(0,e.lastIndexOf(".")),n=document.getElementById(i);n&&(n.hasAttribute("data-line")||n.setAttribute("data-line",""),Prism.plugins.lineHighlight.highlightLines(n,t,"temporary ")(),r&&document.querySelector(".temporary.line-highlight").scrollIntoView())}}}(); 8 | !function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var e="line-numbers",n=/\n(?!$)/g,t=Prism.plugins.lineNumbers={getLine:function(n,t){if("PRE"===n.tagName&&n.classList.contains(e)){var i=n.querySelector(".line-numbers-rows");if(i){var r=parseInt(n.getAttribute("data-start"),10)||1,s=r+(i.children.length-1);ts&&(t=s);var l=t-r;return i.children[l]}}},resize:function(e){r([e])},assumeViewportIndependence:!0},i=void 0;window.addEventListener("resize",(function(){t.assumeViewportIndependence&&i===window.innerWidth||(i=window.innerWidth,r(Array.prototype.slice.call(document.querySelectorAll("pre.line-numbers"))))})),Prism.hooks.add("complete",(function(t){if(t.code){var i=t.element,s=i.parentNode;if(s&&/pre/i.test(s.nodeName)&&!i.querySelector(".line-numbers-rows")&&Prism.util.isActive(i,e)){i.classList.remove(e),s.classList.add(e);var l,o=t.code.match(n),a=o?o.length+1:1,u=new Array(a+1).join("");(l=document.createElement("span")).setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=u,s.hasAttribute("data-start")&&(s.style.counterReset="linenumber "+(parseInt(s.getAttribute("data-start"),10)-1)),t.element.appendChild(l),r([s]),Prism.hooks.run("line-numbers",t)}}})),Prism.hooks.add("line-numbers",(function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}))}function r(e){if(0!=(e=e.filter((function(e){var n,t=(n=e,n?window.getComputedStyle?getComputedStyle(n):n.currentStyle||null:null)["white-space"];return"pre-wrap"===t||"pre-line"===t}))).length){var t=e.map((function(e){var t=e.querySelector("code"),i=e.querySelector(".line-numbers-rows");if(t&&i){var r=e.querySelector(".line-numbers-sizer"),s=t.textContent.split(n);r||((r=document.createElement("span")).className="line-numbers-sizer",t.appendChild(r)),r.innerHTML="0",r.style.display="block";var l=r.getBoundingClientRect().height;return r.innerHTML="",{element:e,lines:s,lineHeights:[],oneLinerHeight:l,sizer:r}}})).filter(Boolean);t.forEach((function(e){var n=e.sizer,t=e.lines,i=e.lineHeights,r=e.oneLinerHeight;i[t.length-1]=void 0,t.forEach((function(e,t){if(e&&e.length>1){var s=n.appendChild(document.createElement("span"));s.style.display="block",s.textContent=e}else i[t]=r}))})),t.forEach((function(e){for(var n=e.sizer,t=e.lineHeights,i=0,r=0;r= 145) { 14 | $header.addClass('header-expand'); 15 | } 16 | }); 17 | $header.on('mouseleave', function () { 18 | $header.removeClass('header-expand'); 19 | }); 20 | 21 | /* 22 | * add prettyprint classes to our current active codeblock 23 | * run prettyPrint() to highlight the active code 24 | * scroll to the line when prettyprint is done 25 | * highlight the current line 26 | */ 27 | var renderCurrentCodeblock = function(id) { 28 | Prism.highlightAll(); 29 | highlightCurrentLine(); 30 | } 31 | 32 | /* 33 | * Highlight the active and neighboring lines for the current frame 34 | * Adjust the offset to make sure that line is veritcally centered 35 | */ 36 | 37 | var highlightCurrentLine = function() { 38 | // We show more code than needed, purely for proper syntax highlighting 39 | // Let’s hide a big chunk of that code and then scroll the remaining block 40 | $activeFrame.find('.code-block').first().css({ 41 | maxHeight: 345, 42 | overflow: 'hidden', 43 | }); 44 | 45 | var line = $activeFrame.find('.code-block .line-highlight').first()[0]; 46 | line.scrollIntoView(); 47 | line.parentElement.scrollTop -= 180; 48 | 49 | $container.scrollTop(0); 50 | } 51 | 52 | /* 53 | * click handler for loading codeblocks 54 | */ 55 | 56 | $frameContainer.on('click', '.frame', function() { 57 | 58 | var $this = $(this); 59 | var id = /frame\-line\-([\d]*)/.exec($this.attr('id'))[1]; 60 | var $codeFrame = $('#frame-code-' + id); 61 | 62 | if ($codeFrame) { 63 | 64 | $activeLine.removeClass('active'); 65 | $activeFrame.removeClass('active'); 66 | 67 | $this.addClass('active'); 68 | $codeFrame.addClass('active'); 69 | 70 | $activeLine = $this; 71 | $activeFrame = $codeFrame; 72 | 73 | renderCurrentCodeblock(id); 74 | 75 | } 76 | 77 | }); 78 | 79 | var clipboard = new Clipboard('.clipboard'); 80 | var showTooltip = function(elem, msg) { 81 | elem.classList.add('tooltipped', 'tooltipped-s'); 82 | elem.setAttribute('aria-label', msg); 83 | }; 84 | 85 | clipboard.on('success', function(e) { 86 | e.clearSelection(); 87 | 88 | showTooltip(e.trigger, 'Copied!'); 89 | }); 90 | 91 | clipboard.on('error', function(e) { 92 | showTooltip(e.trigger, fallbackMessage(e.action)); 93 | }); 94 | 95 | var btn = document.querySelector('.clipboard'); 96 | 97 | btn.addEventListener('mouseleave', function(e) { 98 | e.currentTarget.classList.remove('tooltipped', 'tooltipped-s'); 99 | e.currentTarget.removeAttribute('aria-label'); 100 | }); 101 | 102 | function fallbackMessage(action) { 103 | var actionMsg = ''; 104 | var actionKey = (action === 'cut' ? 'X' : 'C'); 105 | 106 | if (/Mac/i.test(navigator.userAgent)) { 107 | actionMsg = 'Press ⌘-' + actionKey + ' to ' + action; 108 | } else { 109 | actionMsg = 'Press Ctrl-' + actionKey + ' to ' + action; 110 | } 111 | 112 | return actionMsg; 113 | } 114 | 115 | function scrollIntoView($node, $parent) { 116 | var nodeOffset = $node.offset(); 117 | var nodeTop = nodeOffset.top; 118 | var nodeBottom = nodeTop + nodeOffset.height; 119 | var parentScrollTop = $parent.scrollTop(); 120 | var parentHeight = $parent.height(); 121 | 122 | if (nodeTop < 0) { 123 | $parent.scrollTop(parentScrollTop + nodeTop); 124 | } else if (nodeBottom > parentHeight) { 125 | $parent.scrollTop(parentScrollTop + nodeBottom - parentHeight); 126 | } 127 | } 128 | 129 | $(document).on('keydown', function(e) { 130 | var applicationFrames = $frameContainer.hasClass('frames-container-application'), 131 | frameClass = applicationFrames ? '.frame.frame-application' : '.frame'; 132 | 133 | if(e.ctrlKey || e.which === 74 || e.which === 75) { 134 | // CTRL+Arrow-UP/k and Arrow-Down/j support: 135 | // 1) select the next/prev element 136 | // 2) make sure the newly selected element is within the view-scope 137 | // 3) focus the (right) container, so arrow-up/down (without ctrl) scroll the details 138 | if (e.which === 38 /* arrow up */ || e.which === 75 /* k */) { 139 | $activeLine.prev(frameClass).click(); 140 | scrollIntoView($activeLine, $leftPanel); 141 | $container.focus(); 142 | e.preventDefault(); 143 | } else if (e.which === 40 /* arrow down */ || e.which === 74 /* j */) { 144 | $activeLine.next(frameClass).click(); 145 | scrollIntoView($activeLine, $leftPanel); 146 | $container.focus(); 147 | e.preventDefault(); 148 | } 149 | } else if (e.which == 78 /* n */) { 150 | if ($appFramesTab.length) { 151 | setActiveFramesTab($('.frames-tab:not(.frames-tab-active)')); 152 | } 153 | } 154 | }); 155 | 156 | // Render late enough for highlightCurrentLine to be ready 157 | renderCurrentCodeblock(); 158 | 159 | // Avoid to quit the page with some protocol (e.g. IntelliJ Platform REST API) 160 | $ajaxEditors.on('click', function(e){ 161 | e.preventDefault(); 162 | $.get(this.href); 163 | }); 164 | 165 | // Symfony VarDumper: Close the by default expanded objects 166 | $('.sf-dump-expanded') 167 | .removeClass('sf-dump-expanded') 168 | .addClass('sf-dump-compact'); 169 | $('.sf-dump-toggle span').html('▶'); 170 | 171 | // Make the given frames-tab active 172 | function setActiveFramesTab($tab) { 173 | $tab.addClass('frames-tab-active'); 174 | 175 | if ($tab.attr('id') == 'application-frames-tab') { 176 | $frameContainer.addClass('frames-container-application'); 177 | $allFramesTab.removeClass('frames-tab-active'); 178 | } else { 179 | $frameContainer.removeClass('frames-container-application'); 180 | $appFramesTab.removeClass('frames-tab-active'); 181 | } 182 | } 183 | 184 | $('a.frames-tab').on('click', function(e) { 185 | e.preventDefault(); 186 | setActiveFramesTab($(this)); 187 | }); 188 | }); 189 | -------------------------------------------------------------------------------- /vendor/whoops/Resources/views/env_details.html.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |

Environment & details:

4 | 5 |
6 | $data): ?> 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | $value): ?> 18 | 19 | 20 | 21 | 22 | 23 |
KeyValue
escape($k) ?>dump($value) ?>
24 | 25 | 26 | empty 27 | 28 |
29 | 30 |
31 | 32 | 33 |
34 | 35 | $h): ?> 36 |
37 | . escape(get_class($h)) ?> 38 |
39 | 40 |
41 | 42 |
43 | -------------------------------------------------------------------------------- /vendor/whoops/Resources/views/frame_code.html.php: -------------------------------------------------------------------------------- 1 | 4 |
5 | $frame) : ?> 6 | getLine(); ?> 7 |
8 | 19 | getFileLines($line - 20, 40); 25 | 26 | // getFileLines can return null if there is no source code 27 | if ($range) : 28 | $range = array_map(function ($line) { 29 | return empty($line) ? ' ' : $line; 30 | }, $range); 31 | $start = key($range) + 1; 32 | $code = join("\n", $range); 33 | ?> 34 | 35 | 36 |
escape($code) ?>
38 | 39 | 40 | 41 | dumpArgs($frame); ?> 42 | 43 |
44 | Arguments 45 |
46 |
47 | 48 |
49 | 50 | 51 | getComments(); 54 | ?> 55 |
56 | $comment) : ?> 57 | 58 |
59 | escape($context) ?> 60 | escapeButPreserveUris($comment) ?> 61 |
62 | 63 |
64 | 65 |
66 | 67 |
68 | -------------------------------------------------------------------------------- /vendor/whoops/Resources/views/frame_list.html.php: -------------------------------------------------------------------------------- 1 | 4 | $frame) : ?> 5 |
6 | 7 |
8 | breakOnDelimiter('\\', $tpl->escape($frame->getClass() ?: '')) ?> 9 | breakOnDelimiter('\\', $tpl->escape($frame->getFunction() ?: '')) ?> 10 |
11 | 12 |
13 | getFile() ? $tpl->breakOnDelimiter('/', $tpl->shorten($tpl->escape($frame->getFile()))) : '<#unknown>' ?> 14 |
15 |
16 | "> 2 | render($frame_list) ?> 3 | -------------------------------------------------------------------------------- /vendor/whoops/Resources/views/frames_description.html.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | Application frames (countIsApplication() ?>) 5 | 6 | 7 | All frames () 8 | 9 | 10 | 11 | kurumi: stack frames () 12 | 13 | 14 |
15 | -------------------------------------------------------------------------------- /vendor/whoops/Resources/views/header.html.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | $nameSection) : ?> 4 | 5 | escape($nameSection) ?> 6 | 7 | escape($nameSection) . ' \\' ?> 8 | 9 | 10 | 11 | (escape($code) ?>) 12 | 13 |
14 |
15 | 16 | escape($message) ?> 17 | 18 |
19 | Previous exceptions 20 |
21 |
    22 | $previousMessage) : ?> 23 |
  • 24 | escape($previousMessage) ?> 25 | () 26 |
  • 27 | 28 |
29 | 30 | 31 | No message 32 | 33 |
34 |
35 | -------------------------------------------------------------------------------- /vendor/whoops/Resources/views/header_outer.html.php: -------------------------------------------------------------------------------- 1 |
2 | render($header) ?> 3 |
4 | -------------------------------------------------------------------------------- /vendor/whoops/Resources/views/layout.html.php: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | <?php echo $tpl->escape($page_title) ?> 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 | 22 | render($panel_left_outer) ?> 23 | 24 | render($panel_details_outer) ?> 25 | 26 |
27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /vendor/whoops/Resources/views/panel_details.html.php: -------------------------------------------------------------------------------- 1 | render($frame_code) ?> 2 | render($env_details) ?> -------------------------------------------------------------------------------- /vendor/whoops/Resources/views/panel_details_outer.html.php: -------------------------------------------------------------------------------- 1 |
2 | render($panel_details) ?> 3 |
-------------------------------------------------------------------------------- /vendor/whoops/Resources/views/panel_left.html.php: -------------------------------------------------------------------------------- 1 | render($header_outer); 3 | $tpl->render($frames_description); 4 | $tpl->render($frames_container); 5 | -------------------------------------------------------------------------------- /vendor/whoops/Resources/views/panel_left_outer.html.php: -------------------------------------------------------------------------------- 1 |
2 | render($panel_left) ?> 3 |
-------------------------------------------------------------------------------- /vendor/whoops/Run.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops; 8 | 9 | use InvalidArgumentException; 10 | use Throwable; 11 | use Whoops\Exception\ErrorException; 12 | use Whoops\Exception\Inspector; 13 | use Whoops\Handler\CallbackHandler; 14 | use Whoops\Handler\Handler; 15 | use Whoops\Handler\HandlerInterface; 16 | use Whoops\Util\Misc; 17 | use Whoops\Util\SystemFacade; 18 | 19 | final class Run implements RunInterface 20 | { 21 | /** 22 | * @var bool 23 | */ 24 | private $isRegistered; 25 | 26 | /** 27 | * @var bool 28 | */ 29 | private $allowQuit = true; 30 | 31 | /** 32 | * @var bool 33 | */ 34 | private $sendOutput = true; 35 | 36 | /** 37 | * @var integer|false 38 | */ 39 | private $sendHttpCode = 500; 40 | 41 | /** 42 | * @var integer|false 43 | */ 44 | private $sendExitCode = 1; 45 | 46 | /** 47 | * @var HandlerInterface[] 48 | */ 49 | private $handlerStack = []; 50 | 51 | /** 52 | * @var array 53 | * @psalm-var list 54 | */ 55 | private $silencedPatterns = []; 56 | 57 | /** 58 | * @var SystemFacade 59 | */ 60 | private $system; 61 | 62 | /** 63 | * In certain scenarios, like in shutdown handler, we can not throw exceptions. 64 | * 65 | * @var bool 66 | */ 67 | private $canThrowExceptions = true; 68 | 69 | public function __construct(SystemFacade $system = null) 70 | { 71 | $this->system = $system ?: new SystemFacade; 72 | } 73 | 74 | /** 75 | * Explicitly request your handler runs as the last of all currently registered handlers. 76 | * 77 | * @param callable|HandlerInterface $handler 78 | * 79 | * @return Run 80 | */ 81 | public function appendHandler($handler) 82 | { 83 | array_unshift($this->handlerStack, $this->resolveHandler($handler)); 84 | return $this; 85 | } 86 | 87 | /** 88 | * Explicitly request your handler runs as the first of all currently registered handlers. 89 | * 90 | * @param callable|HandlerInterface $handler 91 | * 92 | * @return Run 93 | */ 94 | public function prependHandler($handler) 95 | { 96 | return $this->pushHandler($handler); 97 | } 98 | 99 | /** 100 | * Register your handler as the last of all currently registered handlers (to be executed first). 101 | * Prefer using appendHandler and prependHandler for clarity. 102 | * 103 | * @param callable|HandlerInterface $handler 104 | * 105 | * @return Run 106 | * 107 | * @throws InvalidArgumentException If argument is not callable or instance of HandlerInterface. 108 | */ 109 | public function pushHandler($handler) 110 | { 111 | $this->handlerStack[] = $this->resolveHandler($handler); 112 | return $this; 113 | } 114 | 115 | /** 116 | * Removes and returns the last handler pushed to the handler stack. 117 | * 118 | * @see Run::removeFirstHandler(), Run::removeLastHandler() 119 | * 120 | * @return HandlerInterface|null 121 | */ 122 | public function popHandler() 123 | { 124 | return array_pop($this->handlerStack); 125 | } 126 | 127 | /** 128 | * Removes the first handler. 129 | * 130 | * @return void 131 | */ 132 | public function removeFirstHandler() 133 | { 134 | array_pop($this->handlerStack); 135 | } 136 | 137 | /** 138 | * Removes the last handler. 139 | * 140 | * @return void 141 | */ 142 | public function removeLastHandler() 143 | { 144 | array_shift($this->handlerStack); 145 | } 146 | 147 | /** 148 | * Returns an array with all handlers, in the order they were added to the stack. 149 | * 150 | * @return array 151 | */ 152 | public function getHandlers() 153 | { 154 | return $this->handlerStack; 155 | } 156 | 157 | /** 158 | * Clears all handlers in the handlerStack, including the default PrettyPage handler. 159 | * 160 | * @return Run 161 | */ 162 | public function clearHandlers() 163 | { 164 | $this->handlerStack = []; 165 | return $this; 166 | } 167 | 168 | /** 169 | * Registers this instance as an error handler. 170 | * 171 | * @return Run 172 | */ 173 | public function register() 174 | { 175 | if (!$this->isRegistered) { 176 | // Workaround PHP bug 42098 177 | // https://bugs.php.net/bug.php?id=42098 178 | class_exists("\\Whoops\\Exception\\ErrorException"); 179 | class_exists("\\Whoops\\Exception\\FrameCollection"); 180 | class_exists("\\Whoops\\Exception\\Frame"); 181 | class_exists("\\Whoops\\Exception\\Inspector"); 182 | 183 | $this->system->setErrorHandler([$this, self::ERROR_HANDLER]); 184 | $this->system->setExceptionHandler([$this, self::EXCEPTION_HANDLER]); 185 | $this->system->registerShutdownFunction([$this, self::SHUTDOWN_HANDLER]); 186 | 187 | $this->isRegistered = true; 188 | } 189 | 190 | return $this; 191 | } 192 | 193 | /** 194 | * Unregisters all handlers registered by this Whoops\Run instance. 195 | * 196 | * @return Run 197 | */ 198 | public function unregister() 199 | { 200 | if ($this->isRegistered) { 201 | $this->system->restoreExceptionHandler(); 202 | $this->system->restoreErrorHandler(); 203 | 204 | $this->isRegistered = false; 205 | } 206 | 207 | return $this; 208 | } 209 | 210 | /** 211 | * Should Whoops allow Handlers to force the script to quit? 212 | * 213 | * @param bool|int $exit 214 | * 215 | * @return bool 216 | */ 217 | public function allowQuit($exit = null) 218 | { 219 | if (func_num_args() == 0) { 220 | return $this->allowQuit; 221 | } 222 | 223 | return $this->allowQuit = (bool) $exit; 224 | } 225 | 226 | /** 227 | * Silence particular errors in particular files. 228 | * 229 | * @param array|string $patterns List or a single regex pattern to match. 230 | * @param int $levels Defaults to E_STRICT | E_DEPRECATED. 231 | * 232 | * @return Run 233 | */ 234 | public function silenceErrorsInPaths($patterns, $levels = 10240) 235 | { 236 | $this->silencedPatterns = array_merge( 237 | $this->silencedPatterns, 238 | array_map( 239 | function ($pattern) use ($levels) { 240 | return [ 241 | "pattern" => $pattern, 242 | "levels" => $levels, 243 | ]; 244 | }, 245 | (array) $patterns 246 | ) 247 | ); 248 | 249 | return $this; 250 | } 251 | 252 | /** 253 | * Returns an array with silent errors in path configuration. 254 | * 255 | * @return array 256 | */ 257 | public function getSilenceErrorsInPaths() 258 | { 259 | return $this->silencedPatterns; 260 | } 261 | 262 | /** 263 | * Should Whoops send HTTP error code to the browser if possible? 264 | * Whoops will by default send HTTP code 500, but you may wish to 265 | * use 502, 503, or another 5xx family code. 266 | * 267 | * @param bool|int $code 268 | * 269 | * @return int|false 270 | * 271 | * @throws InvalidArgumentException 272 | */ 273 | public function sendHttpCode($code = null) 274 | { 275 | if (func_num_args() == 0) { 276 | return $this->sendHttpCode; 277 | } 278 | 279 | if (!$code) { 280 | return $this->sendHttpCode = false; 281 | } 282 | 283 | if ($code === true) { 284 | $code = 500; 285 | } 286 | 287 | if ($code < 400 || 600 <= $code) { 288 | throw new InvalidArgumentException( 289 | "Invalid status code '$code', must be 4xx or 5xx" 290 | ); 291 | } 292 | 293 | return $this->sendHttpCode = $code; 294 | } 295 | 296 | /** 297 | * Should Whoops exit with a specific code on the CLI if possible? 298 | * Whoops will exit with 1 by default, but you can specify something else. 299 | * 300 | * @param int $code 301 | * 302 | * @return int 303 | * 304 | * @throws InvalidArgumentException 305 | */ 306 | public function sendExitCode($code = null) 307 | { 308 | if (func_num_args() == 0) { 309 | return $this->sendExitCode; 310 | } 311 | 312 | if ($code < 0 || 255 <= $code) { 313 | throw new InvalidArgumentException( 314 | "Invalid status code '$code', must be between 0 and 254" 315 | ); 316 | } 317 | 318 | return $this->sendExitCode = (int) $code; 319 | } 320 | 321 | /** 322 | * Should Whoops push output directly to the client? 323 | * If this is false, output will be returned by handleException. 324 | * 325 | * @param bool|int $send 326 | * 327 | * @return bool 328 | */ 329 | public function writeToOutput($send = null) 330 | { 331 | if (func_num_args() == 0) { 332 | return $this->sendOutput; 333 | } 334 | 335 | return $this->sendOutput = (bool) $send; 336 | } 337 | 338 | /** 339 | * Handles an exception, ultimately generating a Whoops error page. 340 | * 341 | * @param Throwable $exception 342 | * 343 | * @return string Output generated by handlers. 344 | */ 345 | public function handleException($exception) 346 | { 347 | // Walk the registered handlers in the reverse order 348 | // they were registered, and pass off the exception 349 | $inspector = $this->getInspector($exception); 350 | 351 | // Capture output produced while handling the exception, 352 | // we might want to send it straight away to the client, 353 | // or return it silently. 354 | $this->system->startOutputBuffering(); 355 | 356 | // Just in case there are no handlers: 357 | $handlerResponse = null; 358 | $handlerContentType = null; 359 | 360 | try { 361 | foreach (array_reverse($this->handlerStack) as $handler) { 362 | $handler->setRun($this); 363 | $handler->setInspector($inspector); 364 | $handler->setException($exception); 365 | 366 | // The HandlerInterface does not require an Exception passed to handle() 367 | // and neither of our bundled handlers use it. 368 | // However, 3rd party handlers may have already relied on this parameter, 369 | // and removing it would be possibly breaking for users. 370 | $handlerResponse = $handler->handle($exception); 371 | 372 | // Collect the content type for possible sending in the headers. 373 | $handlerContentType = method_exists($handler, 'contentType') ? $handler->contentType() : null; 374 | 375 | if (in_array($handlerResponse, [Handler::LAST_HANDLER, Handler::QUIT])) { 376 | // The Handler has handled the exception in some way, and 377 | // wishes to quit execution (Handler::QUIT), or skip any 378 | // other handlers (Handler::LAST_HANDLER). If $this->allowQuit 379 | // is false, Handler::QUIT behaves like Handler::LAST_HANDLER 380 | break; 381 | } 382 | } 383 | 384 | $willQuit = $handlerResponse == Handler::QUIT && $this->allowQuit(); 385 | } finally { 386 | $output = $this->system->cleanOutputBuffer(); 387 | } 388 | 389 | // If we're allowed to, send output generated by handlers directly 390 | // to the output, otherwise, and if the script doesn't quit, return 391 | // it so that it may be used by the caller 392 | if ($this->writeToOutput()) { 393 | // @todo Might be able to clean this up a bit better 394 | if ($willQuit) { 395 | // Cleanup all other output buffers before sending our output: 396 | while ($this->system->getOutputBufferLevel() > 0) { 397 | $this->system->endOutputBuffering(); 398 | } 399 | 400 | // Send any headers if needed: 401 | if (Misc::canSendHeaders() && $handlerContentType) { 402 | header("Content-Type: {$handlerContentType}"); 403 | } 404 | } 405 | 406 | $this->writeToOutputNow($output); 407 | } 408 | 409 | if ($willQuit) { 410 | // HHVM fix for https://github.com/facebook/hhvm/issues/4055 411 | $this->system->flushOutputBuffer(); 412 | 413 | $this->system->stopExecution( 414 | $this->sendExitCode() 415 | ); 416 | } 417 | 418 | return $output; 419 | } 420 | 421 | /** 422 | * Converts generic PHP errors to \ErrorException instances, before passing them off to be handled. 423 | * 424 | * This method MUST be compatible with set_error_handler. 425 | * 426 | * @param int $level 427 | * @param string $message 428 | * @param string|null $file 429 | * @param int|null $line 430 | * 431 | * @return bool 432 | * 433 | * @throws ErrorException 434 | */ 435 | public function handleError($level, $message, $file = null, $line = null) 436 | { 437 | if ($level & $this->system->getErrorReportingLevel()) { 438 | foreach ($this->silencedPatterns as $entry) { 439 | $pathMatches = (bool) preg_match($entry["pattern"], $file); 440 | $levelMatches = $level & $entry["levels"]; 441 | if ($pathMatches && $levelMatches) { 442 | // Ignore the error, abort handling 443 | // See https://github.com/filp/whoops/issues/418 444 | return true; 445 | } 446 | } 447 | 448 | // XXX we pass $level for the "code" param only for BC reasons. 449 | // see https://github.com/filp/whoops/issues/267 450 | $exception = new ErrorException($message, /*code*/ $level, /*severity*/ $level, $file, $line); 451 | if ($this->canThrowExceptions) { 452 | throw $exception; 453 | } else { 454 | $this->handleException($exception); 455 | } 456 | // Do not propagate errors which were already handled by Whoops. 457 | return true; 458 | } 459 | 460 | // Propagate error to the next handler, allows error_get_last() to 461 | // work on silenced errors. 462 | return false; 463 | } 464 | 465 | /** 466 | * Special case to deal with Fatal errors and the like. 467 | * 468 | * @return void 469 | */ 470 | public function handleShutdown() 471 | { 472 | // If we reached this step, we are in shutdown handler. 473 | // An exception thrown in a shutdown handler will not be propagated 474 | // to the exception handler. Pass that information along. 475 | $this->canThrowExceptions = false; 476 | 477 | $error = $this->system->getLastError(); 478 | if ($error && Misc::isLevelFatal($error['type'])) { 479 | // If there was a fatal error, 480 | // it was not handled in handleError yet. 481 | $this->allowQuit = false; 482 | $this->handleError( 483 | $error['type'], 484 | $error['message'], 485 | $error['file'], 486 | $error['line'] 487 | ); 488 | } 489 | } 490 | 491 | /** 492 | * @param Throwable $exception 493 | * 494 | * @return Inspector 495 | */ 496 | private function getInspector($exception) 497 | { 498 | return new Inspector($exception); 499 | } 500 | 501 | /** 502 | * Resolves the giving handler. 503 | * 504 | * @param callable|HandlerInterface $handler 505 | * 506 | * @return HandlerInterface 507 | * 508 | * @throws InvalidArgumentException 509 | */ 510 | private function resolveHandler($handler) 511 | { 512 | if (is_callable($handler)) { 513 | $handler = new CallbackHandler($handler); 514 | } 515 | 516 | if (!$handler instanceof HandlerInterface) { 517 | throw new InvalidArgumentException( 518 | "Handler must be a callable, or instance of " 519 | . "Whoops\\Handler\\HandlerInterface" 520 | ); 521 | } 522 | 523 | return $handler; 524 | } 525 | 526 | /** 527 | * Echo something to the browser. 528 | * 529 | * @param string $output 530 | * 531 | * @return Run 532 | */ 533 | private function writeToOutputNow($output) 534 | { 535 | if ($this->sendHttpCode() && Misc::canSendHeaders()) { 536 | $this->system->setHttpResponseCode( 537 | $this->sendHttpCode() 538 | ); 539 | } 540 | 541 | echo $output; 542 | 543 | return $this; 544 | } 545 | } 546 | -------------------------------------------------------------------------------- /vendor/whoops/RunInterface.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops; 8 | 9 | use InvalidArgumentException; 10 | use Whoops\Exception\ErrorException; 11 | use Whoops\Handler\HandlerInterface; 12 | 13 | interface RunInterface 14 | { 15 | const EXCEPTION_HANDLER = "handleException"; 16 | const ERROR_HANDLER = "handleError"; 17 | const SHUTDOWN_HANDLER = "handleShutdown"; 18 | 19 | /** 20 | * Pushes a handler to the end of the stack 21 | * 22 | * @throws InvalidArgumentException If argument is not callable or instance of HandlerInterface 23 | * @param Callable|HandlerInterface $handler 24 | * @return Run 25 | */ 26 | public function pushHandler($handler); 27 | 28 | /** 29 | * Removes the last handler in the stack and returns it. 30 | * Returns null if there"s nothing else to pop. 31 | * 32 | * @return null|HandlerInterface 33 | */ 34 | public function popHandler(); 35 | 36 | /** 37 | * Returns an array with all handlers, in the 38 | * order they were added to the stack. 39 | * 40 | * @return array 41 | */ 42 | public function getHandlers(); 43 | 44 | /** 45 | * Clears all handlers in the handlerStack, including 46 | * the default PrettyPage handler. 47 | * 48 | * @return Run 49 | */ 50 | public function clearHandlers(); 51 | 52 | /** 53 | * Registers this instance as an error handler. 54 | * 55 | * @return Run 56 | */ 57 | public function register(); 58 | 59 | /** 60 | * Unregisters all handlers registered by this Whoops\Run instance 61 | * 62 | * @return Run 63 | */ 64 | public function unregister(); 65 | 66 | /** 67 | * Should Whoops allow Handlers to force the script to quit? 68 | * 69 | * @param bool|int $exit 70 | * @return bool 71 | */ 72 | public function allowQuit($exit = null); 73 | 74 | /** 75 | * Silence particular errors in particular files 76 | * 77 | * @param array|string $patterns List or a single regex pattern to match 78 | * @param int $levels Defaults to E_STRICT | E_DEPRECATED 79 | * @return \Whoops\Run 80 | */ 81 | public function silenceErrorsInPaths($patterns, $levels = 10240); 82 | 83 | /** 84 | * Should Whoops send HTTP error code to the browser if possible? 85 | * Whoops will by default send HTTP code 500, but you may wish to 86 | * use 502, 503, or another 5xx family code. 87 | * 88 | * @param bool|int $code 89 | * @return int|false 90 | */ 91 | public function sendHttpCode($code = null); 92 | 93 | /** 94 | * Should Whoops exit with a specific code on the CLI if possible? 95 | * Whoops will exit with 1 by default, but you can specify something else. 96 | * 97 | * @param int $code 98 | * @return int 99 | */ 100 | public function sendExitCode($code = null); 101 | 102 | /** 103 | * Should Whoops push output directly to the client? 104 | * If this is false, output will be returned by handleException 105 | * 106 | * @param bool|int $send 107 | * @return bool 108 | */ 109 | public function writeToOutput($send = null); 110 | 111 | /** 112 | * Handles an exception, ultimately generating a Whoops error 113 | * page. 114 | * 115 | * @param \Throwable $exception 116 | * @return string Output generated by handlers 117 | */ 118 | public function handleException($exception); 119 | 120 | /** 121 | * Converts generic PHP errors to \ErrorException 122 | * instances, before passing them off to be handled. 123 | * 124 | * This method MUST be compatible with set_error_handler. 125 | * 126 | * @param int $level 127 | * @param string $message 128 | * @param string $file 129 | * @param int $line 130 | * 131 | * @return bool 132 | * @throws ErrorException 133 | */ 134 | public function handleError($level, $message, $file = null, $line = null); 135 | 136 | /** 137 | * Special case to deal with Fatal errors and the like. 138 | */ 139 | public function handleShutdown(); 140 | } 141 | -------------------------------------------------------------------------------- /vendor/whoops/Util/HtmlDumperOutput.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Util; 8 | 9 | /** 10 | * Used as output callable for Symfony\Component\VarDumper\Dumper\HtmlDumper::dump() 11 | * 12 | * @see TemplateHelper::dump() 13 | */ 14 | class HtmlDumperOutput 15 | { 16 | private $output; 17 | 18 | public function __invoke($line, $depth) 19 | { 20 | // A negative depth means "end of dump" 21 | if ($depth >= 0) { 22 | // Adds a two spaces indentation to the line 23 | $this->output .= str_repeat(' ', $depth) . $line . "\n"; 24 | } 25 | } 26 | 27 | public function getOutput() 28 | { 29 | return $this->output; 30 | } 31 | 32 | public function clear() 33 | { 34 | $this->output = null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /vendor/whoops/Util/Misc.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Util; 8 | 9 | class Misc 10 | { 11 | /** 12 | * Can we at this point in time send HTTP headers? 13 | * 14 | * Currently this checks if we are even serving an HTTP request, 15 | * as opposed to running from a command line. 16 | * 17 | * If we are serving an HTTP request, we check if it's not too late. 18 | * 19 | * @return bool 20 | */ 21 | public static function canSendHeaders() 22 | { 23 | return isset($_SERVER["REQUEST_URI"]) && !headers_sent(); 24 | } 25 | 26 | public static function isAjaxRequest() 27 | { 28 | return ( 29 | !empty($_SERVER['HTTP_X_REQUESTED_WITH']) 30 | && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'); 31 | } 32 | 33 | /** 34 | * Check, if possible, that this execution was triggered by a command line. 35 | * @return bool 36 | */ 37 | public static function isCommandLine() 38 | { 39 | return PHP_SAPI == 'cli'; 40 | } 41 | 42 | /** 43 | * Translate ErrorException code into the represented constant. 44 | * 45 | * @param int $error_code 46 | * @return string 47 | */ 48 | public static function translateErrorCode($error_code) 49 | { 50 | $constants = get_defined_constants(true); 51 | if (array_key_exists('Core', $constants)) { 52 | foreach ($constants['Core'] as $constant => $value) { 53 | if (substr($constant, 0, 2) == 'E_' && $value == $error_code) { 54 | return $constant; 55 | } 56 | } 57 | } 58 | return "E_UNKNOWN"; 59 | } 60 | 61 | /** 62 | * Determine if an error level is fatal (halts execution) 63 | * 64 | * @param int $level 65 | * @return bool 66 | */ 67 | public static function isLevelFatal($level) 68 | { 69 | $errors = E_ERROR; 70 | $errors |= E_PARSE; 71 | $errors |= E_CORE_ERROR; 72 | $errors |= E_CORE_WARNING; 73 | $errors |= E_COMPILE_ERROR; 74 | $errors |= E_COMPILE_WARNING; 75 | return ($level & $errors) > 0; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /vendor/whoops/Util/SystemFacade.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Util; 8 | 9 | class SystemFacade 10 | { 11 | /** 12 | * Turns on output buffering. 13 | * 14 | * @return bool 15 | */ 16 | public function startOutputBuffering() 17 | { 18 | return ob_start(); 19 | } 20 | 21 | /** 22 | * @param callable $handler 23 | * @param int $types 24 | * 25 | * @return callable|null 26 | */ 27 | public function setErrorHandler(callable $handler, $types = 'use-php-defaults') 28 | { 29 | // Since PHP 5.4 the constant E_ALL contains all errors (even E_STRICT) 30 | if ($types === 'use-php-defaults') { 31 | $types = E_ALL; 32 | } 33 | return set_error_handler($handler, $types); 34 | } 35 | 36 | /** 37 | * @param callable $handler 38 | * 39 | * @return callable|null 40 | */ 41 | public function setExceptionHandler(callable $handler) 42 | { 43 | return set_exception_handler($handler); 44 | } 45 | 46 | /** 47 | * @return void 48 | */ 49 | public function restoreExceptionHandler() 50 | { 51 | restore_exception_handler(); 52 | } 53 | 54 | /** 55 | * @return void 56 | */ 57 | public function restoreErrorHandler() 58 | { 59 | restore_error_handler(); 60 | } 61 | 62 | /** 63 | * @param callable $function 64 | * 65 | * @return void 66 | */ 67 | public function registerShutdownFunction(callable $function) 68 | { 69 | register_shutdown_function($function); 70 | } 71 | 72 | /** 73 | * @return string|false 74 | */ 75 | public function cleanOutputBuffer() 76 | { 77 | return ob_get_clean(); 78 | } 79 | 80 | /** 81 | * @return int 82 | */ 83 | public function getOutputBufferLevel() 84 | { 85 | return ob_get_level(); 86 | } 87 | 88 | /** 89 | * @return bool 90 | */ 91 | public function endOutputBuffering() 92 | { 93 | return ob_end_clean(); 94 | } 95 | 96 | /** 97 | * @return void 98 | */ 99 | public function flushOutputBuffer() 100 | { 101 | flush(); 102 | } 103 | 104 | /** 105 | * @return int 106 | */ 107 | public function getErrorReportingLevel() 108 | { 109 | return error_reporting(); 110 | } 111 | 112 | /** 113 | * @return array|null 114 | */ 115 | public function getLastError() 116 | { 117 | return error_get_last(); 118 | } 119 | 120 | /** 121 | * @param int $httpCode 122 | * 123 | * @return int 124 | */ 125 | public function setHttpResponseCode($httpCode) 126 | { 127 | if (!headers_sent()) { 128 | // Ensure that no 'location' header is present as otherwise this 129 | // will override the HTTP code being set here, and mask the 130 | // expected error page. 131 | header_remove('location'); 132 | } 133 | 134 | return http_response_code($httpCode); 135 | } 136 | 137 | /** 138 | * @param int $exitStatus 139 | */ 140 | public function stopExecution($exitStatus) 141 | { 142 | exit($exitStatus); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /vendor/whoops/Util/TemplateHelper.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace Whoops\Util; 8 | 9 | use Symfony\Component\VarDumper\Caster\Caster; 10 | use Symfony\Component\VarDumper\Cloner\AbstractCloner; 11 | use Symfony\Component\VarDumper\Cloner\VarCloner; 12 | use Symfony\Component\VarDumper\Dumper\HtmlDumper; 13 | use Whoops\Exception\Frame; 14 | 15 | /** 16 | * Exposes useful tools for working with/in templates 17 | */ 18 | class TemplateHelper 19 | { 20 | /** 21 | * An array of variables to be passed to all templates 22 | * @var array 23 | */ 24 | private $variables = []; 25 | 26 | /** 27 | * @var HtmlDumper 28 | */ 29 | private $htmlDumper; 30 | 31 | /** 32 | * @var HtmlDumperOutput 33 | */ 34 | private $htmlDumperOutput; 35 | 36 | /** 37 | * @var AbstractCloner 38 | */ 39 | private $cloner; 40 | 41 | /** 42 | * @var string 43 | */ 44 | private $applicationRootPath; 45 | 46 | public function __construct() 47 | { 48 | // root path for ordinary composer projects 49 | $this->applicationRootPath = dirname(dirname(dirname(dirname(dirname(dirname(__DIR__)))))); 50 | } 51 | 52 | /** 53 | * Escapes a string for output in an HTML document 54 | * 55 | * @param string $raw 56 | * @return string 57 | */ 58 | public function escape($raw) 59 | { 60 | $flags = ENT_QUOTES; 61 | 62 | // HHVM has all constants defined, but only ENT_IGNORE 63 | // works at the moment 64 | if (defined("ENT_SUBSTITUTE") && !defined("HHVM_VERSION")) { 65 | $flags |= ENT_SUBSTITUTE; 66 | } else { 67 | // This is for 5.3. 68 | // The documentation warns of a potential security issue, 69 | // but it seems it does not apply in our case, because 70 | // we do not blacklist anything anywhere. 71 | $flags |= ENT_IGNORE; 72 | } 73 | 74 | $raw = str_replace(chr(9), ' ', $raw); 75 | 76 | return htmlspecialchars($raw, $flags, "UTF-8"); 77 | } 78 | 79 | /** 80 | * Escapes a string for output in an HTML document, but preserves 81 | * URIs within it, and converts them to clickable anchor elements. 82 | * 83 | * @param string $raw 84 | * @return string 85 | */ 86 | public function escapeButPreserveUris($raw) 87 | { 88 | $escaped = $this->escape($raw); 89 | return preg_replace( 90 | "@([A-z]+?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@", 91 | "$1", 92 | $escaped 93 | ); 94 | } 95 | 96 | /** 97 | * Makes sure that the given string breaks on the delimiter. 98 | * 99 | * @param string $delimiter 100 | * @param string $s 101 | * @return string 102 | */ 103 | public function breakOnDelimiter($delimiter, $s) 104 | { 105 | $parts = explode($delimiter, $s); 106 | foreach ($parts as &$part) { 107 | $part = '' . $part . ''; 108 | } 109 | 110 | return implode($delimiter, $parts); 111 | } 112 | 113 | /** 114 | * Replace the part of the path that all files have in common. 115 | * 116 | * @param string $path 117 | * @return string 118 | */ 119 | public function shorten($path) 120 | { 121 | if ($this->applicationRootPath != "/") { 122 | $path = str_replace($this->applicationRootPath, '…', $path); 123 | } 124 | 125 | return $path; 126 | } 127 | 128 | private function getDumper() 129 | { 130 | if (!$this->htmlDumper && class_exists('Symfony\Component\VarDumper\Cloner\VarCloner')) { 131 | $this->htmlDumperOutput = new HtmlDumperOutput(); 132 | // re-use the same var-dumper instance, so it won't re-render the global styles/scripts on each dump. 133 | $this->htmlDumper = new HtmlDumper($this->htmlDumperOutput); 134 | 135 | $styles = [ 136 | 'default' => 'color:#FFFFFF; line-height:normal; font:12px "Inconsolata", "Fira Mono", "Source Code Pro", Monaco, Consolas, "Lucida Console", monospace !important; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: normal', 137 | 'num' => 'color:#BCD42A', 138 | 'const' => 'color: #4bb1b1;', 139 | 'str' => 'color:#BCD42A', 140 | 'note' => 'color:#ef7c61', 141 | 'ref' => 'color:#A0A0A0', 142 | 'public' => 'color:#FFFFFF', 143 | 'protected' => 'color:#FFFFFF', 144 | 'private' => 'color:#FFFFFF', 145 | 'meta' => 'color:#FFFFFF', 146 | 'key' => 'color:#BCD42A', 147 | 'index' => 'color:#ef7c61', 148 | ]; 149 | $this->htmlDumper->setStyles($styles); 150 | } 151 | 152 | return $this->htmlDumper; 153 | } 154 | 155 | /** 156 | * Format the given value into a human readable string. 157 | * 158 | * @param mixed $value 159 | * @return string 160 | */ 161 | public function dump($value) 162 | { 163 | $dumper = $this->getDumper(); 164 | 165 | if ($dumper) { 166 | // re-use the same DumpOutput instance, so it won't re-render the global styles/scripts on each dump. 167 | // exclude verbose information (e.g. exception stack traces) 168 | if (class_exists('Symfony\Component\VarDumper\Caster\Caster')) { 169 | $cloneVar = $this->getCloner()->cloneVar($value, Caster::EXCLUDE_VERBOSE); 170 | // Symfony VarDumper 2.6 Caster class dont exist. 171 | } else { 172 | $cloneVar = $this->getCloner()->cloneVar($value); 173 | } 174 | 175 | $dumper->dump( 176 | $cloneVar, 177 | $this->htmlDumperOutput 178 | ); 179 | 180 | $output = $this->htmlDumperOutput->getOutput(); 181 | $this->htmlDumperOutput->clear(); 182 | 183 | return $output; 184 | } 185 | 186 | return htmlspecialchars(print_r($value, true)); 187 | } 188 | 189 | /** 190 | * Format the args of the given Frame as a human readable html string 191 | * 192 | * @param Frame $frame 193 | * @return string the rendered html 194 | */ 195 | public function dumpArgs(Frame $frame) 196 | { 197 | // we support frame args only when the optional dumper is available 198 | if (!$this->getDumper()) { 199 | return ''; 200 | } 201 | 202 | $html = ''; 203 | $numFrames = count($frame->getArgs()); 204 | 205 | if ($numFrames > 0) { 206 | $html = '
    '; 207 | foreach ($frame->getArgs() as $j => $frameArg) { 208 | $html .= '
  1. '. $this->dump($frameArg) .'
  2. '; 209 | } 210 | $html .= '
'; 211 | } 212 | 213 | return $html; 214 | } 215 | 216 | /** 217 | * Convert a string to a slug version of itself 218 | * 219 | * @param string $original 220 | * @return string 221 | */ 222 | public function slug($original) 223 | { 224 | $slug = str_replace(" ", "-", $original); 225 | $slug = preg_replace('/[^\w\d\-\_]/i', '', $slug); 226 | return strtolower($slug); 227 | } 228 | 229 | /** 230 | * Given a template path, render it within its own scope. This 231 | * method also accepts an array of additional variables to be 232 | * passed to the template. 233 | * 234 | * @param string $template 235 | * @param array $additionalVariables 236 | */ 237 | public function render($template, array $additionalVariables = null) 238 | { 239 | $variables = $this->getVariables(); 240 | 241 | // Pass the helper to the template: 242 | $variables["tpl"] = $this; 243 | 244 | if ($additionalVariables !== null) { 245 | $variables = array_replace($variables, $additionalVariables); 246 | } 247 | 248 | call_user_func(function () { 249 | extract(func_get_arg(1)); 250 | require func_get_arg(0); 251 | }, $template, $variables); 252 | } 253 | 254 | /** 255 | * Sets the variables to be passed to all templates rendered 256 | * by this template helper. 257 | * 258 | * @param array $variables 259 | */ 260 | public function setVariables(array $variables) 261 | { 262 | $this->variables = $variables; 263 | } 264 | 265 | /** 266 | * Sets a single template variable, by its name: 267 | * 268 | * @param string $variableName 269 | * @param mixed $variableValue 270 | */ 271 | public function setVariable($variableName, $variableValue) 272 | { 273 | $this->variables[$variableName] = $variableValue; 274 | } 275 | 276 | /** 277 | * Gets a single template variable, by its name, or 278 | * $defaultValue if the variable does not exist 279 | * 280 | * @param string $variableName 281 | * @param mixed $defaultValue 282 | * @return mixed 283 | */ 284 | public function getVariable($variableName, $defaultValue = null) 285 | { 286 | return isset($this->variables[$variableName]) ? 287 | $this->variables[$variableName] : $defaultValue; 288 | } 289 | 290 | /** 291 | * Unsets a single template variable, by its name 292 | * 293 | * @param string $variableName 294 | */ 295 | public function delVariable($variableName) 296 | { 297 | unset($this->variables[$variableName]); 298 | } 299 | 300 | /** 301 | * Returns all variables for this helper 302 | * 303 | * @return array 304 | */ 305 | public function getVariables() 306 | { 307 | return $this->variables; 308 | } 309 | 310 | /** 311 | * Set the cloner used for dumping variables. 312 | * 313 | * @param AbstractCloner $cloner 314 | */ 315 | public function setCloner($cloner) 316 | { 317 | $this->cloner = $cloner; 318 | } 319 | 320 | /** 321 | * Get the cloner used for dumping variables. 322 | * 323 | * @return AbstractCloner 324 | */ 325 | public function getCloner() 326 | { 327 | if (!$this->cloner) { 328 | $this->cloner = new VarCloner(); 329 | } 330 | return $this->cloner; 331 | } 332 | 333 | /** 334 | * Set the application root path. 335 | * 336 | * @param string $applicationRootPath 337 | */ 338 | public function setApplicationRootPath($applicationRootPath) 339 | { 340 | $this->applicationRootPath = $applicationRootPath; 341 | } 342 | 343 | /** 344 | * Return the application root path. 345 | * 346 | * @return string 347 | */ 348 | public function getApplicationRootPath() 349 | { 350 | return $this->applicationRootPath; 351 | } 352 | } 353 | -------------------------------------------------------------------------------- /vendor/zafkiel/Classloader.php: -------------------------------------------------------------------------------- 1 | dependencies = require __DIR__ . "/../../zafkiel.php"; 12 | } 13 | 14 | public function Intialize() 15 | { 16 | // looping semua dependensi 17 | spl_autoload_register(function ($class) { 18 | 19 | // pisah string untuk menghapus array index 0 20 | $exClass = explode("\\", $class); 21 | unset($exClass[0]); 22 | 23 | // looping semua directory 24 | foreach ($this->dependencies as $namespace => $folder) { 25 | $file = __DIR__ . "/../../" . $folder . implode("/", $exClass) . ".php"; 26 | 27 | // dan require jika class nya ada 28 | if (file_exists($file)) { 29 | require $file; 30 | return; 31 | } 32 | } 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /zafkiel.php: -------------------------------------------------------------------------------- 1 | "app/", 5 | 'Kurumi\\' => "vendor/kurumi/", 6 | 'Whoops\\' => "vendor/whoops/", 7 | 'Rasiel\\' => "vendor/rasiel/", 8 | ); 9 | --------------------------------------------------------------------------------