Modern PHP, soft skills, productivity and time management.

PHPyths Buster: End of the project


2016-08-01-roman-drits-barnimages-005

Time to speed the things up!

The series becomes a little too long, so its time to the drastic movement.

The application is working now. Here I’ll describe how to add a new note and set reminder as done. I think, that this will be a good foundation for extending the application.

Attention!

To speed up the development I’ll compromise. There will be no authenticating inside the application (except in Evernote, of course), no store notes in the database and no production deploy.

That means that this application will be useful only for one user – you. And you’ll be able to use it for your personal use just by running the application locally. This also means that application will be a little slow because it will receive all data from Evernote on each request.

I think. I’ll cover that inconveniences in some time, maybe in other posts.

No more talking, let’s go!

Adding reminder

First, I’ll show you how to add a new reminder. I’ll start with creating a form type. Thanks to that I’ll be able to use some great Symfony’s functionalities for handling forms, like handling CSFR tokens and, even basic, validation.

class NoteType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add("title", TextType::class)
            ->add("content", TextareaType::class)
            ->add("reminder", TextType::class)
            ->add("submit", SubmitType::class);
    }

    public function getBlockPrefix() : string
    {
        return "note";
    }
}

As you may know, Symfony allows specifying the model for the form, but I didn’t do that. In fact, I removed the Note model because it interferes with the SDK’s one and is no longer needed if notes won’t be stored in the database.

To save new note I’m receiving data from the request itself, set the values in the Note model and send it to Evernote. If everything goes as expected you’ll be redirected back to notes list with a newly added note of course.

    /**
     * @Route("/new/", name="new_reminder")
     */
    public function newReminder(Request $request) : Response
    {
        $noteType = $this->createForm(NoteType::class);

        $noteType->handleRequest($request);
        if (true === $noteType->isValid()) {
            $note = new Note();
            $note->setTitle($noteType->get("title")->getData());
            $note->setContent(new PlainTextNoteContent($noteType->get("content")->getData()));
            $note->setReminder((new \DateTime($noteType->get("reminder")->getData()))->getTimestamp());

            $token = $this->get("session")->get("en_token");

            $client = new Client($token, true);

            $client->uploadNote($note);
        }

        return $this->redirectToRoute("note_list");
    }

And finally using the form in the template, thanks to using Symfony form type I can use twig helper `form(noteForm)` for rendering the whole form.

    {# ... #}
    {% endfor %}
    <hr>
    {{ form_start(noteForm, { "action": url("new_reminder") }) }}

    {{ form(noteForm) }}

Set reminder as done

Another basic action is setting reminders as done. To do this I’ll display simple “done” button aside each note. When you click this button a notes reminder will be set as done in Evernote and will disappear from the list.

This time, I’ll use the manually created form because it’s really simple and doing it by Symfony’s form type will have some drawbacks.

{# ... #}
<p>id: {{ note.guid }}</p>
<div>
    <form action="{{ url("note_done") }}" method="post">
        <input type="hidden" name="id" value="{{ note.guid }}"/>
        <input type="hidden" name="_token" value="{{ csrf_token(note.guid) }}"/>
        <input type="submit" value="done" />
    </form>
</div>

The action will be simple. Important thing is to handle CSRF tokens. The simplest way I’ve found to modify the note is to replace it.

    /**
     * @Route("/done/", name="note_done")
     */
    public function doneAction(Request $request) : Response
    {
        $token = $this->get("session")->get("en_token");

        $client = new Client($token, true);

        $noteId = $request->request->get("id");
        $csrf = $request->request->get("_token");

        if (false === $this->isCsrfTokenValid($noteId, $csrf)) {
            throw new \InvalidArgumentException("invalid token");
        }

        $note = $client->getNote($noteId);
        $doneNote = clone $note;
        $doneNote->setAsDone();

        $client->replaceNote($note, $doneNote);

        return $this->redirectToRoute("note_list");
    }

Conclusion

And that’s all I want to show you for now. I know that I made some shortcuts. But I was thinking about this series and the conclusion was: it’s too long and I should focus on showing you cool features of PHP and not necessarily creating an application from scratch.

So, this post ends series about creating the application. I’ll be surely developing it and you could always check out the progress on the GitHub.

If you have any questions about the project – let me know, I’ll be more than happy to help!

Don’t forget to check out other PHPhyts!

2 Comments

  1. some_person

    Hi there, maybe to speed up the app maybe you should use some kind of caching.

    • krzych

      Even storing the data in session will be enough 🙂 Session, SQLite, Redis – there are many many great and simple ways to avoid refreshing data on every request. But, with caching you have always one big problem – invalidation and it’s too big topic to cover it in such short post 😉

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

© 2024 Krzych Jończyk

Theme by Anders NorenUp ↑