Linux secure copy scp command examples

What is secure copy (scp)?

`scp` allows we can copy files to, from or between different hosts. It uses `ssh` for data transfer.

You are properly familiar with using `cp`  command to copy files or directory on your local machine. `scp` is pretty similar. The only different thing is you can push files to a host or pull files from a host to local or pull, push files between the hosts.

scp examples

Copy a file from a remote host to the local host

`scp username@remote_host:<path_to_file> /path/to/local/directory`

username: your hosting user name

remote_host: host IP or domain name

<path_to_file>: path to your file which you want to get on remote host

/path/to/local/directory: path to directory which contains the file on remote host

Copy a file from the local host to a remote host

It is reverse of copy file from remote host to local host

`scp /path/to/file username@remote_host:<path_to_directory>`

/path/to/file: path to file on local host

username: your host user name

remote_host: hosting IP or domain name

<path_to_directory>: path to directory which holds the file on local host

Copy a directory from local host to a remote host’s directory

`scp -r /path/to/directory username@remote_host:<path_to_directory>`

Copy a file from remote host Foo to remote host Bar

`scp username@Foo_remote_host:<path_to_file> username@Bar_remote_host:<path_to_directory>`

Copy multiple files from local host to remote host

`scp /path/to/foo.txt /path/to/bar.txt username@remote_host:<path_to_directory>`

Copy multiple files from remote to local host

scp username@remote_host:<path_to_directory>/\{foo.txt,bar.txt\} /path/to/directory

Copy a file from local host to remote host with port number

`scp -P <port_number> /path/to/file username@remote_host:<path_to_directory>`

 

How to activate comments form on custom post type

Sometimes after you register a custom post type. You return single page and you did not see the comments form there. Although you used comment_form() or comments_template() function in your template file. The excuse for this maybe you forgot define `comments` option for `supports` when you register post type or the `comment_status` field was set to 0 somehow or maybe it just was disabled on admin.

Check your register post type argument

Add `comments` to `supports` arguments when you register post type `’supports’ => [‘title’, ‘author’, ‘editor’, ‘thumbnail’, ‘comments’]`

Set comment_status of post type to open

You can force all comment_status of post of custom post type to `open` by use wp_insert_post_data filter.

if (!function_exists('activeCommentForBar')) {
    /**
     * callback function
     * 
     * @since 1.3.4
     * @param  array $data
     * @rteurn array $data
     */
    function activeCommentForBar($data)
    {
        $cpts = ['post', 'cpt-1', 'cpt-2'];
        
        if (in_array($data['post_type'], $cpts)) {
            $data['comment_status'] = 'open';
        }
    
        return $data;
    }
    
    add_filter('wp_insert_post_data', 'activeCommentForBar');
}

Enable comments option in the Settings page

You should go to Settings → Discussion to check “Allow people to post comments on new articles” option. If it is uncheck, check it and save.

Hope this small tut helps you.

How to add profile fields in Spark

Modify the view

Note: This article supposes you have create a column or table to store new profile field values. You can see https://laravel.com/docs/5.4/migrations for how to use migrations in laravel

First thing you need to do is create a new view to display your new profile fields. We add a new blade to `/resources/views/vendor/spark/settings/profile.blade.php` file to load a new `user-address` template.

<spark-profile :user="user" inline-template>
    <div>
        <!-- Update Profile Photo -->
        @include('spark::settings.profile.update-profile-photo')

        <!-- Update Contact Information -->
        @include('spark::settings.profile.update-contact-information')

        <!-- User Address -->
        @include('spark::user-address')
    </div>
</spark-profile>

Write `user-address` template

The `@include` directive will load a new blade template which contains our custom panel. Create file `user-address.blade.php` in `/resources/views/settings/profile/`. This template will contain a simple form which holds our fields.

