✅ Notícias, temas e plug-ins da WEB e do WordPress. Aqui compartilhamos dicas e as melhores soluções para sites.

Prototipagem Rápida: Protótipo para Código, Parte 1

32

No que diz respeito aos protótipos rápidos e ao WordPress, fizemos duas coisas até agora:

  1. planejou o plugin ,
  2. esboçou um diagrama de como o código pode ser organizado

Neste ponto, fizemos trabalho suficiente para garantir o início da refatoração de nosso código. Ou seja, vamos começar a converter o protótipo em código. Mas isso é algo que vai precisar ser feito em duas fases.

Primeiro, vamos simplesmente introduzir classes que representam os diagramas do post anterior e que encapsulam a responsabilidade de cada projeto.

Depois disso, veremos como organizar o código em namespaces e pacotes. Antes de podermos fazer isso, porém, precisamos ter certeza de que o código é orientado a objetos e permanece funcional. Então é isso que vai acontecer neste post.

Protótipo para código

Se você está lendo os posts anteriores, note que estou planejando seguir a organização que esbocei no último post. Você não precisa seguir esse design específico, é claro.

Uma palavra sobre controle de origem

Se você estiver usando o controle de origem, é aqui que recomendo criar um branch fora do branch master (se estiver usando o Git) para que você possa fazer seu trabalho sem prejudicar a versão estável do código.

Isso está um pouco além do escopo da série, portanto, se você não estiver usando o controle de origem, não se preocupe. Se você for, estou optando por desenvolver como o nome desta ramificação. Vou mesclá-lo de volta ao mestre  assim que tiver certeza de que está funcional.

Escrevendo Código

Conforme o trabalho esboçado ontem, vou criar duas classes:

  1. a classe meta-caixa,
  2. a classe de exibição da caixa meta.

Haverá alguma reutilização de código do que já vimos, como você verá no código a seguir.

O código

Primeiro, nossa metabox :

<?php
/**
 * Registers the Meta Box with WordPress.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */

/**
 * Registers the Meta Box with WordPress. Defines the ID, title, display function,
 * and the post type on which it will live.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */
class Meta_Box {

    /**
     * A reference to the class that will display the contents in the meta box.
     *
     * @access private
     * @var    Meta_Box_Display
     */
    private $meta_box_display;

    /**
     * Instantiates the class by setting its property equal to a reference to its display.
     */
    public function __construct() {
        $this->meta_box_display = new Meta_Box_Display();
    }

    /**
     * The function responsible for hooking into the WordPress API.
     */
    public function init() {

        add_meta_box(
            'three-recent-posts',
            'Three Recent Posts',
            array( $this->meta_box_display, 'display' ),
            'post',
            'side'
        );
    }
}

E a seguir, nossa exibição :

<?php
/**
 * Defines the display for the meta box.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */

/**
 * Defines the display for the meta box that will render the content in the
 * context of its meta box.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */
class Meta_Box_Display {

    /**
     * A reference to the class that will display the contents in the meta box.
     *
     * @access private
     * @var    Post_Messenger
     */
    private $messenger;

    /**
     * Instantiates the object by setting a property equal to that of the class
     * responsible for rendering the messages from the post query.
     */
    public function __construct() {
        $this->messenger = new Post_Messenger( $this );
    }

    /**
     * If there are posts to display, renders them in the metabox. Otherwise, displays
     * a note that there are no posts to display.
     */
    public function display( $message) {
        $this->messenger->get_message();
    }
}

Que no código da caixa meta, no código da caixa meta estamos explicitamente instanciando a exibição para que possamos chamar seu método de exibição quando necessário.

Outra alternativa seria instanciar os dois objetos separadamente e então injetar a exibição na meta box via injeção de construtor ou algo semelhante. Isso precisaria ser feito em uma classe de terceiros.

As vantagens disso vêm de desacoplar um pouco mais as duas classes. Talvez nós vamos rever como fazer isso no próximo post.

Depois disso, precisamos seguir em frente e definir a classe responsável por exibir as mensagens dentro do contexto do Meta Box Display. Isto é o que chamaremos de Post Messenger :

<?php
/**
 * Display content for the meta box when requested.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */

/**
 * Retrieves information from the class responsible for querying the database and
 * renders it in the context of our meta box when called via the Meta Box Display.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */
class Post_Messenger {

    /**
     * A reference to the query resonsible for retrieving post information from
     * the database.
     *
     * @access private
     * @var    WP_Query
     */
    private $query;

    /**
     * A reference to the message that's displayed in the view of the
     * meta box.
     *
     * @access private
     */
    private $message;

    /**
     * Instantiates the class by setting a reference to the query.
     */
    public function __construct() {
        $this->query = new Post_Query();
    }

    /**
     * Retrieves the content to be displayed in the meta box.
     */
    public function get_message() {

        $this->get_description();

        if ($this->query->has_posts()) {
            $this->get_post_message();
        } else {
            $this->get_no_posts_message();
        }
    }

    /**
     * Displays the description of the content of the meta box.
     *
     * @access private
     */
    private function get_post_message() {
        include_once 'post-list.php';
    }

    /**
     * Displays the description of the content of the meta box.
     *
     * @access private
     */
    private function get_description() {
        include_once 'message-description.php';
    }

    /**
     * Displays a message of there are no recent posts.
     *
     * @access private
     */
    private function get_no_posts_message() {
        include_once 'no-post-list.php';
    }
}

Observe aqui que o Post Messenger também faz referência à Post Query. Esta é a classe onde a comunicação com o banco de dados acontece. Também incluí algumas funções auxiliares para tornar o código de visualização um pouco mais simples, como veremos em breve.

