Autoformatarea codului

Relativ recent am descoperit că pot face auto-formatarea codului la… commit. Da, știu, mind blowing 😀

Eu am nevoie de formatarea SCSS, JS, JSON și PHP. Folosesc întotdeauna composer câteva pachete node, deci am packages.json și composer.json mereu în proiect.  Prin urmare, folosim câteva pachete Node pentru a face treaba:

$ npm i --save-dev cross-env husky lint-staged prettier prettier-stylelint stylelint-scss

Husky instalează hooks de git necesare, lint-staged execută hooks pentru fișierele staged, cross-env permite setarea de variabile. Apoi, adăugăm în package.json:

{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },

  "lint-staged": {
    "*.{js,jsx}": [ "prettier --write", "git add" ],
    "*.{json}": [ "prettier --write --parser=json", "git add" ],
    "*.{scss,sass}": [ "prettier-stylelint --quiet --write", "git add" ],
    "*.{php,php_cs}": [ "php -l", "cross-env PHP_CS_FIXER_FUTURE_MODE=1 php-cs-fixer fix --config=.php_cs", "git add" ]
  }
}

Apoi avem fișierele de config:

// .prettierrc
{
	"useTabs": true,
	"semi": true,
	"singleQuote": true,
	"trailingComma": "all",
	"bracketSpacing": true,
	"jsxBracketSameLine": true,
	"arrowParens": "always"
}

// .stylelintrc
{
    "plugins": [
        "stylelint-scss",
    ],
    "rules": {
        "indentation": 2,
        "string-quotes": "single",
        "color-no-invalid-hex": true,
        "function-parentheses-space-inside": "always",
        "media-feature-parentheses-space-inside": "always",
        "selector-pseudo-class-parentheses-space-inside": "always",
        "max-empty-lines": 2,
        "scss/at-function-parentheses-space-before": "always"
    }
}

Pentru formatarea codului PHP avem nevoie să instalăm un pachet global:

$ composer global require friendsofphp/php-cs-fixer
<?php 

//.php_cs

return PhpCsFixer\Config::create()
  ->setRiskyAllowed(true)
  ->setRules(
	[
		'@Symfony' => true,
		'@Symfony:risky' => true,
		'@PHP71Migration' => true,
		'braces' => true,
		'array_indentation' => true,
		'array_syntax' => ['syntax' => 'short'],
		'dir_constant' => true,
		'heredoc_to_nowdoc' => true,
		'linebreak_after_opening_tag' => true,
		'modernize_types_casting' => true,
		'multiline_whitespace_before_semicolons' => true,
		'no_unreachable_default_argument_value' => true,
		'no_useless_else' => true,
		'no_useless_return' => true,
		'ordered_class_elements' => true,
		'ordered_imports' => true,
		'phpdoc_add_missing_param_annotation' => ['only_untyped' => false],
		'phpdoc_order' => true,
		'doctrine_annotation_braces' => true,
		'doctrine_annotation_indentation' => true,
		'doctrine_annotation_spaces' => true,
		'psr4' => true,
		'no_php4_constructor' => true,
		'no_short_echo_tag' => true,
		'semicolon_after_instruction' => true,
		'align_multiline_comment' => true,
		'doctrine_annotation_array_assignment' => true,
		'general_phpdoc_annotation_remove' => ['annotations' => ['author', 'package']],
		'list_syntax' => ['syntax' => 'short'],
		'phpdoc_types_order' => ['null_adjustment' => 'always_last'],
		'single_line_comment_style' => true,
	]
  )
  ->setCacheFile(__DIR__.'/.php_cs.cache')
  ->setIndent("\t")
  ->setFinder(
	PhpCsFixer\Finder::create()
	  ->in(__DIR__)
  );

Și cam asta e. De fiecare dată când se face commit, autoformatarea se aplică pe fișierul modificat. Asta înseamnă și un timp mai mare de commit, dar până acum nu am observat un delay mai mare de 5-10 secunde.

Evident, regulile sunt ajustabile, fiecare formatter având propriile opțiuni.

Coding tips: Interfețe

Un concept cu care am avut ceva de furcă la început a fost folosirea interfețelor. Peste tot găseam o explicație vag sumară, eventual și ceva legat de un contract și rămâneam cel puțin la fel de confuz ca înainte.

Din punctul meu de vedere, dacă nu plănuiești să ai un cod extensibil (e.g. prin plugin-uri), interfețele sunt overkill. Nu strică, dar nici nu aduc valoare.

Conceptele SOLID sunt another can of worms, despre care probabil voi scrie cu altă ocazie.

Pentru a înțelege scopul interfețelor, este util să înțelegi conceptele SOLID, în special open-closed principle, care zice că un obiect ar trebui să permită extinderea, nu modificarea. Continuă să citești Coding tips: Interfețe