<user-address :user="user" inline-template>
    <div class="panel panel-default">
        <div class="panel-heading">User Address</div>

        <div class="panel-body">
            <!-- Success Message -->
            <div class="alert alert-success" v-if="form.successful">
                Your address information has been updated!
            </div>

            <form class="form-horizontal" role="form">
                <!-- Address -->
                <div class="form-group" :class="{'has-error': form.errors.has('address')}">
                    <label class="col-md-4 control-label">Age</label>

                    <div class="col-md-6">
                        <input type="text" class="form-control" name="address" v-model="form.address">

                        <span class="help-block" v-show="form.errors.has('address')">
                            @{{ form.errors.get('address') }}
                        </span>
                    </div>
                </div>

                <!-- Update Button -->
                <div class="form-group">
                    <div class="col-md-offset-4 col-md-6">
                        <button type="submit" class="btn btn-primary"
                                @click.prevent="update"
                                :disabled="form.busy">

                            Update
                        </button>
                    </div>
                </div>
            </form>
        </div>
    </div>
</user-address>

Note: `user-address` is Vue component name which we will define in next step.

Create vue component

Next, we will define the new `user-address` Vue component which will manage our new panel and form. We can define this `user-address.js`  at `/resources/assets/js/components/settings/profile/`

Vue.component('user-address', {
    props: ['user'],

    data() {
        return {
            form: new SparkForm({
                address: ''
            })
        };
    },

    mounted() {
        this.form.address = this.user.address;
    },

    methods: {
        update() {
            Spark.put('/settings/profile/user_address', this.form)
                .then(response => {
                    Bus.$emit('updateUser');
                });
        }
    }
});

Note that `/settings/profile/user_address` is route name which define in `app/app.php`. `user-address` is Vue component name

Then, we have to instruct it to compile the component into main script `app.js` file. You can do this by adding a line to `/resources/assets/js/components/bootstrap.js` line

require('./home');

// Load the new Vue component...
require('./settings/profile/user-address');

Note: After you define the new component and instruct it to `app.js` remember run `gulp` command to re-compile your Javascript.

Validation & Storage

Finally, we need to define a route and controller to handle updating for an existing user.

First, we create a route at `route/web.php`

Route::put('/settings/profile/user_address', 'UserAddressController@update');

Remember the route name `settings/profile/user_address` must matches with the route name you defined in Vue component before.

Once, the route has been defined, we can define the controller in `app/Http/Controllers/UserAddressController.php`

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserAddressController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Update the user's profile details.
     *
     * @return Response
     */
    public function update(Request $request)
    {
        $this->validate($request, [
            'address' => 'required',
        ]);

        $request->user()->forceFill([
            'address' => $request->address
        ])->save();
    }
}

Now, you can go to “settings” page to update new address value for user.

How to resolve mysqldump command not found on Mac

I got this problem a few days ago when I tried to dump my database on localhost that using MAMP. It shows me a message that mysqldump command not found.

 

After trying many workaround, I realised we can resolve this problem (on OS X and MAMP) by these solutions:

#1. Using `.bash_profile` file

Open the `.bash_profile`:

sudo nano ~/.bash_profile

Add your directory

export PATH=/Applications/MAMP/Library/bin:$PATH

Close and Open terminal again. Then type `mysqldump` in terminal. You should look like this:

Usage: mysqldump [OPTIONS] database [tables]
OR     mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]
OR     mysqldump [OPTIONS] --all-databases [OPTIONS]

#2. Make an alias of mysqldump in `/Users/bin`

Open the `.bash_profile`:

sudo nano ~/.bash_profile

Add an alias following this code. Change your mysql user and password `-uroot -proot`

alias mysqldump='/Applications/MAMP/Library/bin/mysqldump --host=localhost -uroot -proot'

Save file, close termial, open terminal again and type `mysqldump` to test. You should look these line:

Usage: mysqldump [OPTIONS] database [tables]
OR     mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]
OR     mysqldump [OPTIONS] --all-databases [OPTIONS]

 

How to add icon for special menu item in wordpress

Hello! Today, I got a task that adds custom icon after the text of menu item which has children in WordPress.

