2
    if ( cpmb_is_valid_mp3( $_FILES['video-url']['name'] ) ) {

            $response = wp_upload_bits( $_FILES['video-url']['name'], null, file_get_contents( $_FILES['video-url']['tmp_name'] ) );

            if ( 0 == strlen ( trim( $response['error'] ) ) ) {
                update_post_meta( $post_id, 'mp3', $response['url'] );
            }

        // Otherwise, mark this as an invalid file
        } else {
            update_post_meta( $post_id, 'mp3', 'invalid-file-type' );
        }

The above is a part of code from a plugin. Then here comes the function

function cpmb_is_valid_mp3( $filename ) {

    $path_parts = pathinfo( $filename );
    return 'mp3' == strtolower( $path_parts['extension'] );

}

Let me tell you what I understand: If it is validated that file is .mp3 then execute the code?

QUESTION: Can someone help me to create such validations for a "URL"?

I have tried like this →

if ( cpmb_is_valid_url( $_REQUEST['video-url']['name'] ) ) {

   Some code is executed here.

}

But I have no idea how to write this function →

cpmb_is_valid_url
  • what part of the url are you trying to validate/confirm exists? Or are you trying to confirm it is a url at all? (also this will probably fall under a general php type question, fyi) – hwl Jul 29 '17 at 17:20
  • Input by the admin/author of the post in the metabox such youtube, vimeo URL. – The WP Intermediate Jul 29 '17 at 17:22
  • should I paste the code for MP3? – The WP Intermediate Jul 29 '17 at 17:27
3

I would look into PHP's parse_url() and/or filter_var() with FILTER_VALIDATE_URL filter. parse_url() gives you a bit more control. Combine that with a sanitization as mentioned at the end.

Here are couple use cases that will hopefully give you a better idea on how to proceed:


If you want to verify that the url's domain is of an approved site:

function url_allowed( $url ) {

        $allowed_hosts = array(
                        'youtube.com',
                        'vimeo.com'
                        ); 
        if ( in_array( parse_url( $url, PHP_URL_HOST ), $allowed_hosts ) ) {
            return true;
        }

        return false;      
    }

Then pass it the url to check within your conditional:

if ( url_allowed( $value_of_url_to_check_wherever_you_are_getting_it ) ) {
    //do stuff
}

