Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Php symfony update #10

Open
wants to merge 2 commits into
base: php-symfony
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 2 additions & 196 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,198 +1,6 @@
# Symfony 2.8 - Exercise 5 - Simple CRUD on REST
# PHP Symfony 2.8 scaffolding for RealSkill


## Summary

Expected result of this task is an application which allows user to create/read/update/delete row in the table using REST requests.

Sample employee structure:
```
[
'id' => 1,
'name' => 'Martin'
'surname' => 'Fowler'
'email' => '[email protected]'
'daysInOffice' => 2,
'bio' => 'Lorem ipsum dolor sit amet.'
]
```

To make working with JSON requests easy we have installed and configured **symfony-json-request-transformer** bundle so:
```
A request with JSON content like:
{
"foo": "bar"
}
will be decoded automatically so can access the foo property like:

$request->request->get('foo');
```

If you have solved **Symfony 2 - Exercise 4 - Simple CRUD** then You can copy `Employee` entity to this branch and step 1 will be done.
`git checkout task/4-simple-crud -- src/AppBundle/Entity/Employee.php`

## Goals

In order to complete this exercise you will need to follow these steps:

1. Create `Employee` entity in `AppBundle/Entity/Employee.php` with proper `namespace`. Entity should contain properties listed below with setters and getters for each one.

* id - primary key, autoincrement
* name - type: `string`, length: 64, required, assertions:
* not blank
* min length = 3
* max length = 64
* surname - type: `string`, length: 64, required, assertions:
* not blank
* min length = 3
* max length = 64
* email - type: `string`, length: 254, required, unique, assertions:
* not blank
* email
* max length = 254
* bio - type: `string`, length: 400, not required, assertions:
* max length = 400
* daysInOffice - type: `smallint`, required, assertions:
* not blank
* range(2,5)
* min range message = "You must be at least {{ limit }} days working in the office."
* max range message = "You cannot work more than {{ limit }} days in the office."

2. Create endpoint to retrieve list of employees
* should be accessed via GET "/api/employee"
* should return array of employees as JSON

3. Create endpoint to create new employee
* should be accessed via POST "/api/employee"
* should assign name, surname, email, bio, daysInOffice from request to `Employee` object
* should validate if `Employee` after assigning data is valid
* if `Employee` is invalid it should return JSON with property success equal false and errors containing array of error messages per each property with **PRECONDITION_FAILED** status code - use specially created for this purpose `violation_list_converter` service to convert errors from `validator` service to array eg:
```
{
"success": false,
"errors": {
"name": "This value should not be blank."
}
}
```
* if unique constraint will throw exception it should return JSON response with property success equal false and errors containing info for `email` property that `Such email exists in DB.` with **CONFLICT** status code like below:
```
{
"success": false,
"errors": {
"email": "Such email exists in DB."
}
}
```
* if `Employee` is valid it should create it and return JSON response with property `success` set to to true and id set to newly created object id like below:
```
{
"success": true,
"id": 15
}
```

4. Create endpoint to update existing employee
* should be accessed via PUT "/api/employee/{employeeId}"
* should assign name, surname, email, bio, daysInOffice from request to `Employee` object
* should validate if `Employee` after assigning data is valid
* if `Employee` with given `employeeId` not exist it should return **NOT_FOUND** status code and JSON with property `success` set to false
* if `Employee` is invalid it should return JSON with property success equal false and errors containing array of error messages per each property with **PRECONDITION_FAILED** status code - use specially created for this purpose `violation_list_converter` service to convert errors from `validator` service to array eg:
```
{
"success": false,
"errors": {
"name": "This value should not be blank."
}
}
```
* if unique constraint will throw exception it should return JSON response with property success equal false and errors containing info for `email` property that `Such email exists in DB.` with **CONFLICT** status code like below:
```
{
"success": false,
"errors": {
"email": "Such email exists in DB."
}
}
```
* if `Employee` is valid it should create it and return JSON response with property `success` set to to true and id set to newly created object id like below:
```
{
"success": true,
"id": 15
}
```