menu item

After a while looking for a few plugins, I decide using custom code for this job because I don’t want to load too many plugins on the website. This will slow down the site.

I use Walker_Nav_Menu approach so assume that you know where put wp_nav_menu function in theme source. Commonly, wp_nav_menu function put in header.php.

Note: In case you have no child theme, you should create it to avoid lost your code when the main theme update.

OK. Let’s start.

Add your icon to menu item

First of all, we will create an inheritance of Walker_Nav_Menu class. You can either write the new class in functions.php or in a separate file and require it in functions.php.

I create a file name NavWalker.php. It contains a single class name NavWalker that extends Walker_Nav_Menu class.

class NavWalker extends \Walker_Nav_Menu
{
	public function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0)
	{
		if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
			$t = '';
			$n = '';
		} else {
			$t = "\t";
			$n = "\n";
		}
		$indent = ( $depth ) ? str_repeat( $t, $depth ) : '';

		$classes = empty( $item->classes ) ? array() : (array) $item->classes;
		$classes[] = 'menu-item-' . $item->ID;

		/**
		 * Filters the arguments for a single nav menu item.
		 *
		 * @since 4.4.0
		 *
		 * @param stdClass $args  An object of wp_nav_menu() arguments.
		 * @param WP_Post  $item  Menu item data object.
		 * @param int      $depth Depth of menu item. Used for padding.
		 */
		$args = apply_filters( 'nav_menu_item_args', $args, $item, $depth );

		/**
		 * Filters the CSS class(es) applied to a menu item's list item element.
		 *
		 * @since 3.0.0
		 * @since 4.1.0 The `$depth` parameter was added.
		 *
		 * @param array    $classes The CSS classes that are applied to the menu item's `<li>` element.
		 * @param WP_Post  $item    The current menu item.
		 * @param stdClass $args    An object of wp_nav_menu() arguments.
		 * @param int      $depth   Depth of menu item. Used for padding.
		 */
		$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth ) );
		$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';

		/**
		 * Filters the ID applied to a menu item's list item element.
		 *
		 * @since 3.0.1
		 * @since 4.1.0 The `$depth` parameter was added.
		 *
		 * @param string   $menu_id The ID that is applied to the menu item's `<li>` element.
		 * @param WP_Post  $item    The current menu item.
		 * @param stdClass $args    An object of wp_nav_menu() arguments.
		 * @param int      $depth   Depth of menu item. Used for padding.
		 */
		$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args, $depth );
		$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';

		$output .= $indent . '<li' . $id . $class_names .'>';

		$atts = array();
		$atts['title']  = ! empty( $item->attr_title ) ? $item->attr_title : '';
		$atts['target'] = ! empty( $item->target )     ? $item->target     : '';
		$atts['rel']    = ! empty( $item->xfn )        ? $item->xfn        : '';
		$atts['href']   = ! empty( $item->url )        ? $item->url        : '';

		/**
		 * Filters the HTML attributes applied to a menu item's anchor element.
		 *
		 * @since 3.6.0
		 * @since 4.1.0 The `$depth` parameter was added.
		 *
		 * @param array $atts {
		 *     The HTML attributes applied to the menu item's `<a>` element, empty strings are ignored.
		 *
		 *     @type string $title  Title attribute.
		 *     @type string $target Target attribute.
		 *     @type string $rel    The rel attribute.
		 *     @type string $href   The href attribute.
		 * }
		 * @param WP_Post  $item  The current menu item.
		 * @param stdClass $args  An object of wp_nav_menu() arguments.
		 * @param int      $depth Depth of menu item. Used for padding.
		 */
		$atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );

		$attributes = '';
		foreach ( $atts as $attr => $value ) {
			if ( ! empty( $value ) ) {
				$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
				$attributes .= ' ' . $attr . '="' . $value . '"';
			}
		}

		/** This filter is documented in wp-includes/post-template.php */
		$title = apply_filters( 'the_title', $item->title, $item->ID );

		/**
		 * Filters a menu item's title.
		 *
		 * @since 4.4.0
		 *
		 * @param string   $title The menu item's title.
		 * @param WP_Post  $item  The current menu item.
		 * @param stdClass $args  An object of wp_nav_menu() arguments.
		 * @param int      $depth Depth of menu item. Used for padding.
		 */
		$title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
		
		if ($args->walker->has_children) {
			$args->after = '<i class="fa fa-angle-down" aria-hidden="true"></i>';
		} else {
			$args->after = '';
		}

		$item_output = $args->before;
		$item_output .= '<a'. $attributes .'>';
		$item_output .= $args->link_before . $title . $args->link_after;
		$item_output .= '</a>';
		$item_output .= $args->after;

		/**
		 * Filters a menu item's starting output.
		 *
		 * The menu item's starting output only includes `$args->before`, the opening `<a>`,
		 * the menu item's title, the closing `</a>`, and `$args->after`. Currently, there is
		 * no filter for modifying the opening and closing `<li>` for a menu item.
		 *
		 * @since 3.0.0
		 *
		 * @param string   $item_output The menu item's starting HTML output.
		 * @param WP_Post  $item        Menu item data object.
		 * @param int      $depth       Depth of menu item. Used for padding.
		 * @param stdClass $args        An object of wp_nav_menu() arguments.
		 */
		$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
	}
}

