نیما در شرکت *کدنویسگستران شرق بهجز حسن* مشغول به کار است. او فردی مینیمالیست است و از کتابخانههای بزرگ و پیچیدهی *PHP* متنفر است. در حال حاضر، تیم *کدنویسگستران شرق بهجز حسن* از موتور قالب *Smarty* استفاده میکند. این موتور قالب از نظر نیما بسیار بزرگ و پیچیده است. او تصمیم گرفته تا موتور قالب سادهای با نام *Smarties* بسازد تا در پروژههای بعدیشان از آن استفاده کنند.
از شما میخواهیم *Smarties* را برای نیما پیادهسازی کنید.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/problemset/assignments/4367/download_problem_initial_project/76791/) دانلود کنید.
## اینترفیس `SmartiesFilter`
*اسمارتیز* همانند سایر *template engine* ها امکان اعمال فیلتر روی مقادیر را داراست. البته، این فیلترها هیچ آرگومانی بهجز مقدار فعلی ندارد. همهی فیلترهای *اسمارتیز* اینترفیس `SmartiesFilter` را پیادهسازی میکنند. این اینترفیس تنها شامل متدی با نام `apply` است که متن ورودی را دریافت کرده و پس از اعمال تغییرات، متن نهایی را برمیگرداند.
```php
interface SmartiesFilter
{
public function apply($text);
}
```
## کلاس `SmartiesFilterFactory`
وظیفهی این کلاس، تبدیل یک تابع به آبجکتی از `SmartiesFilter` است. این کلاس شامل متدی *static* به نام `create` است که یک تابع را به شکل نام تابع یا *anonymous function* دریافت کرده و یک آبجکت از نوع `SmartiesFilter` برمیگرداند که عملکرد متد `apply` آن دقیقاً مطابق با تابع ورودی است.
اگر آرگومان ورودی نامعتبر بود (قابل فراخوانی نبود)، یک `InvalidArgumentException` با متن پیغام `filter must be callable` *throw* کنید.
```php
class SmartiesFilterFactory
{
public static function create($filter)
{
// TODO: Implement
}
}
```
**توجه:** برای پیادهسازی متد `create`، مجاز به ایجاد کلاس جدید (کلاسی که *anonymous* نباشد) در برنامه نیستید.
## کلاس `Smarties`
این کلاس، کلاس اصلی *اسمارتیز* است. این کلاس شامل متدهای زیر است:
1. متد `addFilter($name, $filter)`: این متد، یک فیلتر با نام `$name` را به فیلترها اضافه میکند. موارد زیر را برای پیادهسازی این متد در نظر داشته باشید:
+ اگر فیلتری با این نام از قبل موجود باشد، فیلتر جدید باید جایگزین فیلتر قبلی شود. اگر فیلتر ورودی از نوع `SmartiesFilter` نباشد، باید یک `InvalidArgumentException` با متن پیغام `filter must implement SmartiesFilter` *throw* کنید.
+ *اسمارتیز* نباید به کوچکی و بزرگی حروف در نام فیلترها حساس باشد.
2. متد `render($filepath, $parameters)`: این متد، نام فایل قالب ورودی و آرایهای انجمنی از پارامترها دریافت میکند و رشتهی خروجی را برمیگرداند. موارد زیر را برای پیادهسازی این متد در نظر داشته باشید:
+ اگر فایل `$filepath` موجود نباشد، باید یک `Exception` با متن پیغام `input file not exist` *throw* کنید.
+ اگر پارامتری موجود نباشد، باید یک `Exception` با متن پیغام `parameter "$parameterName" not provided` *throw* کنید (`$parameterName` نام پارامتر است).
+ اگر فیلتری موجود نباشد، باید یک `Exception` با متن پیغام `filter "$filter" does not exist` *throw* کنید (`$filter` نام فیلتر است).
+ *اسمارتیز* نباید به کوچکی و بزرگی حروف در نام پارامترها حساس باشد. **تضمین میشود** که دو پارامتر نظیر `a` و `A` بهصورت همزمان به این متد داده نمیشود.
پارامترها در قالب بهصورت زیر نوشته میشوند:
```
{{ parameter_name }}
```
برای اعمال فیلتر نیز از کاراکتر `|` استفاده میشود. میتوان یک یا چند فیلتر را بر روی یک پارامتر اعمال کرد:
```
{{ parameter1|uppercase }}
{{ parameter2|reverse|uppercase }}
```
فیلترها باید بهترتیب از چپ به راست روی پارامتر اعمال شوند.
```php
class Smarties
{
public function addFilter($name, $filter)
{
// TODO: Implement
}
public function render($filepath, $parameters)
{
// TODO: Implement
}
}
```
# مثال
با اجرای اسکریپت `index.php` موجود در پروژهی اولیه، خروجی باید بهصورت زیر باشد:
```html
<!DOCTYPE html>
<html>
<head>
<title>sample</title>
</head>
<body>
<p>WELCOME TO CODECUP!</p>
</body>
</html>
```
# آنچه باید آپلود کنید
فایلهای `Smarties.php` و `SmartiesFilterFactory` را *Zip* کرده و آپلود کنید.