Skip to content
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
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
OOPTIMO Job Application tests — PHP
------------
# OOPTIMO Job Application tests — PHP

Please follow the instructions below carefully. If you have any questions, feel free to reach out.

Expand All @@ -8,17 +7,17 @@ Please follow the instructions below carefully. If you have any questions, feel
This exercise consists of adding new functionalities to this app.
To do so, run the app and you will find the instructions on how to implement each exercise.

*Note: This is a project based on the basic template of [Yii 2](https://www.yiiframework.com/) but you don't need to know much about Yii or do it "the yii way". PHP, MVC, Composer and git is enought.*
_Note: This is a project based on the basic template of [Yii 2](https://www.yiiframework.com/) but you don't need to know much about Yii or do it "the yii way". PHP, MVC, Composer and git is enought._

## Instructions

1. Fork this repository under your own GitHub account.
2. Clone the repository to your local machine to work on the test.
3. Create a new branch to work on.
4. Solve the problem(s) described in the **Task** section.
1. Install dependencies: `composer install`
2. Run `php yii serve` to start the development server at `http://localhost:8080/`.
3. Write your code.
1. Install dependencies: `composer install`
2. Run `php yii serve` to start the development server at `http://localhost:8080/`.
3. Write your code.
5. Push your changes to your fork.
6. Submit a pull request (PR)

Expand Down Expand Up @@ -48,4 +47,4 @@ To do so, run the app and you will find the instructions on how to implement eac

We will review your pull request and provide feedback. There is no need to merge the PR, as we will handle that. Once reviewed, your PR will be closed.

#### Thank you for your time, and good luck!
### Thank you for your time, and good luck!
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"homepage": "https://www.yiiframework.com/",
"type": "project",
"license": "BSD-3-Clause",
"version": "0.0.2",
"support": {
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
"forum": "https://www.yiiframework.com/forum/",
Expand All @@ -17,7 +18,8 @@
"php": ">=7.4.0",
"yiisoft/yii2": "~2.0.45",
"yiisoft/yii2-bootstrap5": "~2.0.2",
"yiisoft/yii2-symfonymailer": "~2.0.3"
"yiisoft/yii2-symfonymailer": "~2.0.3",
"yiisoft/yii2-httpclient": "^2.0"
},
"require-dev": {
"yiisoft/yii2-debug": "~2.1.0",
Expand Down
49 changes: 37 additions & 12 deletions controllers/SiteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
namespace app\controllers;

use yii\web\Controller;
use app\models\JasonPlaceholderAPI;
use yii\data\ArrayDataProvider;
use yii\data\Pagination;

class SiteController extends Controller{
class SiteController extends Controller
{
/**
* {@inheritdoc}
*/
public function actions(){
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
Expand All @@ -21,16 +26,36 @@ public function actions(){
*
* @return string
*/
public function actionIndex(){
public function actionIndex()
{
return $this->render('index');
}

/**
* Displays test 1.
*
* @return string
*/
public function actionTest1(){
return $this->render('test1');
}

/**
* Displays test 1.
*
* @return string
*/
public function actionTest1()
{

// obtenemos los datos de la API
$model = new JasonPlaceholderAPI();
$data = $model->getData();

// Configurar la paginación
$pagination = new Pagination([
'totalCount' => count($data),
'pageSize' => 10,
]);

// Crear el proveedor de datos
$dataProvider = new ArrayDataProvider([
'allModels' => $data, // Datos obtenidos de la API (Array)
'pagination' => $pagination, // Configuración de la paginación
]);

// Renderizar la vista con los datos
return $this->render('test1', ['dataProvider' => $dataProvider]);
}
}
60 changes: 60 additions & 0 deletions models/JasonPlaceholderAPI.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace app\models;

use yii\base\Model;
use yii\httpclient\Client;
use Yii;

class JasonPlaceholderAPI extends Model
{
// URL base de la API de JSONPlaceholder
private $base_url = 'https://jsonplaceholder.typicode.com';

/**
* Consume la API de JSONPlaceholder y devuelve los datos.
*
* @return array|null Los datos de la API o null en caso de error.
*/
public function getData()
{
// Endpoint de la API
$endpoint = '/posts';

try {

// Creamos una instancia de la clase Client de Yii y hacemos una petición GET a la API
$client = new Client();
$response = $client->createRequest()
->setMethod('GET')
->setUrl($this->base_url . $endpoint)
->send();


// Si la petición fue exitosa, obtenemos los datos, los mapeamos y los devolvemos
if ($response->isOk) {
$data = $response->data;
$posts = [];
// Mapeamos los datos obtenidos para devolver solo los campos que nos interesan y en el formato deseado
foreach ($data as $item) {
$post = [
'userId' => $item['userId'],
'id' => $item['id'],
'title' => $item['title'],
'body' => $item['body']
];
$posts[] = $post;
}
return $posts;
} else {
// Registrar el error si la respuesta no es exitosa
Yii::error('Error en la respuesta de la API: ' . $response->content, __METHOD__);
return [];
}
} catch (\Exception $e) {
// Capturar y registrar cualquier excepción que ocurra durante la petición
Yii::error('Error al consumir la API: ' . $e->getMessage(), __METHOD__);
return [];
}
}
}
15 changes: 15 additions & 0 deletions views/site/_post.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

/** @var $post array */
?>
<div class="row mt-3" id="post_<?= $post['id'] ?>">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<h5 class="card-title"><?= ucfirst($post['title']) ?></h5>
<h6 class="card-subtitle mb-2 text-muted">ID de usuario: <?= $post['userId'] ?></h6>
<p class="card-text"><?= ucfirst($post['body']) ?></p>
</div>
</div>
</div>
</div>
62 changes: 43 additions & 19 deletions views/site/test1.php
Original file line number Diff line number Diff line change
@@ -1,33 +1,57 @@
<?php

use yii\widgets\ListView;
use yii\widgets\LinkPager;

/** @var yii\web\View $this */
/** @var $dataProvider yii\data\ArrayDataProvider */


$this->title = 'Test 1 — ooptimo';
?>
<div class="site-test1">
<div class="body-content">
<div class="row mt-5">
<div class="col-md-12">
<h2>Test 1 — Consumir API</h2>
<p>El objetivo es cargar datos de una API externa y mostrarlos en pantalla.</p>
<p>Usaremos la "Fake API" <a href="https://jsonplaceholder.typicode.com/" target="_blank">JSONPlaceholder</a> para cargar datos.<br>Usa este endpoint: <code>https://jsonplaceholder.typicode.com/posts</code>, y muestra una lista en esta misma página con los datos obtenidos.</p>
<h5>Ayuda</h5>
<ul>
<li>Estamos usando el framework MVC Yii v2: <a href="https://www.yiiframework.com/doc/guide/2.0/en" target="_blank">Guia</a>.</li>
<li>La API externa es la de JSONPlaceholder: <a href="https://jsonplaceholder.typicode.com/guide/" target="_blank">Guia</a></li>
<li>Los archivos relevantes estan en <code>/controllers</code>, <code>/models</code> y <code>/views</code>.</li>
<li>Para los estilos puedes editar directamente el archivo <code>/web/css/site.css</code>.</li>
</ul>
</div>
</div>
</div>
<div class="body-content">
<div class="row mt-5">
<div class="col-md-12">
<h2>Test 1 — Consumir API</h2>
<p>El objetivo es cargar datos de una API externa y mostrarlos en pantalla.</p>
<p>Usaremos la "Fake API" <a href="https://jsonplaceholder.typicode.com/" target="_blank">JSONPlaceholder</a> para cargar datos.<br>Usa este endpoint: <code>https://jsonplaceholder.typicode.com/posts</code>, y muestra una lista en esta misma página con los datos obtenidos.</p>

<h5>Ayuda</h5>
<ul>
<li>Estamos usando el framework MVC Yii v2: <a href="https://www.yiiframework.com/doc/guide/2.0/en" target="_blank">Guia</a>.</li>
<li>La API externa es la de JSONPlaceholder: <a href="https://jsonplaceholder.typicode.com/guide/" target="_blank">Guia</a></li>
<li>Los archivos relevantes estan en <code>/controllers</code>, <code>/models</code> y <code>/views</code>.</li>
<li>Para los estilos puedes editar directamente el archivo <code>/web/css/site.css</code>.</li>
</ul>
</div>
</div>
</div>

<hr>

<div class="posts-list">
<div class="row mt-4">
<h2>Posts</h2>
</div>

<?php
// Usamos listView para mostrar los datos y la paginación
echo ListView::widget([
'dataProvider' => $dataProvider,
'itemView' => function ($model, $key, $index, $widget) {
return $this->render('_post', ['post' => $model]);
},
'layout' => "{items}\n{pager}",
'pager' => [
'class' => \yii\widgets\LinkPager::class, // Clase del paginador
'options' => ['class' => 'pagination justify-content-center mt-3'], // Clase CSS personalizada
'linkOptions' => ['class' => 'page-link'], // Clase CSS para los enlaces
'prevPageLabel' => 'Anterior', // Etiqueta para el enlace de página anterior
'nextPageLabel' => 'Siguiente', // Etiqueta para el enlace de página siguiente
'disabledPageCssClass' => 'd-none', // Clase CSS para las páginas deshabilitadas
'activePageCssClass' => 'active', // Clase CSS para la página activa
],
]) ?>
</div>
</div>
</div>