<?php
/**
 * Queries the database for three most recent posts.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */

/**
 * Queries the database for three most recent posts. Returns the query to the
 * caller so that it can be interrogates for posts or not.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */
class Post_Query {

    /**
     * A reference to the WP_Query this class wraps.
     *
     * @access private
     * @var    WP_Query
     */
    private $query;

    /**
     * Instantiates the class by preparing instance data and executing the
     * query so the display can render the contents.
     */
    public function __construct() {

        $this->query = null;
        $this->get_posts();
    }

    /**
     * Executes the query for returning the post recent posts ordered by date.
     *
     * @access private
     */
    private function get_posts() {

        $args = array(
            'post_type'   => 'post',
            'post_status' => 'publish',
            'orderby'     => 'date',
            'order'       => 'desc',
        );
        $this->query = new WP_Query( $args );

        return $this->query;
    }

    /**
     * A helper function to determine if the query has any posts.
     */
    public function has_posts() {
        return! $this->query->have_posts();
    }

    /**
     * A helper function for retrieving the next post in the list of
     * posts
     */
    public function the_post() {
        return $this->query->the_post();
    }
}

E é isso para as classes principais. Claro, ainda precisamos falar sobre os pontos de vista.

As visualizações

As views são responsáveis ​​por renderizar o HTML no contexto da meta box. Não gosto de escrever HTML no contexto do PHP (nem gosto de misturar PHP no contexto do HTML, mas isso é inevitável neste projeto).

Existem alguns grandes projetos de modelagem para tornar isso mais fácil, mas eu discordo. De qualquer forma, você notará que no  arquivo post-list.php, existem referências a funções auxiliares na classe Post Query. Isso é para ter certeza de que não estou expondo muitas propriedades e violando a Lei de Deméter.

Vamos dar uma olhada nesse arquivo primeiro, pois é o mais complicado :

<ol>
    <?php while ($this->query->has_posts()) {  ?>
        <?php $this->query->the_post(); ?>
        <li>
            <a href="<?php get_the_permalink(); ?>" target="_blank">
                <?php echo get_the_title(); ?>
            </a>
        </li>
    <?php } ?>
</ol>

Parece com o código padrão do WordPress, mas lembre-se de que, como esse arquivo é chamado no Post Messenger, ele se referirá à consulta como a consulta envolvida por essa classe.

Os dois últimos arquivos são bastante simples. Um deles fornece uma descrição :

<p>
    <span class="description">
        Displays up to the three most recent posts.
    </span><!-- .description -->
</p>

O outro fornece uma mensagem quando não há postagens :

<p>There are no recent posts.</p>

Fora isso, a funcionalidade básica está feita.

Inicializando o plug-in

A última coisa que precisamos fazer é iniciar o plugin. Para fazer isso, alteramos o código no arquivo principal do plugin para que fique assim :

<?php
/**
 * Three Recent Posts
 *
 * @package     TRP
 * @author      Tom McFarlin
 * @copyright   2017 Tom McFarlin
 * @license     MIT
 *
 * @wordpress-plugin
 * Plugin Name: Three Recent Posts
 * Plugin URI:  https://tommcfarlin.com/three-recent-posts/
 * Description: Displays the three mot recent posts in your post editor screen.
 * Version:     0.2.0
 * Author:      Tom McFarlin
 * Author URI:  https://tommcfarlin.com
 * Text Domain: three-recent-posts
 * License:     GPL
 * License URI: http://www.gnu.org/licenses/gpl-3.0.txt
 */

include 'class-meta-box.php';
include 'class-meta-box-display.php';
include 'class-post-messenger.php';
include 'class-post-query.php';

add_action( 'add_meta_boxes', 'trp_start' );
/**
 * Starts the plugin.
 */
function trp_start() {

    $meta_box = new Meta_Box();
    $meta_box->init();
}

Isso se conectará ao WordPress, instanciará nosso plug-in e o colocará em movimento. Ao executá-lo em sua instalação do WordPress, ele deve ficar exatamente como na primeira versão.

A única diferença é que agora temos as coisas organizadas em classes ao invés de funções individuais.

Notas

Primeiro, há oportunidades para refatoração aqui que reduziriam ainda mais o desacoplamento (como diferentes tipos de injeção de dependência, etc.), mas o objetivo desta série não é cobrir isso.

Em vez disso, é pegar a ideia de ver plugins escritos por muitas funções procedurais e então dividi-los em classes mais conceituais que encapsulam suas responsabilidades.

Em segundo lugar, se você revisar o código-fonte no repositório para esta versão do projeto, verá que também apresentei composer.json. Isso é para que eu possa aproveitar o PHP CodeSniffer e os padrões de codificação do WordPress ao escrever código.

Na última parte da série, passaremos pelo namespace e reorganizaremos os arquivos. Se o tempo permitir, incluiremos um autoloader para que não tenhamos que incluir manualmente os arquivos no topo do nosso arquivo de plugin.

Finalmente, mesclei este código no master e o marquei como 0.2.1 (já que tive que fazer um pequeno hotfix), já que ainda é um trabalho em andamento.

Postagens da série

  1. Prototipagem Rápida com WordPress: Do Conceito ao Plugin
  2. Prototipagem Rápida com WordPress: Análise de Conceito
  3. Prototipagem Rápida: Protótipo para Código, Parte 1
  4. Prototipagem Rápida: Protótipo para Código, Parte 2
  5. Prototipagem Rápida: Apresentando o Autoloading

Fonte de gravação: tommcfarlin.com

Este site usa cookies para melhorar sua experiência. Presumiremos que você está ok com isso, mas você pode cancelar, se desejar. Aceitar Consulte Mais informação