I need to add an icon after the label of the menu item which has children. So I add a snippet to check every menu item.

if ($args->walker->has_children) {
	$args->after = '<i class="fa fa-angle-down" aria-hidden="true"></i>';
} else {
	$args->after = '';
}

Update argument for register menu function

Finally, we need a little change for wp_nav_menu function. We add an argument walker with value is this class name NavWalker.

wp_nav_menu([
	'walker' => new NavWalker,
	'theme_location' => 'main_menu',
	'menu_id'        => 'main_menu',
	'menu_class' => 'nav nav-tabs',
]);

Hope this helpfully.

How to add taxonomy filter to admin list of custom post type

Good morning! Today, I got a task about taxonomy in WordPress. This task asks you have to create a custom taxonomy filter in admin  list. We have many plugins which could finishes this task. However I prefer use custom code because I can control everything and easier to maintain latter.

OK! So let’s start!

Note: you can place your code in `functions.php` file or write it in your plugin.

Step 1. Add a custom taxonomy filter dropdown with its data

I created a taxonomy names destination and assign it for a custom post type name property. In this step, we will use `restrict_manage_posts` filter to create the select box of taxonomy.

add_action('restrict_manage_posts', 'createTaxonomyFilterDropdown');

function createTaxonomyFilterDropdown()
{
	global $typenow;

	$post_type = ['property'];
	$taxonomySlug = 'destination';

	if (in_array($typenow, $post_type)) {

		$selected = isset($_GET[$taxonomySlug]) ? $_GET[$taxonomySlug] : '';
		$taxonomy = get_taxonomy($taxonomySlug);

		wp_dropdown_categories(
			[
				'show_option_all' => __("Show All {$taxonomy->label}"),
				'taxonomy' => $taxonomySlug,
				'name' => $taxonomySlug,
				'orderby' => 'name',
				'selected' => $selected,
				'show_count' => true,
				'hide_empty' => true,
			]
		);
	};
}

I used `get_taxonomy()` function to get information of `destination` taxonomy. And I used `wp_dropdown_categories()` to get all its terms.

`if (in_array($typenow, $post_type)) {…}` the condition clause ensure your code just apply for custom post type `property`.

Step 2. Parse taxonomy filter value to query url

To do this, WordPress produces `parse_query` filter.

add_filter('parse_query', [$this, 'parseTaxonomyValueToQuery']);