5. Create endpoint to delete existing employee
* should be accessed via DELETE "/api/employee/{employeeId}"
* if `Employee` with given `employeeId` not exist it should **NOT_FOUND** status code and JSON with property `success` set to false
* if `Employee` with given `employeeId` exist it should delete him and return JSON with property `success` set to true

Expected result of `php app/composer test-dox` for completed exercise is listed below:
```
AppBundle\Tests\Entity\Employee
[x] Should not allow to save employee without name
[x] Should not allow to save employee without surname
[x] Should not allow to save employee without email
[x] Should not allow to save employee without days in office
[x] Should not allow to save employee with same email that exists in db
[x] Should allow to save employee without bio
[x] Should have defined length of each string field and trim if is longer

AppBundle\Tests\Feature\CreateEmployee
[x] Should return precondition failed with proper errors if empty data is send
[x] Should return precondition failed with proper errors if all send employee properties are empty
[x] Should return precondition failed with proper errors if name is to short
[x] Should return precondition failed with proper errors if name is to long
[x] Should return precondition failed with proper errors if surname is to short
[x] Should return precondition failed with proper errors if surname is to long
[x] Should return precondition failed with proper errors if email is invalid
[x] Should return precondition failed with proper errors if email is to long
[x] Should return precondition failed with proper errors if bio is to long
[x] Should return precondition failed with proper errors if days in office is invalid
[x] Should return precondition failed with proper errors if days in office has to low value
[x] Should return precondition failed with proper errors if days in office has to high value
[x] Should save employee if proper data is given and return its id
[x] Should not require bio

AppBundle\Tests\Feature\DeleteEmployee
[x] Should return 404 if employee not exists and json with property status set to false
[x] Should delete certain employee

AppBundle\Tests\Feature\RetrieveEmployee
[x] Should return employees array

AppBundle\Tests\Feature\UpdateEmployee
[x] Should save employee if proper data is given and return its id
[x] Should not require bio
[x] Should return precondition failed with proper errors if empty data is send
[x] Should return precondition failed with proper errors if all send employee properties are empty
[x] Should return precondition failed with proper errors if name is to short
[x] Should return precondition failed with proper errors if name is to long
[x] Should return precondition failed with proper errors if surname is to short
[x] Should return precondition failed with proper errors if surname is to long
[x] Should return precondition failed with proper errors if email is invalid
[x] Should return precondition failed with proper errors if email is to long
[x] Should return precondition failed with proper errors if bio is to long
[x] Should return precondition failed with proper errors if days in office is invalid
[x] Should return precondition failed with proper errors if days in office has to low value
[x] Should return precondition failed with proper errors if days in office has to high value
```


## Hints

Most of changes should lay in `src` dir. You can also modify templates in `app/Resources/views`. If needed You can also modify config and other files in `app` dir.

If You want to see what goals You have passed You should run: `php app/composer test-dox`. Each scenario with **[x]** has passed and those with **[ ]** has to be done.

More info about errors during tests You can get running tests with command: `php app/composer test`

This task is concerned as done when all tests are passing and when code-sniffer and mess-detector do not return errors nor warnings (ignore info about "Remaining deprecation notices" during test).

Remember to commit changes before You change branch.

Remember to install dependencies if You change branch.
You can quickly create Symfony tasks by cloning the scaffolding repo. You don't have to bother with configuration.

### Helpful links

Expand Down Expand Up @@ -228,7 +36,6 @@ Please remember to read documentation for Symfony 2.8 because it can differ in n

php app/composer code-sniffer


## Run php server