Selectarea categoriilor cu ajutorul Carbon Fields

Despre Carbon Fields am scris atât pe blogul personal, cât și pe forum și am tot început să-l folosesc la diverse proiecte, având tot felul de provocări, care mai de care mai interesantă. Ultima? Să pot permite selectarea unei singure categorii pentru un anumit post. Soluția e foarte simplă și are câțiva pași simpli. Evident, în loc de category se poate folosi și o taxonomie proprie.

<?php

use \Carbon_Fields\Container;
use \Carbon_Fields\Field;

add_action('after_setup_theme', function () {
  // inițializăm Carbon Fields
  \Carbon_Fields\Carbon_Fields::boot();
});

function getCurrentValue()
{
  if (!is_admin()) {
    // pentru că toate câmpurile sunt parsate și în frontend, nu facem interogările decât în admin
    return [];
  }

  $currentPostID = absint($_GET['post'] ?? 0);

  $mediumTerm = wp_list_pluck((array) get_the_terms($currentPostID, 'category'), 'term_id');
  
  // în cazul în care postul are deja mai multe categorii setate, o întoarcem doar pe prima
  return array_shift($mediumTerm);
}

function getAvailableOptions()
{
  if (!is_admin()) {
    return [];
  }
  $terms = get_terms([
    'taxonomy' => 'category',
    'hide_empty' => false,
  ]);

  $parsedTerms[-1] = __('Select');

  foreach ($terms as $term) {
    // generăm un array de forma "id" => "Nume", pentru a-l putea afișa în select 
    $parsedTerms[$term->term_id] = $term->name;
  }

  return $parsedTerms;
}

add_action('carbon_fields_register_fields', function () {
  Container::make('post_meta', __('My Category'))
    ->where('post_type', '=', 'post')
    ->add_fields([
      Field::make('select', 'my_category', __('Category'))
        ->add_options(getAvailableOptions())
        ->set_required(true),
    ]);
});


add_action('carbon_fields_post_meta_container_saved', function ($postID) {
  $term = absint(carbon_get_the_post_meta('my_category'));
 

  if (!empty($term)) {
    wp_set_post_terms($postID, [$term], 'category', false);
    // https://developer.wordpress.org/reference/functions/wp_set_post_terms/
    // salvăm toată povestea
    // al patrulea argument, `false` poate fi setat ca `true` dacă se dorește 
    // adăugarea mai multor categorii
  }
});


add_filter('register_taxonomy_args', function ($args, $taxonomy) {
  if ($taxonomy === 'category') {
    // ascundem selectorul de categorie
    $args['meta_box_cb'] = false;
  }
  return $args;
}, 10, 3);

Cum configurezi eficient Windows pentru PHP Dev?

Mi se întâmplă deseori să constat lipsa –  pe sistemele unor programatori – a unor  utilitarele mici, inspirate sau portate din lumea Linux. Prin urmare, m-am gândit să încerc să fac un mic ghid despre ce și cum ar trebui instalat.

Plec de la premisa că este și NodeJS instalat iar XAMPP este Stack-ul folosit, dar se poate aplica în orice alt context; scopul este acela de a avea toate utilitarele disponibile în cmd (hint: încearcă cmder)

1. Rapid Environment Editor

Complet opțional, dar foarte la îndemână, util în editarea/adăugarea variabilelor. Sigur, te poți descurca și prin alte metode, dar REE este atât de eficient încât nici nu merită să iau în considerare alte explicații 😀

2. Gow

Este o colecție de utilitare, de genul whereis, wget, curl, grep, tar șamd. În total sunt peste o sută de astfel de programe.

3. GnuWin

Similar cu Gow, dar ultima actualizare a fost în 2009. Eu le am pe amândouă doar pentru că pe ăsta l-am găsit primul și mi-a fost prea lene să le compar 😀

4. Git

Instalat astfel încât Git va fi disponibil direct din cmd. Adică la instalare alegi ultima opțiune:


După ce instalăm tot ce am listat mai sus, deschidem REE și avem grijă ca în PATH să existe directoarele unde au fost instalate utilitarele astea:

Săgețile albastre sunt legate de contul curent din Windows și poate fi aflat prin apăsarea Win+R -> %appData%\npm respectiv %appData\Composer.

Pe lângă utilitarele înșirate mai sus, recomand să adaugi și directoarele bin  de la Apache sau Mysql, respectiv directorul în care se află executabilul php.exe (e.g. c:\xampp\php)

După ce ai adăugat toate variabilele astea în editor, salvezi și dai un restart (unii zic că logout ar fi suficient). Imediat după, dacă deschizi cmd vei avea la dispoziție o mulțime de utilitare, care mai de care mai… utile.

windows apple dropbox facebook twitter