{"id":231266,"date":"2022-12-16T14:36:00","date_gmt":"2022-12-16T11:36:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=231266"},"modified":"2022-12-16T14:36:20","modified_gmt":"2022-12-16T11:36:20","slug":"wordpress-widgetit-refaktorointi-osa-2","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/fi\/wordpress-widgetit-refaktorointi-osa-2\/","title":{"rendered":"WordPress-widgetit: Refaktorointi, osa 2"},"content":{"rendered":"\n<p><strong><a href=\"https:\/\/wordpress.mediadoma.com\/fi\/wordpress-widgetit-refaktorointi-osa-1\/\" title=\"Kaiken alustavan sis\u00e4ll\u00f6n\">Kaiken alustavan sis\u00e4ll\u00f6n<\/a><\/strong> j\u00e4lkeen olemme vihdoin paikassa, jossa olemme valmiita aloittamaan IDE:n ja koodinlaatuty\u00f6kalujemme aiheuttamien koodausstandardiongelmien ratkaisemisen.<\/p>\n<p>T\u00e4t\u00e4 tehdess\u00e4ni aion jakaa sis\u00e4ll\u00f6n kahteen viestiin:<\/p>\n<ul>\n<li>ensimm\u00e4inen viesti keskittyy vain olemassa olevan koodin uudelleenmuodostukseen,<\/li>\n<li>seuraavassa viestiss\u00e4 aiomme tarkastella laajennuksen rakenteen uudelleenj\u00e4rjestely\u00e4 organisaation ja arkkitehtuurin parantamiseksi.<\/li>\n<\/ul>\n<p>Katsotaanpa nyt kuitenkin koodin haistajan aiheuttamia virheit\u00e4 ja katsotaan, emmek\u00f6 pysty saamaan sit\u00e4 nykyaikaisempien standardien mukaisiksi.<\/p>\n<h2>WordPress Widget Boilerplate: Refactoring, osa 2<\/h2>\n<p>Huomaa, ett\u00e4 olen edelleen <strong>kehityshaaralla<\/strong>, koska emme ole viel\u00e4 valmiita yhdist\u00e4m\u00e4\u00e4n t\u00e4t\u00e4 masteriksi. Ja jos olet m\u00e4\u00e4ritt\u00e4nyt koodinsnifferit ja muut ty\u00f6kalut oikein, sinun pit\u00e4isi n\u00e4hd\u00e4 <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/dce6bda0d104192a21cb06dc7d3ca23c#file-00-regex-results-txt\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">seuraava:<\/a><\/strong><\/p>\n<pre><code>Warning: Uncaught ErrorException: require_once(\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/vendor\/autoload.php): failed to open stream: No such file or directory in \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/php-cs-fixer:62\nStack trace:\n#0 \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/php-cs-fixer(62): {closure}(2, 'require_once(\/U...', '\/Users\/tommcfar...', 62, Array)\n#1 \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/php-cs-fixer(62): require_once()\n#2 {main}\n  thrown in \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/php-cs-fixer on line 62\n\nCall Stack:\n    0.0041     365448   1. {main}() \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/php-cs-fixer:0\n\nFatal error: main(): Failed opening required '\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/vendor\/autoload.php' (include_path='.:\/usr\/local\/Cellar\/php@7.1\/7.1.19\/share\/php@7.1\/pear') in \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/php-cs-fixer on line 62\n\nCall Stack:\n    0.0041     365448   1. {main}() \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/php-cs-fixer:0\n\nYou can fix all errors by running following commands:\n'\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/php-cs-fixer' '--allow-risky=yes' '--config=.php_cs.dist' '--using-cache=yes' '--verbose' 'fix'\nERROR: Ruleset \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/phpcs.xml is not valid\n\nRun \"phpcs --help\" for usage information\n\nWarning: require(\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/parallel-lint.php): failed to open stream: No such file or directory in \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/parallel-lint on line 4\n\nCall Stack:\n    0.0035     352864   1. {main}() \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/parallel-lint:0\n\nFatal error: require(): Failed opening required '\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/parallel-lint.php' (include_path='.:\/usr\/local\/Cellar\/php@7.1\/7.1.19\/share\/php@7.1\/pear') in \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/parallel-lint on line 4\n\nCall Stack:\n    0.0035     352864   1. {main}() \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/parallel-lint:0\n\nPHP Warning:  require(\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/parallel-lint.php): failed to open stream: No such file or directory in \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/parallel-lint on line 4\nPHP Stack trace:\nPHP   1. {main}() \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/parallel-lint:0\nPHP Fatal error:  require(): Failed opening required '\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/parallel-lint.php' (include_path='.:\/usr\/local\/Cellar\/php@7.1\/7.1.19\/share\/php@7.1\/pear') in \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/parallel-lint on line 4\nPHP Stack trace:\nPHP   1. {main}() \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/parallel-lint:0\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:33     The class Widget_Name has 12 public methods. Consider refactoring Widget_Name to keep number of public methods under 10.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:33     The class Widget_Name is not named in CamelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:33     The property$widget_slug is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:97     The method get_widget_slug is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:111    The variable$widget_string is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:111    The variable$before_widget is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:111    The variable$widget_string is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:111    The variable$widget_string is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:111    The variable$after_widget is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:111    The variable$widget_string is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:111    The variable$widget_string is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:111    Avoid unusedparameters such as '$instance'.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:131    Avoid unusedlocal variables such as '$before_widget'.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:137    Avoid unusedlocal variables such as '$after_widget'.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:149    The method flush_widget_cache is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:159    The parameter $new_instance is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:159    The parameter $old_instance is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:159    The variable$old_instance is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:159    Avoid unusedparameters such as '$new_instance'.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:195    The method widget_textdomain is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:207    The parameter $network_wide is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:207    Avoid unusedparameters such as '$network_wide'.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:216    The parameter $network_wide is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:216    Avoid unusedparameters such as '$network_wide'.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:223    The method register_admin_styles is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:232    The method register_admin_scripts is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:241    The method register_widget_styles is not named in camelCase.\n\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/src\/Plugin.php:250    The method register_widget_scripts is not named in camelCase.\n[FATAL] \/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/phpcs.xml: Premature end of data in tag ruleset line 2\n (77) on line 28,12<\/code><\/pre>\n<p>Ja sinun pit\u00e4isi n\u00e4hd\u00e4 ainakin t\u00e4m\u00e4 kaikki suorituksen j\u00e4lkeen:<\/p>\n<pre><code>$ vendor\/bin\/grumphp run<\/code><\/pre>\n<p>Ennen kuin siirrymme eteenp\u00e4in, meid\u00e4n on teht\u00e4v\u00e4 joitain pieni\u00e4 muutoksia tiedostojen j\u00e4rjest\u00e4miseen. Toisin sanoen meid\u00e4n on erotettava ydinlaajennustiedosto (joka meill\u00e4 on nimell\u00e4 <strong>Plugin.php<\/strong>) kahdeksi tiedostoksi.<\/p>\n<p>Tarkemmin sanottuna meill\u00e4 on oltava laajennuksen bootstrap-tiedosto, ja sitten meid\u00e4n on yll\u00e4pidett\u00e4v\u00e4 laajennustiedostoa. Joten ensin luodaan plugin bootstrap.<\/p>\n<h3>Luo Bootstrap<\/h3>\n<p>Luo laajennuksen juureen tiedosto nimelt\u00e4 <strong>wordpress-widget-boilerplate.php.<\/strong> Lis\u00e4\u00e4 sitten <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/dce6bda0d104192a21cb06dc7d3ca23c#file-01-wordpress-widget-boilerplate-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">siihen seuraava<\/a><\/strong> :<\/p>\n<pre><code>&lt;?php\n\/**\n * WordPress Widget Boilerplate\n *\n * The WordPress Widget Boilerplate is an organized, maintainable boilerplate for building widgets using WordPress best practices.\n *\n * @package   Widget_Name\n * @author    Your Name &lt;email@example.com&gt;\n * @license   GPL-2.0+\n * @link      http:\/\/example.com\n * @copyright 2018 Your Name or Company Name\n *\n * @wordpress-plugin\n * Plugin Name:       @TODO\n * Plugin URI:        @TODO\n * Description:       @TODO\n * Version:           1.0.0\n * Author:            @TODO\n * Author URI:        @TODO\n * Text Domain:       widget-name\n * License:           GPL-3.0+\n * License URI:       http:\/\/www.gnu.org\/licenses\/gpl-3.0.txt\n * Domain Path:       \/lang\n * GitHub Plugin URI: https:\/\/github.com\/&lt;owner&gt;\/&lt;repo&gt;\n *\/\n\n\/\/ Prevent this file from being called directly.\ndefined('WPINC') || die;\n\n\/\/ Include the autoloader.\nrequire_once __DIR__. '\/inc\/autoload.php';\n<\/code><\/pre>\n<p>Huomautus yll\u00e4 olevassa tiedostossa; meill\u00e4 on laajennuksen otsikko, ehdollinen m\u00e4\u00e4ritt\u00e4m\u00e4\u00e4n, voidaanko tiedostoa k\u00e4ytt\u00e4\u00e4, ja sitten ladataan Composerin automaattinen lataus.<\/p>\n<h3>Muokkaa Core Plugin -laajennusta<\/h3>\n<p>Kun t\u00e4m\u00e4 on tehty, t\u00e4m\u00e4 muuttaa ydin <strong>Plugin.php-<\/strong> tiedoston n\u00e4ytt\u00e4m\u00e4\u00e4n <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/dce6bda0d104192a21cb06dc7d3ca23c#file-02-plugin-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">t\u00e4lt\u00e4:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\n\n\/\/ TODO: change 'Widget_Name' to the name of your plugin\nclass Widget_Name extends WP_Widget {\n\n    \/**\n     * @TODO - Rename \"widget-name\" to the name your your widget\n     *\n     * Unique identifier for your widget.\n     *\n     *\n     * The variable name is used as the text domain when internationalizing strings\n     * of text. Its value should match the Text Domain file header in the main\n     * widget file.\n     *\n     * @since    1.0.0\n     *\n     * @var      string\n     *\/\n    protected $widget_slug = 'widget-name';\n\n    \/*--------------------------------------------------*\/\n    \/* Constructor\n    \/*--------------------------------------------------*\/\n\n    \/**\n     * Specifies the classname and description, instantiates the widget,\n     * loads localization files, and includes necessary stylesheets and JavaScript.\n     *\/\n    public function __construct() {\n\n        \/\/ load plugin text domain\n        add_action( 'init', array( $this, 'widget_textdomain') );\n\n        \/\/ TODO: update description\n        parent::__construct(\n            $this-&gt;get_widget_slug(),\n            __( 'Widget Name', $this-&gt;get_widget_slug() ),\n            array(\n                'classname'  =&gt; $this-&gt;get_widget_slug().'-class',\n                'description' =&gt; __( 'Short description of the widget goes here.', $this-&gt;get_widget_slug())) );\n\n        \/\/ Register admin styles and scripts\n        add_action( 'admin_print_styles', array( $this, 'register_admin_styles') );\n        add_action( 'admin_enqueue_scripts', array( $this, 'register_admin_scripts') );\n\n        \/\/ Register site styles and scripts\n        add_action( 'wp_enqueue_scripts', array( $this, 'register_widget_styles') );\n        add_action( 'wp_enqueue_scripts', array( $this, 'register_widget_scripts') );\n\n        \/\/ Refreshing the widget's cached output with each new post\n        add_action( 'save_post',    array( $this, 'flush_widget_cache') );\n        add_action( 'deleted_post', array( $this, 'flush_widget_cache') );\n        add_action( 'switch_theme', array( $this, 'flush_widget_cache') );\n\n    } \/\/ end constructor\n\n    \/**\n     * Return the widget slug.\n     *\n     * @since    1.0.0\n     *\n     * @return    Plugin slug variable.\n     *\/\n    public function get_widget_slug() {\n        return $this-&gt;widget_slug;\n    }\n\n    \/*--------------------------------------------------*\/\n    \/* Widget API Functions\n    \/*--------------------------------------------------*\/\n\n    \/**\n     * Outputs the content of the widget.\n     *\n     * @param array args  The array of form elements\n     * @param array instance The current instance of the widget\n     *\/\n    public function widget( $args, $instance) {\n\n        \/\/ Check if there is a cached output\n        $cache = wp_cache_get( $this-&gt;get_widget_slug(), 'widget' );\n\n        if (!is_array( $cache)) $cache = array();\n\n        if (! isset ($args['widget_id'])) $args['widget_id'] = $this-&gt;id;\n\n        if (isset ($cache[ $args['widget_id'] ])) return print $cache[ $args['widget_id'] ];\n\n        \/\/ go on with your widget logic, put everything into a string and \u2026\n\n        extract( $args, EXTR_SKIP );\n\n        $widget_string = $before_widget;\n\n        \/\/ TODO: Here is where you manipulate your widget's values based on their input fields\n        ob_start();\n        include( plugin_dir_path( __FILE__ ). 'views\/widget.php' );\n        $widget_string .= ob_get_clean();\n        $widget_string .= $after_widget;\n\n        $cache[ $args['widget_id'] ] = $widget_string;\n\n        wp_cache_set( $this-&gt;get_widget_slug(), $cache, 'widget' );\n\n        print $widget_string;\n\n    } \/\/ end widget\n\n    public function flush_widget_cache()\n    {\n        wp_cache_delete( $this-&gt;get_widget_slug(), 'widget' );\n    }\n    \/**\n     * Processes the widget's options to be saved.\n     *\n     * @param array new_instance The new instance of values to be generated via the update.\n     * @param array old_instance The previous instance of values before the update.\n     *\/\n    public function update( $new_instance, $old_instance) {\n\n        $instance = $old_instance;\n\n        \/\/ TODO: Here is where you update your widget's old values with the new, incoming values\n\n        return $instance;\n\n    } \/\/ end update\n\n    \/**\n     * Generates the administration form for the widget.\n     *\n     * @param array instance The array of keys and values for the widget.\n     *\/\n    public function form( $instance) {\n\n        \/\/ TODO: Define default values for your variables\n        $instance = wp_parse_args(\n            (array) $instance\n        );\n\n        \/\/ TODO: Store the values of the widget in their own variable\n\n        \/\/ Display the admin form\n        include( plugin_dir_path(__FILE__). 'views\/admin.php' );\n\n    } \/\/ end form\n\n    \/*--------------------------------------------------*\/\n    \/* Public Functions\n    \/*--------------------------------------------------*\/\n\n    \/**\n     * Loads the Widget's text domain for localization and translation.\n     *\/\n    public function widget_textdomain() {\n\n        \/\/ TODO be sure to change 'widget-name' to the name of *your* plugin\n        load_plugin_textdomain( $this-&gt;get_widget_slug(), false, dirname( plugin_basename( __FILE__) ). 'lang\/' );\n\n    } \/\/ end widget_textdomain\n\n    \/**\n     * Fired when the plugin is activated.\n     *\n     * @param  boolean $network_wide True if WPMU superadmin uses \"Network Activate\" action, false if WPMU is disabled or plugin is activated on an individual blog.\n     *\/\n    public static function activate( $network_wide) {\n        \/\/ TODO define activation functionality here\n    } \/\/ end activate\n\n    \/**\n     * Fired when the plugin is deactivated.\n     *\n     * @param boolean $network_wide True if WPMU superadmin uses \"Network Activate\" action, false if WPMU is disabled or plugin is activated on an individual blog\n     *\/\n    public static function deactivate( $network_wide) {\n        \/\/ TODO define deactivation functionality here\n    } \/\/ end deactivate\n\n    \/**\n     * Registers and enqueues admin-specific styles.\n     *\/\n    public function register_admin_styles() {\n\n        wp_enqueue_style( $this-&gt;get_widget_slug().'-admin-styles', plugins_url( 'css\/admin.css', __FILE__) );\n\n    } \/\/ end register_admin_styles\n\n    \/**\n     * Registers and enqueues admin-specific JavaScript.\n     *\/\n    public function register_admin_scripts() {\n\n        wp_enqueue_script( $this-&gt;get_widget_slug().'-admin-script', plugins_url( 'js\/admin.js', __FILE__ ), array('jquery') );\n\n    } \/\/ end register_admin_scripts\n\n    \/**\n     * Registers and enqueues widget-specific styles.\n     *\/\n    public function register_widget_styles() {\n\n        wp_enqueue_style( $this-&gt;get_widget_slug().'-widget-styles', plugins_url( 'css\/widget.css', __FILE__) );\n\n    } \/\/ end register_widget_styles\n\n    \/**\n     * Registers and enqueues widget-specific scripts.\n     *\/\n    public function register_widget_scripts() {\n\n        wp_enqueue_script( $this-&gt;get_widget_slug().'-script', plugins_url( 'js\/widget.js', __FILE__ ), array('jquery') );\n\n    } \/\/ end register_widget_scripts\n\n} \/\/ end class\n\n\/\/ TODO: Remember to change 'Widget_Name' to match the class name definition\nadd_action( 'widgets_init', create_function( '', 'register_widget(\"Widget_Name\");') );\n\n\/\/ Hooks fired when the Widget is activated and deactivated\n\/\/ TODO: Remember to change 'Widget_Name' to match the class name definition\nregister_activation_hook( __FILE__, array( 'Widget_Name', 'activate') );\nregister_deactivation_hook( __FILE__, array( 'Widget_Name', 'deactivate') );\n<\/code><\/pre>\n<p>Muista, ett\u00e4 meid\u00e4n on viel\u00e4 teht\u00e4v\u00e4 paljon ty\u00f6t\u00e4, mutta ensimm\u00e4inen asia, joka meid\u00e4n on teht\u00e4v\u00e4, on aloittaa koodikannan puhdistaminen nykyisest\u00e4 tilastaan. Lopulta muokkaamme t\u00e4m\u00e4n paljon oliokeskeisemm\u00e4ksi, mutta meid\u00e4n on saatava laajennuksen nykyinen versio kunnossa.<\/p>\n<p>Nyt voimme kuitenkin k\u00e4\u00e4nt\u00e4\u00e4 huomiomme takaisin GrumPHP:n alkuper\u00e4iseen tuotteeseen. Jos katsot l\u00e4pi, tulosteen n\u00e4et seuraavanlaisen rivin:<\/p>\n<pre><code>You can fix all errors by running following commands:\n'\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/php-cs-fixer' '--allow-risky=yes' '--config=.php_cs.dist' '--using-cache=yes' '--verbose' 'fix'<\/code><\/pre>\n<p>Joten t\u00e4ss\u00e4 vaiheessa tarkastellaan suositellun komennon suorittamista ja katsotaan mit\u00e4 tapahtuu. Kirjoita t\u00e4m\u00e4 terminaaliin:<\/p>\n<pre><code>'\/Users\/tommcfarlin\/Dropbox\/Projects\/trunk\/wp-content\/plugins\/WordPress-Widget-Boilerplate\/vendor\/bin\/php-cs-fixer' '--allow-risky=yes' '--config=.php_cs.dist' '--using-cache=yes' '--verbose' 'fix'<\/code><\/pre>\n<p>Olettaen, ett\u00e4 kaikki asiat toimivat oikein, sinun pit\u00e4isi n\u00e4hd\u00e4 jotain t\u00e4m\u00e4n kaltaista:<\/p>\n<h4>Huomautus tulostusvirheist\u00e4<\/h4>\n<p>Jos saat virheilmoituksen aina kun teet t\u00e4m\u00e4n, sinun on ehk\u00e4 p\u00e4ivitett\u00e4v\u00e4 <strong>toimittajahakemisto<\/strong> tai jopa p\u00e4ivitett\u00e4v\u00e4 hakemisto. Jos n\u00e4in on, kokeile ensin t\u00e4t\u00e4:<\/p>\n<pre><code>$ composer update<\/code><\/pre>\n<p>Ja jos se ei ratkaise ongelmaasi, kokeile:<\/p>\n<pre><code>$ rm -rf vendor\n$ composer update<\/code><\/pre>\n<p>Suorita sen j\u00e4lkeen komento uudelleen.<\/p>\n<h3>Takaisin ulostuloon<\/h3>\n<p>Sinun pit\u00e4isi sitten n\u00e4hd\u00e4 t\u00e4m\u00e4n kaltainen tulos:<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-161324-61e71fbbbfefa.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-161324-61e71fbbbfefa.png\" alt=\"WordPress-widgetit: Refaktorointi, osa 2\"><\/a><\/p>\n<p>Suorita seuraavaksi seuraava komento p\u00e4\u00e4tteess\u00e4si:<\/p>\n<pre><code>$ vendor\/grumphp\/run<\/code><\/pre>\n<p>T\u00e4ss\u00e4 sinun pit\u00e4isi nyt n\u00e4hd\u00e4 ongelmia koodausstandardien kanssa. Luettelo on liian pitk\u00e4 lueteltavaksi t\u00e4ss\u00e4, mutta sinun pit\u00e4isi n\u00e4hd\u00e4 vaihtoehto tehd\u00e4 jotain <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/dce6bda0d104192a21cb06dc7d3ca23c#file-03-coding-standards-txt\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">t\u00e4llaista:<\/a><\/strong><\/p>\n<pre><code>----------------------------------------------------------------------\nFOUND 9 ERRORS AFFECTING 8 LINES\n----------------------------------------------------------------------<\/code><\/pre>\n<p>Ja t\u00e4ss\u00e4 vaiheessa meid\u00e4n on teht\u00e4v\u00e4 paljon muutoksia, jos haluamme saattaa sen PSR2-standardien mukaiseksi. Joten tehd\u00e4\u00e4n se nyt.<\/p>\n<h3>Widget-kattilalevyn refaktorointi<\/h3>\n<p>Olettaen, ett\u00e4 sinulla on kaikki tarvittavat laajennukset ja lis\u00e4osat asennettuna Visual Studio Codessa, n\u00e4et todenn\u00e4k\u00f6isesti melko paljon punaista IDE:ss\u00e4si.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-161324-61e71fbfb62de.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-161324-61e71fbfb62de.png\" alt=\"WordPress-widgetit: Refaktorointi, osa 2\"><\/a><\/p>\n<p>N\u00e4m\u00e4 ovat kaikki ongelmia, jotka on korjattava. Joten aion k\u00e4yd\u00e4 l\u00e4pi ja p\u00e4ivitt\u00e4\u00e4 koodin. Sitten jaan koodin t\u00e4nne (ilman kommentteja tilans\u00e4\u00e4st\u00f6n vuoksi).<\/p>\n<p>Olettaen, ett\u00e4 olet tehnyt kaikki oikeat muutokset, sinulla pit\u00e4isi olla jotain <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/dce6bda0d104192a21cb06dc7d3ca23c#file-04-wordpress-widget-boilerplate-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">t\u00e4m\u00e4n kaltaista:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\n\nnamespace WordPressWidgetBoilerplate;\n\nclass Plugin extends WP_Widget\n{\n    protected $widgetSlug = 'widget-name';\n\n    public function __construct()\n    {\n        add_action('init', [$this, 'widgetTextdomain']);\n\n        parent::__construct(\n            $this-&gt;getWidgetSlug(),\n            __('Widget Name', $this-&gt;getWidgetSlug()),\n            [\n                'classname' =&gt; $this-&gt;getWidgetSlug().'-class',\n                'description' =&gt; __('Short description of the widget goes here.', $this-&gt;getWidgetSlug()),\n            ]\n        );\n\n        add_action('admin_print_styles', [$this, 'registerAdminStyles']);\n        add_action('admin_enqueue_scripts', [$this, 'registerAdminScripts']);\n\n        add_action('wp_enqueue_scripts', [$this, 'registerWidgetStyles']);\n        add_action('wp_enqueue_scripts', [$this, 'registerWidgetScripts']);\n\n        add_action('save_post', [$this, 'flushWidgetCache']);\n        add_action('deleted_post', [$this, 'flushWidgetCache']);\n        add_action('switch_theme', [$this, 'flushWidgetCache']);\n    }\n\n    public function getWidgetSlug()\n    {\n        return $this-&gt;widgetSlug;\n    }\n\n    public function widget($args, $instance)\n    {\n        \/\/ Check if there is a cached output\n        $cache = wp_cache_get($this-&gt;getWidgetSlug(), 'widget');\n\n        if (!is_array($cache)) {\n            $cache = [];\n        }\n\n        if (!isset($args['widget_id'])) {\n            $args['widget_id'] = $this-&gt;id;\n        }\n\n        if (isset($cache[$args['widget_id']])) {\n            return print $cache[$args['widget_id']];\n        }\n\n        extract($args, EXTR_SKIP);\n\n        $widgetString = $beforeWidget;\n\n        ob_start();\n        include plugin_dir_path(__FILE__).'views\/widget.php';\n        $widgetString .= ob_get_clean();\n        $widgetString .= $afterWidget;\n\n        $cache[$args['widget_id']] = $widgetString;\n\n        wp_cache_set($this-&gt;getWidgetSlug(), $cache, 'widget');\n\n        echo $widgetString;\n    }\n\n    public function flushWidgetCache()\n    {\n        wp_cache_delete($this-&gt;getWidgetSlug(), 'widget');\n    }\n\n    public function update($newInstance, $oldInstance)\n    {\n        $instance = $oldInstance;\n\n        \/\/ TODO: Here is where you update your widget's old values with the new, incoming values\n\n        return $instance;\n    }\n\n    public function form($instance)\n    {\n        \/\/ TODO: Define default values for your variables\n        $instance = wp_parse_args(\n            (array) $instance\n        );\n\n        \/\/ TODO: Store the values of the widget in their own variable\n\n        \/\/ Display the admin form\n        include plugin_dir_path(__FILE__).'views\/admin.php';\n    }\n\n    public function widgetTextdomain()\n    {\n        \/\/ TODO: be sure to change 'widget-name' to the name of *your* plugin\n        load_plugin_textdomain($this-&gt;getWidgetSlug(), false, dirname(plugin_basename(__FILE__)).'lang\/');\n    }\n\n    public static function activate($networkWide)\n    {\n        \/\/ TODO: define activation functionality here\n    }\n\n    public static function deactivate($networkWide)\n    {\n        \/\/ TODO:define deactivation functionality here\n    }\n\n    public function registerAdminStyles()\n    {\n        wp_enqueue_style($this-&gt;getWidgetSlug().'-admin-styles', plugins_url('css\/admin.css', __FILE__));\n    }\n\n    public function registerAdminScripts()\n    {\n        wp_enqueue_script($this-&gt;getWidgetSlug().'-admin-script', plugins_url('js\/admin.js', __FILE__), ['jquery']);\n    }\n\n    public function registerWidgetStyles()\n    {\n        wp_enqueue_style($this-&gt;getWidgetSlug().'-widget-styles', plugins_url('css\/widget.css', __FILE__));\n    }\n\n    public function registerWidgetScripts()\n    {\n        wp_enqueue_script($this-&gt;getWidgetSlug().'-script', plugins_url('js\/widget.js', __FILE__), ['jquery']);\n    }\n}\n<\/code><\/pre>\n<p>Suorita viel\u00e4 kerran:<\/p>\n<pre><code>$ vendor\/bin\/grumphp run<\/code><\/pre>\n<p>Ja katso mit\u00e4 tulosta saat. Saat silti useita virheit\u00e4, jotka kertovat jotain seuraavista:<\/p>\n<blockquote>\n<p>V\u00e4lt\u00e4 k\u00e4ytt\u00e4m\u00e4tt\u00f6mi\u00e4 paikallisia muuttujia, kuten\u2026<\/p>\n<\/blockquote>\n<p>T\u00e4m\u00e4 johtuu siit\u00e4, ett\u00e4 koodin nuuskimiss\u00e4\u00e4nn\u00f6t eiv\u00e4t halua meid\u00e4n k\u00e4ytt\u00e4v\u00e4n muuttujia, joita ei k\u00e4ytet\u00e4. kuitenkin, kattilalevyss\u00e4 aiomme todenn\u00e4k\u00f6isesti k\u00e4ytt\u00e4\u00e4 n\u00e4it\u00e4 muuttujia ennen projektin loppua.<\/p>\n<p>Siksi siit\u00e4 ei tarvitse huolehtia t\u00e4ss\u00e4 vaiheessa. Hoidamme sen, kun sen aika on.<\/p>\n<h2>PSR:\u00e4\u00e4n asti<\/h2>\n<p>T\u00e4ss\u00e4 vaiheessa suuri osa laajennuksesta on ostettu PSR-standardien mukaisesti, ja niill\u00e4 on ollut vankka ty\u00f6kaluvalikoima, jota voimme k\u00e4ytt\u00e4\u00e4 koodimme jatkuvaan testaamiseen sit\u00e4 kirjoitettaessa.<\/p>\n<p>Jos seuraat arkistoa, <strong><a href=\"https:\/\/github.com\/tommcfarlin\/WordPress-Widget-Boilerplate\/tree\/develop\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">kehityshaara<\/a><\/strong> on p\u00e4ivitetty vastaamaan t\u00e4m\u00e4n viestin muutoksia, joten ved\u00e4 se ja tarkista koodi.<\/p>\n<p>Seuraavassa viestiss\u00e4 alamme muokata koodia paljon oliokeskeisemm\u00e4ll\u00e4 tavalla.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Katsotaanpa virheit\u00e4, joita koodin haistaja heitt\u00e4\u00e4 WordPress Widget Boilerplatelle, ja katsotaan, emmek\u00f6 pysty saamaan sit\u00e4 nykyaikaisempien standardien mukaisiksi.<\/p>\n","protected":false},"author":1,"featured_media":236238,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[719,895,843,803,864],"tags":[1166],"class_list":["post-231266","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kehittaejae","category-koodi","category-opetusohjelmia","category-php-5","category-wordpress-5","tag-affiai-fi"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/posts\/231266","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/comments?post=231266"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/posts\/231266\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/media\/236238"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/media?parent=231266"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/categories?post=231266"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/tags?post=231266"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}