php app/console server:run
Expand All @@ -247,7 +54,6 @@ mysql> grant usage on *.* to realskill@localhost identified by 'realskill';
mysql> grant all privileges on realskill.* to realskill@localhost ;
```


**Now You can access website via http://127.0.0.1:8000**

Good luck!
135 changes: 0 additions & 135 deletions src/AppBundle/Tests/Entity/EmployeeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,141 +30,6 @@ public function shouldNotAllowToSaveEmployeeWithoutName()
$em->flush();
}

/**
* @test
* @expectedException Doctrine\DBAL\Exception\NotNullConstraintViolationException
*/
public function shouldNotAllowToSaveEmployeeWithoutSurname()
{
$employee = new Employee();
$employee
->setName('aaa')
->setEmail('[email protected]')
->setDaysInOffice(3);

$em = self::getEntityManager();

$em->persist($employee);
$em->flush();
}

/**
* @test
* @expectedException Doctrine\DBAL\Exception\NotNullConstraintViolationException
*/
public function shouldNotAllowToSaveEmployeeWithoutEmail()
{
$employee = new Employee();
$employee
->setName('aaa')
->setSurname('aaa')
->setDaysInOffice(3);

$em = self::getEntityManager();

$em->persist($employee);
$em->flush();
}

/**
* @test
* @expectedException Doctrine\DBAL\Exception\NotNullConstraintViolationException
*/
public function shouldNotAllowToSaveEmployeeWithoutDaysInOffice()
{
$employee = new Employee();
$employee
->setName('aaa')
->setSurname('aaa')
->setEmail('[email protected]');

$em = self::getEntityManager();

$em->persist($employee);
$em->flush();
}

/**
* @test
* @expectedException Doctrine\DBAL\Exception\UniqueConstraintViolationException
*/
public function shouldNotAllowToSaveEmployeeWithSameEmailThatExistsInDb()
{
$employee = new Employee();
$employee
->setName('aaa')
->setSurname('aaa')
->setEmail('[email protected]')
->setDaysInOffice(3);

$em = self::getEntityManager();

$em->persist($employee);
$em->flush();
}

/**
* @test
*/
public function shouldAllowToSaveEmployeeWithoutBio()
{
$employee = new Employee();
$employee
->setName(str_repeat('a', 64))
->setSurname(str_repeat('a', 64))
->setEmail(str_repeat('a', 254))
->setDaysInOffice(3);

$em = self::getEntityManager();

$em->persist($employee);
$em->flush();
$em->detach($employee);

/**
* @var Employee $savedEmployee
*/
$savedEmployee = $em->getRepository('AppBundle:Employee')->find(4);

$this->assertEquals(64, strlen($savedEmployee->getName()));
$this->assertEquals(64, strlen($savedEmployee->getSurname()));
$this->assertEquals(254, strlen($savedEmployee->getEmail()));
$this->assertEquals(0, strlen($savedEmployee->getBio()));
$this->assertEquals(3, $savedEmployee->getDaysInOffice());
}

/**
* @test
*/
public function shouldHaveDefinedLengthOfEachStringFieldAndTrimIfIsLonger()
{
$employee = new Employee();
$employee
->setName(str_repeat('a', 999))
->setSurname(str_repeat('a', 999))
->setEmail(str_repeat('a', 999))
->setBio(str_repeat('a', 999))
->setDaysInOffice(3);

$em = self::getEntityManager();

$em->persist($employee);
$em->flush();
$em->detach($employee);

/**
* @var Employee $savedEmployee
*/
$savedEmployee = $em->getRepository('AppBundle:Employee')->find(4);

$this->assertEquals(64, strlen($savedEmployee->getName()), 'Name should has max length equal 64');
$this->assertEquals(64, strlen($savedEmployee->getSurname()), 'Surname should has max length equal 64');
$this->assertEquals(254, strlen($savedEmployee->getEmail()), 'Email should has max length equal 254');
$this->assertEquals(400, strlen($savedEmployee->getBio()), 'Bio should has max length equal 400');
$this->assertEquals(3, $savedEmployee->getDaysInOffice());
}


/**
* @return \Doctrine\Common\Persistence\ObjectManager|object
*/
Expand Down
Loading