function parseTaxonomyValueToQuery($query)
{
	global $pagenow;

	$post_type = ['property'];
	$taxonomySlug = 'destination';

	$queryVars = &$query->query_vars;

	if ($pagenow == 'edit.php' && 
		isset($queryVars['post_type']) && 
		in_array($queryVars['post_type'], $post_type) && 
		isset($queryVars[$taxonomySlug]) && 
		is_numeric($queryVars[$taxonomySlug]) && 
		$queryVars[$taxonomySlug] != 0) {

		$term = get_term_by('id', $queryVars[$taxonomySlug], $taxonomySlug);

		$queryVars[$taxonomySlug] = $term->slug;
	}
}

Hope this help.

 

How to rewrite permalink for custom post type

Hello! Yesterday I got a task about how to custom the permalink of a custom post type in wordpress. The task describes that we have 2 custom post types are property and destination. The goal is convert the permalink of  single property looks like this https://domain.com/destinations/parent-destination/child-destination/.../property-slug.

I spend 2 hours to read about Permalink and Rewrite_API in wordpress. In addition, I used ACF plugin to create relationship between property and destination. Lets start step by step. Ready! Here we go.

Step 1. Create custom post type

Note: you can either place the code into `functions.php` file or create your plugin.

We create 2 custom post types by using `register_post_type` function. Pay your attention on this snippet:

'rewrite'	=>  array(
    'slug' => 'destinations/%path%',
    'with_front' => false
),

`slug` is customize the permalink structure slug.

`with_front` is  the permalink structure be prepended with the front base. We set it to `false` to remove custom post type slug in url.

example: if your permalink structure is /property/, then your links will be: false →/four-seasion-hotel/, true →/property/four-seasion-hotel/.

Register property custom post type

add_action('init', 'registerPropertyPostType');

/**
 * Register a Property post type.
 *
 * @link https://codex.wordpress.org/Function_Reference/register_post_type
 */
function registerPropertyPostType()
{
	$labels = array(
		'name'               => _x( 'Properties', 'post type general name', 'your-plugin-textdomain' ),
		'singular_name'      => _x( 'Property', 'post type singular name', 'your-plugin-textdomain' ),
		'menu_name'          => _x( 'Properties', 'admin menu', 'your-plugin-textdomain' ),
		'name_admin_bar'     => _x( 'Property', 'add new on admin bar', 'your-plugin-textdomain' ),
		'add_new'            => _x( 'Add New', 'Property', 'your-plugin-textdomain' ),
		'add_new_item'       => __( 'Add New Property', 'your-plugin-textdomain' ),
		'new_item'           => __( 'New Property', 'your-plugin-textdomain' ),
		'edit_item'          => __( 'Edit Property', 'your-plugin-textdomain' ),
		'view_item'          => __( 'View Property', 'your-plugin-textdomain' ),
		'all_items'          => __( 'All Properties', 'your-plugin-textdomain' ),
		'search_items'       => __( 'Search Properties', 'your-plugin-textdomain' ),
		'parent_item_colon'  => __( 'Parent Properties:', 'your-plugin-textdomain' ),
		'not_found'          => __( 'No Properties found.', 'your-plugin-textdomain' ),
		'not_found_in_trash' => __( 'No Properties found in Trash.', 'your-plugin-textdomain' )
	);

	$args = array(
		'labels'             => $labels,
                'description'        => __( 'Description.', 'your-plugin-textdomain' ),
		'public'             => true,
		'publicly_queryable' => true,
		'show_ui'            => true,
		'show_in_menu'       => true,
		'query_var'          => true,
		'rewrite'	=>  array(
		    'slug' => 'destinations/%path%',
		    'with_front' => false
		),
		'capability_type'    => 'post',
		'has_archive'        => true,
		'hierarchical'       => false,
		'menu_position'      => null,
		'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' )
	);

	register_post_type( 'property', $args );
}

Next we register destination post type with same code

add_action('init', 'registerDestinationPostType');

/**
 * Register a Destination post type.
 *
 * @link https://codex.wordpress.org/Function_Reference/register_post_type
 */
