میخواهیم یک کتابخانه برای تجزیهی جدول بنویسیم.
یکی از علاقهمندیهای ما در نوشتن این کتابخانه، شیگرا نوشتن آن است پس برای نوشتن آن کلاسهایی را در نظر میگیریم.
هدف اصلی ما این است که این کتابخانه ورودیای مانند زیر بگیرد:
```
id|first header|second header|third header
1|salam|khoobi|khooshi?
2|quera|codecup 4|digikala
3|something|nothing|everything
4|this|is|easy
```
و در آخر یک کد htmlشده از جدول مثل
```
<table><tr><th>id</th><th>first header</th><th>second header</th><th>third header</th></tr><tr><td>1</td><td>salam</td><td>khoobi</td><td>khooshi?</td></tr><tr><td>2</td><td>quera</td><td>codecup 4</td><td>digikala</td></tr><tr><td>3</td><td>something</td><td>nothing</td><td>everything</td></tr><tr><td>4</td><td>this</td><td>is</td><td>easy</td></tr></table>
```
خروجی دهد.
در ادامه به شرح کلاسها و جزئیات پیادهسازی آنها میپردازیم.
## جزئیات
### کلاسها
#### `\Quera\CodeCup4\TableParser\Parser`
این کلاس کلاسِ اصلی ما است که دارای سه تابع زیر از نوع استاتیک است:
- `parse` که یک کد میگیرد و یک خروجی از نوع `\Quera\CodeCup4\TableParser\Table`
بر میگرداند که جدول ساخته شده است، کد جدول از چندین سطر تشکیل شده که ستونهای هر سطر با `|` از هم جدا شدهاند.
- `parseHeader` که یک خط کد به عنوان سطر اول جدول میگیرد و یک خروجی از نوع `\Quera\CodeCup4\TableParser\Header` بر میگرداند و در صورت معتبر نبودن کد یک اکسپشن از نوع `InvalidHeaderException` پرت میکند.
- `parseRow` که یک خط کد به عنوان سطر جدول و یک `Header` میگیرد و یک خروجی از نوع `\Quera\CodeCup4\TableParser\Data` بر میگرداند و در صورت معتبر نبودن کد یک اکسپشن از نوع `InvalidRowException` پرت میکند.
#### `\Quera\CodeCup4\TableParser\Table`
این کلاس وظیفهی نگهداری جدول را بر عهده دارد و شامل توابع زیر است:
- یک کانستراکتور که یک `Header` و یک آرایه از نوع `Data` میگیرد و جدول را از روی آن میسازد.
- تابع `getHeader` که سطر اول را بر میگرداند.
- تابع `getRows` که یک آرایه از سطرها برمیگرداند.
- تابع `render` که کد `html` مربوط به جدول را ساخته و بر میگرداند.
این تابع تنها شامل تگهای `table`، `tr`، `td` و `th` است و خروجیای مانند شکل زیر دارد:
```
<table><tr><th>header one</th><th>header two</td>...</tr><tr><td>row 1.1</td><td>row 1.2</td></tr><tr><td>row 2.1</td><td>row 2.2</td></tr>...</table>
```
دقت کنید هیچ فاصلهای در بین تگها یا در انتهای خروجی مجاز نیست.
#### `\Quera\CodeCup4\TableParser\Row`
یک ابسترکت کلاس است که `\Quera\CodeCup4\TableParser\Header` و `\Quera\CodeCup4\TableParser\Data` این کلاس را به ارث میبرند.
#### `\Quera\CodeCup4\TableParser\Header`
این کلاس وظیفهی نگهداری سطر اول جدول را بر عهده دارد و شامل توابع زیر است:
- یک کانتسراکتور که یک آرایه که در واقع ستونهای سطر اولند میگیرد. ستونها تنها میتوانند شامل حروف کوچک انگلیسی و اسپیس باشند و نباید خالی باشند همچنین محتوای ستونها باید از هم متمایز باشد در غیر اینصورت باید یک اکسپشن از نوع `InvalidHeaderException` پرت شود.
- تابع `columnsCount` که تعداد ستونها را برگرداند.
- تابع `render` که باید یک کد `html` با تگ `tr` و `th` به شکل زیر خروجی دهد:
```
<tr><th>first column</th><th>second column</th>...</tr>
```
دقت کنید هیچ فاصلهای نباید در بین تگها یا در ابتدا یا انتهای آنها باشد.
#### `\Quera\CodeCup4\TableParser\Data`
این کلاس وظیفهی نگهداری دیگر سطرهای جدول را بر عهده دارد و شامل توابع زیر است:
- یک کانستراکتور که یک آرایه که در واقع ستونهای سطر اند و یک هدر میگیرد. تعداد ستونهای سطر باید با تعداد ستونهای هدر برابر باشد؛ در غیر این صورت باید اکسپشنی از نوع `InvalidRowException` پرت شود.
- تابع `columnsCount` که تعداد ستونها را برگرداند.
- تابع `get` که یک ورودی مثل `x` دارد، اگر ورودی از نوع عدد بود، آنگاه مقدار ستون `x`ام (با شروع از ۰) سطر را برگرداند و در غیر اینصورت مقدار متناظر با سطر اولی که مقدار آن به شکل `CamelCase` برابر با `x` است را برگرداند. در هر دو صورت اگر ستون پیدا نشد یک اکسپشن از نوع `ColumnNotFoundException` پرت کند.
- توابع به شکل `get*` دیگر توابعی که با `get` شروع میشوند، باید به شکل `CamelCase` مقدار ستون متناظر با هدرش را برگرداند (در مثالها توضیحات بیشتری داده میشود.) و در صورتی که تابع نامعتبر بود اکسپشنی از نوع `InvalidMethodException` پرت شود.
- تابع `render` که باید یک کد `html` با تگ `tr` و `td` به شکل زیر خروجی دهد:
```
<tr><td>first column</td><td>second column</td>...</tr>
```
دقت کنید هیچ فاصلهای نباید در بین تگها یا در ابتدا یا انتهای آنها باشد.
کلاسهای دیگری نیز قابل استفاده هستند که در پروژهی اولیه آنها را میبینید.
## `CamelCase`
منظور از `CamelCase` در تبدیل این است که فاصلههای رشته حذف شده و حروف اول همهی کلمات به شکل بزرگ و بقیهی حرفها به کوچک نوشته شوند. به طور مثال `alireza amir` به `AlirezaAmir` تبدیل شود.
## مثال
یک نمونه از اجرای این کلاسها شکل زیر است:
```php
$table = \Quera\CodeCup4\TableParser\Parser::parse("id|first header|second header|third header
1|salam|khoobi|khooshi?
2|quera|codecup 4|digikala
3|something|nothing|everything
4|this|is|easy");
echo $table->render();
// <table><tr><th>id</th><th>first header</th><th>second header</th><th>third header</th></tr><tr><td>1</td><td>salam</td><td>khoobi</td><td>khooshi?</td></tr><tr><td>2</td><td>quera</td><td>codecup 4</td><td>digikala</td></tr><tr><td>3</td><td>something</td><td>nothing</td><td>everything</td></tr><tr><td>4</td><td>this</td><td>is</td><td>easy</td></tr></table>
echo $table->getHeader()->columnsCount();
// 4
echo $table->getHeader()->render();
// <tr><th>id</th><th>first header</th><th>second header</th><th>third header</th></tr>
echo $table->getRows()[0]->get(1);
// salam
echo $table->getRows()[0]->getId();
// 1
echo $table->getRows()[1]->getSecondHeader();
// codecup 4
echo $table->getRows()[1]->get("ThirdHeader");
// digikala
echo $table->getRows()[1]->getThirdHeader();
// digikala
echo $table->getRows()[1]->get(10);
// throws Quera\CodeCup4\TableParser\ColumnNotFoundException
echo $table->getRows()[1]->get("thirdHeader");
// throws Quera\CodeCup4\TableParser\ColumnNotFoundException
echo $table->getRows()[1]->get("third header");
// throws Quera\CodeCup4\TableParser\ColumnNotFoundException
echo $table->getRows()[1]->getInvalidHeader();
// throws Quera\CodeCup4\TableParser\InvalidMethodException
echo $table->getRows()[1]->randomFunction();
// throws Quera\CodeCup4\TableParser\InvalidMethodException
echo \Quera\CodeCup4\TableParser\Parser::parseHeader("a|b|c|d2")->render();
// throws Quera\CodeCup4\TableParser\InvalidHeaderException
echo (new \Quera\CodeCup4\TableParser\Header(['a', 'b', 'c']))->render();
// <tr><th>a</th><th>b</th><th>c</th></tr>
```
## بارگذاری
پروژهی اولیه را میتوانید از زیر دانلود کنید.
[دانلود کدهای اولیه پروژه](http://bayanbox.ir/download/2007887897855915447/table-parser-initial.zip)
در بارگذاری تنها کافی است پوشهی `Quera` را داخل یک فایل زیپ قرار داده و ارسال کنید.