در این سوال از شما میخواهیم که بخشی از کوئرا فریمورک را طراحی کنید.
## توضیحات
+ در این فریمورک برای ورود و احراز هویت کاربر از [`JWT(Json Web Token)`](https://jwt.io) استفاده می شود.
+ همچنین برای ذخیرهسازی اطلاعات کاربران از `sqlite3` استفاده میشود.
+ سعی شده در این پروژه برای تمامی توابع توضیحات مناسب بر روی کد قرار داده شدهباشد.
+ دقت کنید سعی شده هر بخش به شکل جدا نمرهدهی شود و با پیادهسازی قسمتی از سوال، بتوانید نمرهی آن قسمت را دریافت کنید ( بجز بخشهایی که با یکدیگر ارتباط نزدیک دارند مانند `signUp` و `signIn` ) .
+ در تمامی بخشهای کار با فایل برای رفتن به خط جدید از `\n` استفاده کنید.
+ پروژهی اولیه در زیر قرار گرفتهاست، لازم است قسمتهایی که کامنت `TODO: implement` دارند را پیادهسازی کنید.
[دانلود کدهای اولیه پروژه](http://bayanbox.ir/download/8103367018364077313/Simple-API-initial.zip)
## پایگاه داده
برای شروع پایگاه دادهای با نام `qdb.sqlite` در جایی که `bootstrap.php` در آن قرار دارد، ایجاد کنید.
در این پایگاه داده باید یک جدول به نام `users` وجود داشتهباشد که ستونهای آن به شرح زیر است:
- `id`: `INTEGER PRIMARY KEY NOT NULL`
- `name`: `TEXT NOT NULL`
- `passWD`: `TEXT NOT NULL`
- `firstName`: `TEXT NOT NULL`
- `lastName`: `TEXT NOT NULL`
- `email`: `TEXT NOT NULL`
## بخشهایی که باید آنها را تکمیل کنید
### bootstrap.php
#### autoload
این تابع به عنوان تابع ورودی به `spl_autoload_register` داده خواهد شد.
این تابع باید در صورت ایجاد شدن شیء از هر یک کلاسهای موجود در پوشهی برنامه، که ساختار نامگذاری فایل آنها بصورت `class.نام کلاس.php` می باشد، فایل مربوط را `require_once` کند.
#### quera_exception_handler
این تابع باید `exception`ٰهای دریافتی خود را در پوشه برنامه و در فایل `exception.log` ذخیره کند.
به ازای هر `exception` باید توضیحات آن را با فرمت زیر در خط جدیدی به فایل اضافه نمایید.
این تابع به عنوان ورودی به `set_exception_handler` داده خواهد شد.
```php
$file - $line : $message
```
برای مثال یکی از خطوط ذخیره شده در فایل می تواند به این صورت باشد :
```
/project/test.php - 12 : Some error message
```
#### quera_error_handler
این تابع باید `error`های دریافتی خود را در پوشه برنامه و در فایل `error.log` ذخیره کند.
به ازای هر `error` باید توضیحات آن را با فرمت زیر در خط جدیدی به فایل اضافه نمایید.
این تابع به عنوان ورودی به `set_error_handler` داده خواهد شد.
```php
$level - $filename - $line : $message
```
برای مثال یکی از خطوط ذخیره شده در فایل میتواند به این صورت باشد:
```
E_USER_NOTICE - /project/test.php - 18 : Value at position 2 is not a number, using 0 (zero)
```
+ برای ذخیره `exception` و `error` الزامی برای استفاده از کلاس `Log` نیست.
+ بهتر است برای دسترسی به آدرس پوشه برنامه از `QUERA_FRAMEWORK_ROOT` استفاده کنید.
---
### class.log.php
#### __construct
تنها ورودی آن ، آدرس فایل مورد نظر جهت ذخیره لاگ میباشد. در صورت عدم وجود آن فایل ، آن را ایجاد میکند.
#### writeLog
دو ورودی `message` و `alertDetail` میگیرد و در انتهای فایل مورد نظر در خط جدید بصورت زیر مینویسد. در صورتی که فایل خالی بود از ابتدا فایل شروع میکند.
```php
$alertDetail : $message
```
---
### class.router.php
در این کلاس پنج تابع `post`, `get`, `put`, `delete`, `resolve` را به نحوی پیادهسازی کنید که عملیاتهای زیر را انجام دهند.
هر یک از توابع `post`, `get`, `put`, `delete` سه ورودی میگیرند که به ترتیب زیر میباشند :
1. آدرس ورودی جهت مسیریابی
2. آرایهای با دو عضو که عضو اول آن یک شیء از یک کلاس و عضو دوم آن نام تابعی از آن کلاس است.
3. آرایهای از آرگومانهایی که برای اجرای تابع مشخص شده از آنها استفاده میشود (می تواند آرایهای خالی باشد)
+ در ورودی این توابع می توان از `[s]` یا `[i]` استفاده کرد که به ترتیب نشاندهندهی یک `string` و `integer` هستند.
+ برای مثال اگر url ورودی تابع `/api/[i]/` باشد میتواند هرکدام از مسیر های `/api/21312/` یا `/api/3123/` یا `/api/1/?test=sample` را مسیریابی کند.
تابع `resolve` نیز دو ورودی میگیرد که به ترتیب زیر میباشند:
1. متدی که برنامه با آن فراخوانی شده است ( برای مثال : `GET` )
2. آدرس ورودی جهت مسیریابی
+ تابع `resolve` در صورت یافتن مسیر مناسب تابع مورد نظر آن مسیریابی را با آرگومان های مشخص شده اجرا می کند و `true` بر میگرداند و در صورت عدم یافتن مسیریابی مناسب `false` بر میگرداند.
+ اگر چند مسیریابی برای یک مسیرقابل قبول بودند الویت با مسیری است که زودتر از بقیه افزوده شده باشد.
+ `[s]` می تواند هر کاراکتری بجز `/` را شامل شود.
+
برای مثال یک استفاده از `Router` میتواند به صورت زیر باشد:
```php
$app = new Router();
$app->post('/api/v1/Message/', array(new Controller(),'sendMessage'), array());
$app->get('/api/v1/User/[s]/', array(new Controller(),'getUser'), array());
$app->resolve($_SERVER['REQUEST_METHOD'],$_SERVER['REQUEST_URI']);
```
---
### class.controller.php
#### signUp
اطلاعات ورودی ثبت نام یک کاربر را گرفته و در پایگاه داده ذخیره میکند. ورودیهای تابع به صورت زیر میباشند.
1. نام کاربری
2. رمز عبور
3. نام
4. نام خانوادگی
5. ایمیل
+ تمامی اطلاعات کاربر بجز رمز عبور را همانگونه که به تابع داده می شود در پایگاه داده ذخیره کنید.
+ رمز عبور را نیز با استفاده از `native password hashing API` موجود در `PHP` و با استفاده از الگوریتم `PASSWORD_BCRYPT` رمزگذاری کرده و سپس در پایگاه داده ذخیره کنید.
#### checkSignIn
یک نام کاربری و یک رمزعبور (بصورت رمزگذاری نشده) را به عنوان ورودی میگیرد و از پایگاه داده بررسی میکند که آیا اطلاعات ورودی صحیح است یا خیر.
#### createToken
این تابع `SECRET`, `HEADER`, `PAYLOAD` را دریافت کرده و به عنوان خروجی `JWT` را برمیگرداند.
+ الگوریتم مورد نظر جهت رمزنگاری `HS256` میباشد.
+ نیاز به `secret base64 encoded` نیست.
+ دقت کنید که باید تمام `TOKEN` را با فرمت صحیح برگردانید و برگرداندن `SIGNATURE` به تنهایی کافی نیست.
#### checkToken
این تابع `SECRET`, `TOKEN` دریافت می کند و تایید میکند که آیا این `TOKEN` با استفاده از این `SECRET` مورد تایید است یا خیر.
#### بارگذاری
فایلهای `class.controller.php`، `class.log.php`، `class.router.php`، `qdb.sqlite` و `bootstrap.php` را داخل یک فایل زیپ قرار داده و بارگذاری کنید.