function registerDestinationPostType()
{
	$labels = array(
		'name'               => _x( 'Destinations', 'post type general name', 'your-plugin-textdomain' ),
		'singular_name'      => _x( 'Destination', 'post type singular name', 'your-plugin-textdomain' ),
		'menu_name'          => _x( 'Destinations', 'admin menu', 'your-plugin-textdomain' ),
		'name_admin_bar'     => _x( 'Destination', 'add new on admin bar', 'your-plugin-textdomain' ),
		'add_new'            => _x( 'Add New', 'Destination', 'your-plugin-textdomain' ),
		'add_new_item'       => __( 'Add New Destination', 'your-plugin-textdomain' ),
		'new_item'           => __( 'New Destination', 'your-plugin-textdomain' ),
		'edit_item'          => __( 'Edit Destination', 'your-plugin-textdomain' ),
		'view_item'          => __( 'View Destination', 'your-plugin-textdomain' ),
		'all_items'          => __( 'All Destinations', 'your-plugin-textdomain' ),
		'search_items'       => __( 'Search Destinations', 'your-plugin-textdomain' ),
		'parent_item_colon'  => __( 'Parent Destinations:', 'your-plugin-textdomain' ),
		'not_found'          => __( 'No Destinations found.', 'your-plugin-textdomain' ),
		'not_found_in_trash' => __( 'No Destinations found in Trash.', 'your-plugin-textdomain' )
	);

	$args = array(
		'labels'             => $labels,
                'description'        => __( 'Description.', 'your-plugin-textdomain' ),
		'public'             => true,
		'publicly_queryable' => true,
		'show_ui'            => true,
		'show_in_menu'       => true,
		'query_var'          => true,
		'rewrite'	=>  array(
            'slug' 			=> 'destinations',
            'with_front' 	=> false
        ),
		'capability_type'    => 'post',
		'has_archive'        => true,
		'hierarchical'       => false,
		'menu_position'      => null,
		'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' )
	);

	register_post_type( 'destination', $args );
}

Step 2. Install ACF plugin and create relationship

I’m using ACf plugin for many projects. It is very helpfully. You can add, remove, manage custom meta field of post type. It has enough field types for you to use. You can download free version on WordPress.org or premium version here.

I create a relationship field of property which reference to destination. It likes foreign key to destination.

rewrite permalink - ACF property meta field

Step 3. Apply new permalink structure to custom post type permalink

In this step, I get destination of property. And then I get all sub-destination of that destination. Join them as a path of the link. Replace `%path%` pattern to this path and returen the link.

add_filter('post_type_link', 'modifySlug', 10, 2);

function modifySlug($link, $post)
{
	$type = get_post_type($post);

	if ($type == 'property') {
		$destinationId = get_post_meta($post->ID, 'destination_property', true);
		$destination = get_post($destinationId);

		$path = array();

		if ($destination->post_parent == 0) {
			array_push($path, $destination->post_name);
		} else {
			$destinationParent = get_post($destination->post_parent);
			array_push($path, $destinationParent->post_name);
			array_push($path, $destination->post_name);
		}

		array_push($path, $type);
		
		$path = implode('/', $path);
		$link = str_replace('%path%', $path, $link);

		return $link;
	}
	
    return $link;
}

Step 4. Add new rewrite permalink rule

After you setup rewrite mode for your custom post type. What you have to do next is add a new rewrite rule to inform to wordpress your change in permalink. You use filter rewrite_rules_array to apply your rules.

add_filter('rewrite_rules_array', 'modifyRewriteRules', 10, 2);
function modifyRewriteRules($rules)
{
    $newRules  = array();
    // test for single property
    $newRules['destinations/.+?/property/(.+)/?$'] = 'index.php?property=$matches[1]';
    return array_merge($newRules, $rules);
}

Step 5. Flush Rewrite Rules

By refresh Settings → Permalink page or use flush_rewrite_rules() function to make effect.

Note: If you use flush_rewrite_rules() function, you have to run it in plugin activate hook or theme setup hook.

Hope it helpfully.