If you just want to confirm it is a url at all (which will include ftp://, etc., btw),

if ( filter_var( $url, FILTER_VALIDATE_URL ) ) {
    //do stuff
}

If you would like to only allow urls beginning with http or https,

if ( parse_url( $url, PHP_URL_SCHEME ) == 'http' || parse_url( $url, PHP_URL_SCHEME ) == 'https' ) {
    //do stuff
}

I would also recommended sanitizing the url either via the WordPress esc_url() or php's filter_var( $url, FILTER_SANITIZE_URL )


Edit: Using WP's wp_parse_url()

WordPress provides a wrapper for PHP's parse_url(): wp_parse_url(). It returns an array of 'scheme', 'host', and 'path'. Usage is the same as above:

function url_allowed( $url ) {

        $allowed_hosts = array(
                        'youtube.com',
                        'vimeo.com'
                        );
        $url_array = wp_parse_url($url); 
        if ( in_array( $url_array['host'], $allowed_hosts ) ) {
            return true;
        }

        return false;      
    }

Additionally, the WordPress function wp_allowed_protocols() returns a default list of protocols you could check against:

  array( 'http', 
         'https', 
         'ftp', 
         'ftps', 
         'mailto', 
         'news', 
         'irc', 
         'gopher', 
         'nntp', 
         'feed', 
         'telnet', 
         'mms', 
         'rtsp', 
         'svn', 
         'tel', 
         'fax', 
         'xmpp', 
         'webcal', 
         'urn' 
    )

You can filtered this list with the hook kses_allowed_protocols. In example, removing the mailto protocol may go something like this:

add_filter( 'kses_allowed_protocols', 'my_protocols' );
function my_protocols( $protocols ) {

    if( ($key = array_search( 'mailto', $protocols ) ) !== false ) {    
        unset( $protocols[ $key ] );
    }
}

Do note that this approved protocol list is used by _links_add_base(), edit_user() (for the user url field), wp_kses(), wp_kses_one_attr(), and esc_url().

I would contend it is better to explicitly check the intended protocol of the input field rather than just checking it against this array.


A more complete usage case

Since your usage is to allow users to input urls from specific sites, and in both cases these video urls are served using protocol https, I would check for the site host and force the protocol, and use esc_url() to clean up characters.

Since the end result will require you to know whether the url is from Vimeo or YouTube, you could save that as well.

check against allowed hosts, used by url_verify()

function url_allowed_host( $host ) {

    $allowed_hosts = array(
                    'youtube.com',
                    'vimeo.com'
                    );

    if ( in_array( $host, $allowed_hosts ) ) {
        return true;
    }

    return false;      
}

parse entered url, force https, verify allowed host, create and return array of values

   function url_verify( $url ) {

        $url_array = wp_parse_url( $url );

        if ( $url_array['scheme'] !== 'https' ) {

            $url_array['scheme'] = 'https';
        }

        if ( url_allowed_host( $url_array['host'] ) ) {

            //lets ditch the .com
            $host_word = explode( '.', $url_array['host'] );

            //this should now be just "youtube" or "vimeo"
            $meta_array['host'] = $host_word;
            $meta_array['url']  = $url_array['scheme'] . $url_array['host'] . $url_array['path'];

            return $meta_array;

       } else {

        return false;

       }

   } 

Save the array with url and url host name

  add_action( 'save_post', 'my_meta_save', 10, 2 );

  function my_meta_save( $post_id, $post ) {
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
            return;
        }
    //do nonce check here

    //assuming form field is named: video-url, make sure it is set and not empty AND that url_verify did not return false
    if ( ( isset( $_POST['video-url'] ) && ! empty( $_POST['video-url'] ) ) && ( false !== url_verify( $_POST['video-url'] ) ) ) {


        update_post_meta( $post_id, 'video_url', esc_url( $POST['video_url'] ) );

    }
    //if any of the above are not true, treat it as blank and delete existing value
    else {

        delete_post_meta( $post_id, 'video-url' );
    }    


  }

Retrieve the values

$video_meta = get_post_meta( $post_id, 'video-url', false );
$url = esc_url( $video_meta['url'] );
$host = santize_text_field( $video_meta['host'] );

Displaying something conditionally per host

I use a switch here in case you have a longer list of allowed domains.

switch ( $host ) {
    case "youtube":
        //do some youtube stuff
        break;

    case "vimeo":
        //do some vimeo stuff
        break;
}
| improve this answer | |
  • I have a question since you have restricted the url only from youtube and Vimeo so I think just validating if it is a URL is enough Isn't it? secondly, you have given a wonderful solution aren't we using core php functions whereas WordPress functions can be used there? – The WP Intermediate Jul 29 '17 at 18:29
  • as far as validation of user input goes, I would be as specific to the expected entry as you can. If the end result can only handle certain sources (i.e. youtube, vimeo, etc.) I would force their usage. Same with http or https. I am unaware of any wordpress function(s) that perform url parsing, even as wrappers for parse_url(), but they may exist. You can definitely handle sanitization via WP's esc_url(). – hwl Jul 29 '17 at 18:48
  • sir, I need a little more favor from you. can you also help me in writing //do stuff especially then the part that I have outlined in the red-box → screencast.com/t/su9ivuUOU I am building it from by seeing a plugin that has done this for mp3. – The WP Intermediate Jul 29 '17 at 18:57
  • that bit would part of a save_meta_boxes() type function that is hooked to save_post for saving the values of the meta box's form fields when the post is saved/update. Swap their use of $_FILES for $_POST and it will look more familiar. – hwl Jul 29 '17 at 19:07
  • 1
    the data from the form fields will be present in $_POST upon submitting the form. You're posting that data to the server, so in the interests of disambiguation I would use $_POST here. – hwl Jul 29 '17 at 19:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.