{"id":1132,"date":"2016-11-28T08:22:21","date_gmt":"2016-11-28T08:22:21","guid":{"rendered":"http:\/\/myprojects.advchaweb.com\/?p=1132"},"modified":"2021-11-02T01:25:43","modified_gmt":"2021-11-02T01:25:43","slug":"wordpress-plugin-to-connect-to-upwork-api","status":"publish","type":"post","link":"https:\/\/myprojects.advchaweb.com\/index.php\/2016\/11\/28\/wordpress-plugin-to-connect-to-upwork-api\/","title":{"rendered":"WordPress Plugin to Connect to Upwork API"},"content":{"rendered":"<p>Ref: <a href=\"http:\/\/ieg.wnet.org\/2015\/08\/using-oauth-in-wordpress-plugin-part-1-the-basics\/\" target=\"_blank\" rel=\"noopener noreferrer\">APIS, WORDPRESS TIPS AND TRICKS, USING OAUTH IN WORDPRESS PLUGINS, PART 1: THE BASICS<br \/>\n<\/a>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <a href=\"http:\/\/www.yaconiello.com\/blog\/how-to-write-wordpress-plugin\/\" target=\"_blank\" rel=\"noopener noreferrer\">How to write a WordPress plugin<\/a><\/p>\n<ol>\n<li>Make sure you already registered on Upwork (https:\/\/upwork.com) and have any Upwork key. If not go to https:\/\/developers.upwork.com and get the keys (API Key, API secret, redirect URL, etc). Apply for the API on https:\/\/www.upwork.com\/services\/api\/apply<\/li>\n<li>Go into the plugin directory (\/wp-content\/plugins\/) then create a new directory &#8216;upwork&#8217;. then in the new directory, create a new file &#8216;upwork.php&#8217;<\/li>\n<li>Here is our first content in upwork.php file\n<pre class=\"lang:default decode:true\">&lt;?php\r\n\/*\r\n * Plugin Name: WP Upwork \r\n * Version: 1 \r\n * Plugin URI: http:\/\/advchaweb.com\/\r\n * Description: A plugin to connect to upwork API\r\n * Author: Satria Faestha\r\n * Author URI: http:\/\/advchaweb.com\/\r\n * \r\n * This program is free software: you can redistribute it and\/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n * \r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n * GNU General Public License for more details.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with this program.  If not, see &lt;http:\/\/www.gnu.org\/licenses\/&gt;.\r\n * \r\n *\/\r\n<\/pre>\n<p>From here, we can see the plugin &#8216;Upwork&#8217; in the wordpress admin -&gt; plugin Then please &#8216;Activate&#8217; it.<a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1138\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork.png\" alt=\"wp-plugin-upwork\" width=\"676\" height=\"246\" srcset=\"https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork.png 676w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-300x109.png 300w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px\" \/><\/a><\/li>\n<li>Create a class &#8216;WP_Upwork&#8217; and instantiate it in upwork.php file\n<pre class=\"lang:default decode:true\">if ( ! defined( 'ABSPATH' ) ) exit;\r\n\r\nif(!class_exists('WP_Upwork'))\r\n{\r\n    class WP_Upwork{\r\n        \/**\r\n         * Construct the plugin object\r\n         *\/\r\n        public function __construct()\r\n        {\r\n            \/\/ register actions\r\n        } \/\/ END public function __construct\r\n    \r\n        \/**\r\n         * Activate the plugin\r\n         *\/\r\n        public static function activate()\r\n        {\r\n            \/\/ Do nothing\r\n        } \/\/ END public static function activate\r\n    \r\n        \/**\r\n         * Deactivate the plugin\r\n         *\/     \r\n        public static function deactivate()\r\n        {\r\n            \/\/ Do nothing\r\n        } \/\/ END public static function deactivate\r\n    } \/\/ END class WP_Upwork\r\n} \/\/ END if(!class_exists('WP_Upwork'))\r\n\r\n\/\/Instantiate WP_Upwork class\r\nif(class_exists('WP_Upwork')){\r\n    \/\/ Installation and uninstallation hooks\r\n    register_activation_hook(__FILE__, array('WP_Upwork', 'activate'));\r\n    register_deactivation_hook(__FILE__, array('WP_Upwork', 'deactivate'));\r\n\r\n    \/\/ instantiate the plugin class\r\n    $wp_upwork = new WP_Upwork();\r\n}<\/pre>\n<\/li>\n<li>Add the setting page<br \/>\nTo add the setting page, we need to add actions and callback in constructor of WP_Upwork class.<\/p>\n<pre class=\"lang:default decode:true \">if(!class_exists('WP_Upwork'))\r\n{\r\n    class WP_Upwork{\r\n        \/**\r\n         * Construct the plugin object\r\n         *\/\r\n        public function __construct()\r\n        {\r\n            \/\/ register actions\r\n            \/\/ Register plugin settings\r\n            add_action('admin_init', array(&amp;$this, 'admin_init'));\r\n            \/\/ Add settings page to menu\r\n            add_action('admin_menu', array(&amp;$this, 'add_menu'));\r\n        } \/\/ END public function __construct\r\n    \r\n        ...\r\n    } \/\/ END class WP_Upwork\r\n} \/\/ END if(!class_exists('WP_Upwork'))<\/pre>\n<p>First we set and register the Upwork setting (API Key and Secret) in WP_Upwork class:<\/p>\n<pre class=\"lang:default decode:true \">\/**\r\n * hook into WP's admin_init action hook\r\n *\/\r\npublic function admin_init(){\r\n    \/\/ register your plugin's settings\r\n    register_setting( 'wp_upwork-group', 'wp_upwork_api_key' );\r\n    register_setting( 'wp_upwork-group', 'wp_upwork_api_secret' );\r\n    \/\/ add your settings section\r\n    add_settings_section(\r\n        'wp_upwork-section', \r\n        'Upwork API Settings', \r\n        array( &amp;$this, 'settings_section_wp_upwork'), \r\n        'wp_upwork_settings'\r\n    );\r\n    \/\/ add your setting's fields\r\n    add_settings_field(\r\n        'wp_upwork-api_key', \r\n        'API Key', \r\n        array(&amp;$this, 'settings_field_input_text'), \r\n        'wp_upwork_settings', \r\n        'wp_upwork-section',\r\n        array(\r\n            'field' =&gt; 'wp_upwork_api_key'\r\n        )\r\n    );\r\n    \/\/ add your setting's fields\r\n    add_settings_field(\r\n        'wp_upwork-wp_upwork_api_secret', \r\n        'API Secret', \r\n        array(&amp;$this, 'settings_field_input_text'), \r\n        'wp_upwork_settings', \r\n        'wp_upwork-section',\r\n        array(\r\n            'field' =&gt; 'wp_upwork_api_secret'\r\n        )\r\n    );\r\n}\r\n\r\npublic function settings_section_wp_upwork()\r\n{\r\n    \/\/ Think of this as help text for the section.\r\n    echo 'Upwork API Setting:';\r\n}\r\n\/**\r\n * This function provides text inputs for settings fields\r\n *\/\r\npublic function settings_field_input_text($args)\r\n{\r\n    \/\/ Get the field name from the $args array\r\n    $field = esc_attr($args['field']);\r\n    \/\/ Get the value of this setting\r\n    $value = get_option($field);\r\n    \/\/ echo a proper input type=\"text\"\r\n    echo sprintf('&lt;input type=\"text\" name=\"%s\" id=\"%s\" value=\"%s\" \/&gt;', $field, $field, $value);\r\n} \/\/ END public function settings_field_input_text($args)<\/pre>\n<p>Then we add the menu &#8216;WP Upwork Setting&#8217; in the Settings menu. Let&#8217;s add some code in WP_Upwork class:<\/p>\n<pre class=\"lang:default decode:true \">\/**\r\n * add a menu\r\n *\/     \r\npublic function add_menu()\r\n{\r\n    \/\/ Add a page to manage this plugin's settings\r\n    add_options_page(\r\n        'WP Upwork Settings', \r\n        'WP Upwork Settings', \r\n        'manage_options', \r\n        'wp_upwork', \r\n        array(&amp;$this, 'plugin_settings_page')\r\n    );\r\n} \/\/ END public function add_menu()\r\n\r\n\/**\r\n * Menu Callback\r\n *\/     \r\npublic function plugin_settings_page()\r\n{\r\n    if(!current_user_can('manage_options'))\r\n    {\r\n        wp_die(__('You do not have sufficient permissions to access this page.'));\r\n    }\r\n\r\n    \/\/ Render the settings template\r\n    \/\/include(sprintf(\"%s\/templates\/settings.php\", dirname(__FILE__)));\r\n    ?&gt;\r\n    &lt;div class=\"wrap\"&gt;\r\n        &lt;h2&gt;Upwork API Settings&lt;\/h2&gt;\r\n        &lt;p&gt;You'll need to go to the &lt;a href=\"https:\/\/developers.upwork.com\"&gt;Upwork Developer Page&lt;\/a&gt; to setup your project and setup the values below.&lt;\/p&gt;\r\n        &lt;form action=\"options.php\" method=\"POST\"&gt;\r\n            &lt;?php settings_fields( 'wp_upwork-group' ); ?&gt;\r\n            &lt;?php do_settings_sections( 'wp_upwork_settings' ); ?&gt;\r\n            &lt;?php submit_button(); ?&gt;\r\n        &lt;\/form&gt;\r\n    &lt;\/div&gt;\r\n    &lt;?php\r\n} \/\/ END public function plugin_settings_page()<\/pre>\n<p>Okay. Here is the menu<a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-menu.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1139\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-menu.png\" alt=\"wp-plugin-upwork-menu\" width=\"198\" height=\"277\" \/><\/a>And here is the &#8216;Upwork API Settings&#8217; page (http:\/\/localhost\/works\/wordpress_local\/wp-admin\/options-general.php?page=wp_upwork)<a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-admin-page.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1140\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-admin-page.png\" alt=\"wp-plugin-upwork-admin-page\" width=\"659\" height=\"352\" srcset=\"https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-admin-page.png 659w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-admin-page-300x160.png 300w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px\" \/><\/a><\/li>\n<li>Save the settings<br \/>\nFill the API Key and API Secret data above given by upwork then click &#8216;Save Changes&#8217;<a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-settings.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1145\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-settings.png\" alt=\"wp-plugin-upwork-settings\" width=\"624\" height=\"308\" srcset=\"https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-settings.png 624w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-settings-300x148.png 300w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px\" \/><\/a>The above values would be saved in the database at &#8216;wp_options&#8217; table. You can see them in the table like this:<a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-settings-db.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1146\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-settings-db.png\" alt=\"wp-plugin-upwork-settings-db\" width=\"721\" height=\"112\" srcset=\"https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-settings-db.png 721w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-settings-db-300x47.png 300w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px\" \/><\/a>Here is my Upwork API Settings:<span class=\"rcp-restricted-content-message\">SORRY, ONLY ADMIN CAN SHOW THIS!<\/span><\/li>\n<li>Add Setting link next to activate\/deactivate link in the plugin management list.<br \/>\nIn the WP_Upwork class constructor, add filter &#8216;plugin_action_links&#8217; like this line:<\/p>\n<pre class=\"lang:default decode:true \">public function __construct()\r\n{\r\n    ...\r\n    \/\/ Add settings link to plugins page\r\n    add_filter( 'plugin_action_links_' . plugin_basename(__FILE__) , array( &amp;$this , 'add_settings_link' ) );\r\n} \/\/ END public function __construct\r\n<\/pre>\n<p>Then define the function &#8216;add_settings_link&#8217; in the WP_Upwork class:<\/p>\n<pre class=\"lang:default decode:true\">\/\/ Add the settings link to the plugins page\r\nfunction add_settings_link($links)\r\n{ \r\n    $settings_link = '&lt;a href=\"options-general.php?page=wp_upwork\"&gt;Settings&lt;\/a&gt;'; \r\n    array_unshift($links, $settings_link); \r\n    return $links; \r\n}<\/pre>\n<p>Here is the result looks like:<a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-settings-link.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1143\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-settings-link.png\" alt=\"wp-plugin-upwork-settings-link\" width=\"652\" height=\"242\" srcset=\"https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-settings-link.png 652w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-settings-link-300x111.png 300w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px\" \/><\/a><\/li>\n<li>Refactor our plugin structure a bit. Create a new directory &#8216;includes&#8217; and add a new file in it &#8216;settings.php&#8217;. I want to move the settings in to the file to make the plugin structure better (Please learn <a href=\"http:\/\/wppb.io\/\" target=\"_blank\" rel=\"noopener noreferrer\">WordPress plugin boilerplate<\/a> and read <a href=\"https:\/\/scotch.io\/tutorials\/how-to-build-a-wordpress-plugin-part-1\" target=\"_blank\" rel=\"noopener noreferrer\">How to Build a WordPress Plugin (part 1)<\/a>).<br \/>\nHere is the content of \/includes\/settings.php:<\/p>\n<pre class=\"lang:default decode:true \">&lt;?php\r\nif ( ! defined( 'ABSPATH' ) ) exit;\r\n\r\nif(!class_exists('WP_Upwork_Settings'))\r\n{\r\n    class WP_Upwork_Settings{\r\n        \/**\r\n         * Construct the plugin object\r\n         *\/\r\n        public function __construct()\r\n        {\r\n            \/\/ register actions\r\n            \/\/ Register plugin settings\r\n            add_action('admin_init', array(&amp;$this, 'admin_init'));\r\n            \/\/ Add settings page to menu\r\n            add_action('admin_menu', array(&amp;$this, 'add_menu'));\r\n        } \/\/ END public function __construct\r\n        \r\n        \/**\r\n         * hook into WP's admin_init action hook\r\n         *\/\r\n        public function admin_init(){\r\n            \/\/ register your plugin's settings\r\n            register_setting( 'wp_upwork-group', 'wp_upwork_api_key' );\r\n            register_setting( 'wp_upwork-group', 'wp_upwork_api_secret' );\r\n            \/\/ add your settings section\r\n            add_settings_section(\r\n                'wp_upwork-section', \r\n                __('Upwork API Settings'), \r\n                array( &amp;$this, 'settings_section_wp_upwork'), \r\n                'wp_upwork_settings'\r\n            );\r\n            \/\/ add your setting's fields\r\n            add_settings_field(\r\n                'wp_upwork-api_key', \r\n                __('API Key'), \r\n                array(&amp;$this, 'settings_field_input_text'), \r\n                'wp_upwork_settings', \r\n                'wp_upwork-section',\r\n                array(\r\n                    'field' =&gt; 'wp_upwork_api_key'\r\n                )\r\n            );\r\n            \/\/ add your setting's fields\r\n            add_settings_field(\r\n                'wp_upwork-wp_upwork_api_secret', \r\n                __('API Secret'), \r\n                array(&amp;$this, 'settings_field_input_text'), \r\n                'wp_upwork_settings', \r\n                'wp_upwork-section',\r\n                array(\r\n                    'field' =&gt; 'wp_upwork_api_secret'\r\n                )\r\n            );\r\n        }\r\n\r\n        public function settings_section_wp_upwork()\r\n        {\r\n            \/\/ Think of this as help text for the section.\r\n            \/\/echo 'Upwork API Setting:';\r\n            _e('Upwork API Setting:','wp_upwork');\r\n        }\r\n        \/**\r\n         * This function provides text inputs for settings fields\r\n         *\/\r\n        public function settings_field_input_text($args)\r\n        {\r\n            \/\/ Get the field name from the $args array\r\n            $field = esc_attr($args['field']);\r\n            \/\/ Get the value of this setting\r\n            $value = get_option($field);\r\n            \/\/ echo a proper input type=\"text\"\r\n            echo sprintf('&lt;input type=\"text\" name=\"%s\" id=\"%s\" value=\"%s\" \/&gt;', $field, $field, $value);\r\n        } \/\/ END public function settings_field_input_text($args)\r\n        \r\n        \/**\r\n         * add a menu\r\n         *\/     \r\n        public function add_menu()\r\n        {\r\n            \/\/ Add a page to manage this plugin's settings\r\n            add_options_page(\r\n                __('WP Upwork Settings'), \r\n                __('WP Upwork Settings'), \r\n                'manage_options', \r\n                'wp_upwork', \r\n                array(&amp;$this, 'plugin_settings_page')\r\n            );\r\n        } \/\/ END public function add_menu()\r\n\r\n        \/**\r\n         * Menu Callback\r\n         *\/     \r\n        public function plugin_settings_page()\r\n        {\r\n            if(!current_user_can('manage_options'))\r\n            {\r\n                wp_die(__('You do not have sufficient permissions to access this page.'));\r\n            }\r\n\r\n            \/\/ Render the settings template\r\n            \/\/include(sprintf(\"%s\/templates\/settings.php\", dirname(__FILE__)));\r\n            ?&gt;\r\n            &lt;div class=\"wrap\"&gt;\r\n                &lt;h2&gt;&lt;?php _e('Upwork API Settings','wp_upwork'); ?&gt;&lt;\/h2&gt;\r\n                &lt;p&gt;&lt;?php _e('You\\'ll need to go to the &lt;a href=\"https:\/\/developers.upwork.com\"&gt;Upwork Developer Page&lt;\/a&gt; to setup your project and setup the values below.'); ?&gt;&lt;\/p&gt;\r\n                &lt;form action=\"options.php\" method=\"POST\"&gt;\r\n                    &lt;?php settings_fields( 'wp_upwork-group' ); ?&gt;\r\n                    &lt;?php do_settings_sections( 'wp_upwork_settings' ); ?&gt;\r\n                    &lt;?php submit_button(); ?&gt;\r\n                &lt;\/form&gt;\r\n            &lt;\/div&gt;\r\n            &lt;?php\r\n        } \/\/ END public function plugin_settings_page()\r\n    } \/\/ END class WP_Upwork_Settings\r\n} \/\/ END if(!class_exists('WP_Upwork_Settings'))<\/pre>\n<p>And here is our main plugin file &#8216;upwork.php&#8217; content:<\/p>\n<pre class=\"lang:default decode:true\">if ( ! defined( 'ABSPATH' ) ) exit;\r\n\r\nif( ! defined('WP_UPWORK_PLUGIN_DIR' ) ) {\r\n    define('WP_UPWORK_PLUGIN_DIR', dirname(__FILE__));\r\n}\r\n\r\nif(!class_exists('WP_Upwork'))\r\n{\r\n    class WP_Upwork{\r\n        \/**\r\n         * Construct the plugin object\r\n         *\/\r\n        public function __construct()\r\n        {\r\n            \/\/Initialize settings\r\n            require_once(WP_UPWORK_PLUGIN_DIR . '\/includes\/settings.php');\r\n            $WP_Upwork_Settings=new WP_Upwork_Settings();\r\n            \/\/ Add settings link to plugins page\r\n            add_filter( 'plugin_action_links_' . plugin_basename(__FILE__) , array( &amp;$this , 'add_settings_link' ) );\r\n        }\r\n        \/**\r\n         * Activate the plugin\r\n         *\/\r\n        public static function activate()\r\n        {\r\n            \/\/ Do nothing\r\n        } \/\/ END public static function activate\r\n    \r\n        \/**\r\n         * Deactivate the plugin\r\n         *\/     \r\n        public static function deactivate()\r\n        {\r\n            \/\/ Do nothing\r\n        } \/\/ END public static function deactivate\r\n        \r\n        \/\/ Add the settings link to the plugins page\r\n        function add_settings_link($links)\r\n        { \r\n            $settings_link = '&lt;a href=\"options-general.php?page=wp_upwork\"&gt;Settings&lt;\/a&gt;'; \r\n            array_unshift($links, $settings_link); \r\n            return $links; \r\n        }\r\n    } \/\/ END class WP_Upwork\r\n} \/\/ END if(!class_exists('WP_Upwork'))\r\n\r\n\/\/Instantiate WP_Upwork class\r\nif(class_exists('WP_Upwork')){\r\n    \/\/ Installation and uninstallation hooks\r\n    register_activation_hook(__FILE__, array('WP_Upwork', 'activate'));\r\n    register_deactivation_hook(__FILE__, array('WP_Upwork', 'deactivate'));\r\n\r\n    \/\/ instantiate the plugin class\r\n    $wp_upwork = new WP_Upwork();\r\n}<\/pre>\n<p>Somehow I can&#8217;t put the filter &#8216;plugin_action_links_&#8217; . plugin_basename(__FILE__)&#8217; in &#8216;WP_Upwork_Settings&#8217; class! The setting link can&#8217;t be displayed in the plugin main list!<\/li>\n<li>Now I want to connect to Upwork API with My API key and API Secret provided by Upwork. When the connection is success, I would get the access token! I need to store the token to get more access from Upwork like searching the jobs and many more.<br \/>\nNOTE: I MADE A WRONG THING HERE! WHAT I THOUGHT AS ACCESS TOKEN ACTUALLY IS A REQUEST TOKEN! AND FINALLY IT&#8217;S NOT WORKING FROM HERE #9 UNTIL #13<br \/>\nModify \/includes\/settings.php to show the token below the API Key and Secret (The token must be from Upwork so I dont have to type it manually). The screnario is every &#8216;Save&#8217; button is pressed, beside the keys, the token would be updated as well. So in &#8216;WP_Upwork_Settings&#8217; class constructor, add this:<\/p>\n<pre class=\"lang:default decode:true\">class WP_Upwork_Settings{\r\n    \/**\r\n     * Construct the plugin object\r\n     *\/\r\n    protected $action       = 'wp_upwork';\r\n    protected $option_name  = 'wp_upwork';\r\n\r\n    public function __construct()\r\n    {\r\n        ...\r\n        \/\/ Get access token after saving data\r\n        add_action('init', array(&amp;$this, 'get_access_token'));\r\n    } \/\/ END public function __construct\r\n<\/pre>\n<p>Then show the label for the access token in &#8216;admin_init&#8217; and &#8216;settings_field_label&#8217; function:<\/p>\n<pre class=\"lang:default decode:true\">public function admin_init(){\r\n    \/\/ register your plugin's settings\r\n    ...\r\n    register_setting( 'wp_upwork-group', 'wp_upwork_access_token' );\r\n    ...\r\n    \/\/ add your setting's fields\r\n    add_settings_field(\r\n        'wp_upwork-wp_upwork_access_token', \r\n        __('Access Token'), \r\n        array(&amp;$this, 'settings_field_label'), \r\n        'wp_upwork_settings', \r\n        'wp_upwork-section',\r\n        array(\r\n            'field' =&gt; 'wp_upwork_access_token'\r\n        )\r\n    );\r\n}\r\n...\r\n\/**\r\n * This function provides label for settings fields\r\n *\/\r\npublic function settings_field_label($args)\r\n{\r\n    \/\/ Get the field name from the $args array\r\n    $field = esc_attr($args['field']);\r\n    \/\/ Get the value of this setting\r\n    $value = get_option($field);\r\n    \/\/ echo a proper input type=\"text\"\r\n    echo sprintf('&lt;label name=\"%s\" id=\"%s\"&gt;%s&lt;\/label&gt;', $field, $field, $value);\r\n} \/\/ END public function settings_field_input_text($args)<\/pre>\n<p>Modify &#8216;plugin_settings_page&#8217; function to add a new hidden value &#8216;wp_nonce_field&#8217; and change the button title to &#8216;Save and Get Access Token&#8217;.<\/p>\n<pre class=\"lang:default decode:true\">public function plugin_settings_page()\r\n{\r\n    ...\r\n    ?&gt;\r\n    &lt;div class=\"wrap\"&gt;\r\n        &lt;h2&gt;&lt;?php _e('Upwork API Settings','wp_upwork'); ?&gt;&lt;\/h2&gt;\r\n        &lt;p&gt;&lt;?php _e('You\\'ll need to go to the &lt;a href=\"https:\/\/developers.upwork.com\"&gt;Upwork Developer Page&lt;\/a&gt; to setup your project and setup the values below.'); ?&gt;&lt;\/p&gt;\r\n        &lt;form action=\"options-general.php?page=wp_upwork\" method=\"POST\"&gt;\r\n            &lt;?php settings_fields( 'wp_upwork-group' ); ?&gt;\r\n            &lt;?php wp_nonce_field( $this-&gt;action, $this-&gt;option_name . '_nonce', FALSE ); ?&gt;\r\n            &lt;?php do_settings_sections( 'wp_upwork_settings' ); ?&gt;\r\n            &lt;?php submit_button(__('Save and Get Access Token')); ?&gt;\r\n        &lt;\/form&gt;\r\n    &lt;\/div&gt;\r\n    &lt;?php\r\n} \/\/ END public function plugin_settings_page()<\/pre>\n<p>The hidden value would be submitted and be caught to inspect the keys and get the access token in &#8216;get_access_token&#8217; function.<\/p>\n<pre class=\"lang:default decode:true \">\/**\r\n * Get access token after saving data\r\n *\/     \r\npublic function get_access_token()\r\n{\r\n    if(isset($_POST[ $this-&gt;option_name . '_nonce' ])){\r\n        if ( wp_verify_nonce( $_POST[ $this-&gt;option_name . '_nonce' ], $this-&gt;action ) ){\r\n            if ( isset ( $_POST[ 'wp_upwork_api_key' ] ) &amp;&amp; isset ( $_POST[ 'wp_upwork_api_secret' ] )){\r\n                \/*require_once(WP_UPWORK_PLUGIN_DIR . '\/src\/Upwork\/API\/Config.php');\r\n                NO MORE INCLUDE.USE AUTOLOAD INSTEAD*\/\r\n                $api_key=$_POST[ 'wp_upwork_api_key' ];\r\n                $api_secret=$_POST[ 'wp_upwork_api_secret' ];\r\n                $my_config=array(\r\n                    'consumerKey'       =&gt; $api_key,\r\n                    'consumerSecret'    =&gt; $api_secret,\r\n                    'accessToken'       =&gt; NULL,       \/\/ got access token\r\n                    'accessSecret'      =&gt; NULL,      \/\/ got access secret\r\n                    'requestToken'      =&gt; NULL,      \/\/ got request token\r\n                    'requestSecret'     =&gt; NULL,     \/\/ got request secret\r\n                    'verifySsl'         =&gt; false,\r\n                    'mode'              =&gt; 'web',\r\n                    'authType'          =&gt; 'OAuthPHPLib',\r\n                    'debug'             =&gt; false\r\n                );\r\n                $config=new \\Upwork\\API\\Config($my_config);\r\n                \/\/echo $config::get('consumerKey');\r\n                $client=new \\Upwork\\API\\Client($config);\r\n                \/\/$requestTokenInfo = $client-&gt;getRequestToken();\r\n                var_dump($client-&gt;getRequestToken());\r\n            }\r\n            exit;\r\n        }\r\n    }\r\n} \/\/ END public function admin_post()<\/pre>\n<p>There is an important setting to pass the configuration beside &#8216;consumer key&#8217; and &#8216;consumer secret&#8217;, it&#8217;s &#8216;authType&#8217;. I tried &#8216;OAuth1&#8217; but it didn&#8217;t work. the work is &#8216;OAuthPHPLib&#8217;.<\/li>\n<li>Use composer to download the Upwork API for PHP (https:\/\/github.com\/upwork\/php-upwork). Create a new composer.json file in our main plugin directory. Here is the content:\n<pre class=\"lang:default decode:true \">{\r\n    \"name\": \"advcha\/upwork\",\r\n    \"require\": {\r\n        \"upwork\/php-upwork\": \"dev-master\"\r\n    }\r\n}<\/pre>\n<p>Now use terminal and download the API PHP library<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy-K43SJ:~$ cd Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/\r\nteddy@teddy-K43SJ:~\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork$ composer update\r\nLoading composer repositories with package information\r\nUpdating dependencies (including require-dev)\r\n  - Installing upwork\/php-upwork (dev-master b48b104)\r\n    Downloading: 100%         \r\n\r\nupwork\/php-upwork suggests installing ext-oauth (This extension from PECL provides OAuth consumer and provider bindings. See more under http:\/\/www.php.net\/oauth)\r\nWriting lock file\r\nGenerating autoload files<\/pre>\n<p>This would create a new directory &#8216;vendor&#8217; in the main our plugin directory. The API would be there!<br \/>\nRead how to use autoload and composer for developing wordpress plugin: <a href=\"http:\/\/torquemag.io\/2014\/09\/improving-wordpress-development-workflow-composer\/\" target=\"_blank\" rel=\"noopener noreferrer\">Improving WordPress Development Workflow with Composer<\/a>, <a href=\"https:\/\/deliciousbrains.com\/using-composer-manage-wordpress-themes-plugins\/\" target=\"_blank\" rel=\"noopener noreferrer\">Managing Your WordPress Site with Git and Composer Part 2 \u2013 Using Composer to Manage Themes and Plugins<\/a> and <a href=\"https:\/\/www.smashingmagazine.com\/2015\/05\/how-to-use-autoloading-and-a-plugin-container-in-wordpress-plugins\/\" target=\"_blank\" rel=\"noopener noreferrer\">How To Use Autoloading And A Plugin Container In WordPress Plugins<\/a>.<\/li>\n<li>We need to add the autoload in upwork.php file so we can use the API library:\n<pre class=\"lang:default decode:true \">require __DIR__ . '\/vendor\/autoload.php';<\/pre>\n<p>With this only single line, we dont need to include\/require the API library manually like this (\/includes\/settings.php at &#8216;admin_post&#8217; function):<\/p>\n<pre class=\"lang:default decode:true \">\/*require_once(WP_UPWORK_PLUGIN_DIR . '\/src\/Upwork\/API\/Config.php');\r\nrequire_once(WP_UPWORK_PLUGIN_DIR . '\/src\/Upwork\/API\/Client.php');\r\nrequire_once(WP_UPWORK_PLUGIN_DIR . '\/src\/Upwork\/API\/Debug.php');\r\nrequire_once(WP_UPWORK_PLUGIN_DIR . '\/src\/Upwork\/API\/Interfaces\/Client.php');\r\nrequire_once(WP_UPWORK_PLUGIN_DIR . '\/src\/Upwork\/API\/AuthTypes\/AbstractOAuth.php');\r\nrequire_once(WP_UPWORK_PLUGIN_DIR . '\/src\/Upwork\/API\/AuthTypes\/OAuth1.php');*\/\r\n<\/pre>\n<\/li>\n<li>Here is how it looks<a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-token.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1150\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-token.png\" alt=\"wp-plugin-upwork-token\" width=\"638\" height=\"374\" srcset=\"https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-token.png 638w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-token-300x176.png 300w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px\" \/><\/a>When the button is pressed,\u00a0 if nothing wrong the access token and the access token secret would be revealed like this:<span class=\"rcp-restricted-content-message\">SORRY, ONLY ADMIN CAN SHOW THIS!<\/span><\/li>\n<li>Now I want to store the tokens values in database so later we can get the values and use its for Upwork API functions.<br \/>\nModify &#8216;get_access_token&#8217; function in \/includes\/settings.php file to get the tokens and save its. I use &#8216;update_option&#8217; function to do its (https:\/\/codex.wordpress.org\/Function_Reference\/update_option)<\/p>\n<pre class=\"lang:default decode:true\">public function get_access_token()\r\n{\r\n    if(isset($_POST[ $this-&gt;option_name . '_nonce' ])){\r\n        if ( wp_verify_nonce( $_POST[ $this-&gt;option_name . '_nonce' ], $this-&gt;action ) ){\r\n            if ( isset ( $_POST[ 'wp_upwork_api_key' ] ) &amp;&amp; isset ( $_POST[ 'wp_upwork_api_secret' ] )){\r\n                ...\r\n                $client=new \\Upwork\\API\\Client($config);\r\n                $requestTokenInfo = $client-&gt;getRequestToken();\r\n                if(isset($requestTokenInfo['oauth_token']) &amp;&amp; isset($requestTokenInfo['oauth_token_secret'])){\r\n                    \/\/save\/update the tokens in database\r\n                    update_option('wp_upwork_access_token', $requestTokenInfo['oauth_token']);\r\n                    update_option('wp_upwork_access_token_secret', $requestTokenInfo['oauth_token_secret']);\r\n                }else{\r\n                    var_dump($client-&gt;getRequestToken());\r\n                    exit;\r\n                }\r\n                \r\n            }\r\n            \/\/exit;\r\n        }\r\n    }\r\n} \/\/ END public function get_access_token()<\/pre>\n<p>If everything right, here is how it would looks like<a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-get-token2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1154\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-get-token2.png\" alt=\"wp-plugin-upwork-get-token2\" width=\"651\" height=\"395\" srcset=\"https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-get-token2.png 651w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-get-token2-300x182.png 300w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px\" \/><\/a>&lt;OLD&gt;<br \/>\nYou can also check the tokens values. Not only the value for access token (&#8216;wp_upwork_access_token&#8217;) but also for access token secret&#8217;s value (&#8216;wp_upwork_access_token_secret&#8217;). No reason to display the secret&#8217;s value here.<br \/>\n&lt;\/OLD&gt;<br \/>\n&lt;NEW&gt;<br \/>\nActually I GOT THE REQUEST TOKEN ABOVE NOT THE ACCESS TOKEN!! SO UPWORK GAVE REQUEST TOKEN FIRST THEN GIVE BACK THE ACCESS TOKEN IF SUCCESS!<br \/>\nREAD THIS FOR THE WORKFLOW: https:\/\/developers.upwork.com\/?lang=php#authentication_oauth-10<br \/>\n&lt;\/NEW&gt;<\/li>\n<li>I tried to get the access token (actually I just realized I got the request token not the access token)<br \/>\nI MODIFY &#8216;get_access_token&#8217; function<\/p>\n<pre class=\"lang:default decode:true\">\/**\r\n * Get access token after saving data\r\n *\/     \r\npublic function get_access_token()\r\n{\r\n    if( !session_id() )\r\n        session_start();\r\n        \r\n    if(isset($_POST[ $this-&gt;option_name . '_nonce' ]) || (isset($_SESSION['oauth_token']) &amp;&amp; isset($_SESSION['oauth_token_secret'])) || (isset($_GET['oauth_token']) &amp;&amp; isset($_SESSION['oauth_verifier']))){\r\n        \/\/first\r\n        $api_key=get_option('wp_upwork_api_key');\r\n        $api_secret=get_option('wp_upwork_api_secret');\r\n        \/*if ( isset ( $_POST[ 'wp_upwork_api_key' ] ) &amp;&amp; isset ( $_POST[ 'wp_upwork_api_secret' ] )){\r\n            $api_key=$_POST[ 'wp_upwork_api_key' ];\r\n            $api_secret=$_POST[ 'wp_upwork_api_secret' ];\r\n        }*\/\r\n        $request_token=$_SESSION['oauth_token'];\r\n        $request_token_secret=$_SESSION['oauth_token_secret'];\r\n        $verifier=$_GET['oauth_verifier'];\r\n\r\n        $access_token=$_SESSION['access_token'];\r\n        $access_secret=$_SESSION['access_secret'];\r\n                \r\n        $my_config=array(\r\n            'consumerKey'       =&gt; $api_key,\r\n            'consumerSecret'    =&gt; $api_secret,\r\n            'accessToken'       =&gt; $access_token,             \/\/ got access token\r\n            'accessSecret'      =&gt; $access_secret,            \/\/ got access secret\r\n            'requestToken'      =&gt; $request_token,            \/\/ got request token\r\n            'requestSecret'     =&gt; $request_token_secret,     \/\/ got request secret\r\n            'verifier'          =&gt; $verifier,\r\n            'verifySsl'         =&gt; false,\r\n            'mode'              =&gt; 'web',\r\n            'authType'          =&gt; 'OAuthPHPLib',\r\n            'debug'             =&gt; false\r\n        );\r\n        $config=new \\Upwork\\API\\Config($my_config);\r\n        $client=new \\Upwork\\API\\Client($config);\r\n                \r\n        if ( wp_verify_nonce( $_POST[ $this-&gt;option_name . '_nonce' ], $this-&gt;action ) &amp;&amp; (empty($_SESSION['oauth_token']) &amp;&amp; empty($_SESSION['access_token'])) ){\r\n            if ( isset ( $_POST[ 'wp_upwork_api_key' ] ) &amp;&amp; isset ( $_POST[ 'wp_upwork_api_secret' ] )){\r\n                $requestTokenInfo = $client-&gt;getRequestToken();\r\n                if(isset($requestTokenInfo['oauth_token']) &amp;&amp; isset($requestTokenInfo['oauth_token_secret'])){\r\n                    \r\n                    $_SESSION['oauth_token']=$requestTokenInfo['oauth_token'];\r\n                    $_SESSION['oauth_token_secret']=$requestTokenInfo['oauth_token_secret'];\r\n                    \/\/ request authorization\r\n                    $client-&gt;auth();\r\n                    \/\/var_dump($accessTokenInfo);\r\n                    \/\/exit;\r\n                }else{\r\n                    var_dump($client-&gt;getRequestToken());\r\n                    exit;\r\n                }\r\n                \r\n            }\r\n            \/\/exit;\r\n        }elseif(empty($_SESSION['access_token'])){\r\n            \/\/get authorization\r\n            $accessTokenInfo = $client-&gt;auth();\r\n            var_dump($accessTokenInfo);\r\n            if($accessTokenInfo){\r\n                $_SESSION['access_token']   = $accessTokenInfo['access_token'];\r\n                $_SESSION['access_secret']  = $accessTokenInfo['access_secret'];\r\n                \r\n                \/\/save\/update the tokens in database\r\n                update_option('wp_upwork_access_token',$accessTokenInfo['access_token']);\r\n                update_option('wp_upwork_access_token_secret',$accessTokenInfo['access_secret']);\r\n            }\r\n            \/\/exit;\r\n        }\r\n        \r\n        if ($_SESSION['access_token']) {\r\n            \/\/ clean up session data\r\n            unset($_SESSION['request_token']);\r\n            unset($_SESSION['request_secret']);\r\n            \/\/ gets info of the authenticated user\r\n            $auth = new \\Upwork\\API\\Routers\\Auth($client);\r\n            $info = $auth-&gt;getUserInfo();\r\n            print_r($info);\r\n        }\r\n    }\r\n    \r\n    \r\n} \/\/ END public function get_access_token()<\/pre>\n<p>LIKE I SAID ABOVE, IT DIDN&#8217;T WORK<\/p>\n<p><a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1170\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth.png\" alt=\"wp-plugin-upwork-auth\" width=\"971\" height=\"515\" srcset=\"https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth.png 971w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth-300x159.png 300w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth-768x407.png 768w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/a><a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth-access.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1171\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth-access.png\" alt=\"wp-plugin-upwork-auth-access\" width=\"676\" height=\"676\" srcset=\"https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth-access.png 676w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth-access-150x150.png 150w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth-access-300x300.png 300w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px\" \/><\/a><a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth-no-page.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1172\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth-no-page.png\" alt=\"wp-plugin-upwork-auth-no-page\" width=\"778\" height=\"563\" srcset=\"https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth-no-page.png 778w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth-no-page-300x217.png 300w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-auth-no-page-768x556.png 768w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px\" \/><\/a>https:\/\/www.upwork.com\/services\/api\/www.advchaweb.com\/upwork?oauth_token=708638d60eee72f4c7c133a2617b15ef&amp;oauth_verifier=b57428447a10ef831db125a1c9f6e648<br \/>\nIT SHOULD BE LIKE:<br \/>\nhttp:\/\/localhost\/works\/wordpress_local\/wp-admin\/options-general.php?page=wp_upwork&amp;oauth_token=63c1ab57d81ef2a120dc122255f252fd&amp;oauth_verifier=4601823dab3c049d2d71be0f76a48a7cUNTIL HERE, IT&#8217;S NOT WORKING AS EXPECTED. I NEED TO TRY THIS SAMPLE https:\/\/github.com\/upwork\/php-upwork\/blob\/master\/example\/web.php<br \/>\nI MAKE THE SAMPLE LOCALLY: http:\/\/localhost\/works\/upwork_api\/ AND IT&#8217;S WORKING FOR THE FIRST TIME (NOT WORKING AFTER THAT. MEANS NO DATA CAN I GET FROM UPWORK!!!)<br \/>\n<span class=\"rcp-restricted-content-message\">SORRY, ONLY ADMIN CAN SHOW THIS!<\/span><br \/>\nAfter a few hours I tried again to call the Upwork API via http:\/\/localhost\/works\/upwork_api AND it&#8217;s working again. Actually to get the access token and call a function (like User), it takes four web call.<br \/>\n<span class=\"rcp-restricted-content-message\">SORRY, ONLY ADMIN CAN SHOW THIS!<\/span><\/li>\n<li>Because I failed to get the access token from &#8216;get_access_token&#8217; function, I tried to use Custom Page Template (Please read <a href=\"http:\/\/www.wpexplorer.com\/wordpress-page-templates-plugin\/\" target=\"_blank\" rel=\"noopener noreferrer\">Add Page Templates to WordPress with a Plugin<\/a>) like I used to use it for <a href=\"http:\/\/myprojects.advchaweb.com\/index.php\/2016\/11\/30\/elance-api-on-wordpress-without-wp-plugin\/\" target=\"_blank\" rel=\"noopener noreferrer\">Elance API<\/a>. But it different here. I dont have to inject the php file in the active theme. I can use it from my plugin!<br \/>\nOkay. I need to clean my code and remove the previous changes above (from #9 and #14) about the tokens field and the &#8216;get_access_token&#8217; function.<br \/>\n<span class=\"rcp-restricted-content-message\">SORRY, ONLY ADMIN CAN SHOW THIS!<\/span><br \/>\nSO I BACK TO THE PREVIOUS CODE WHERE THE WP_Upwork plugin in the admin page only to store API Key and API Secret!<br \/>\nBack to our custom page template, create a new file &#8216;template.php&#8217; in \/includes\/ directory. this file would consist of a class &#8216;WP_Upwork_Template&#8217;. This class would get the template file, show it on the page\/post page dropdown template and render\/view it.<\/p>\n<pre class=\"lang:default decode:true \">&lt;?php\r\nif ( ! defined( 'ABSPATH' ) ) exit;\r\n\r\nif(!class_exists('WP_Upwork_Template'))\r\n{\r\n    class WP_Upwork_Template{\r\n        \r\n        \/**\r\n         * A reference to an instance of this class.\r\n         *\/\r\n        private static $instance;\r\n        \/**\r\n         * The array of templates that this plugin tracks.\r\n         *\/\r\n        protected $templates;\r\n        \/**\r\n         * Returns an instance of this class. \r\n         *\/\r\n        public static function get_instance() {\r\n            if ( null == self::$instance ) {\r\n                self::$instance = new WP_Upwork_Template();\r\n            } \r\n            return self::$instance;\r\n        } \r\n        \/**\r\n         * Construct the plugin object\r\n         *\/\r\n        public function __construct()\r\n        {\r\n            $this-&gt;templates = array();\r\n            \r\n            \/\/ Add a filter to the attributes metabox to inject template into the cache.\r\n            if ( version_compare( floatval( get_bloginfo( 'version' ) ), '4.7', '&lt;' ) ) { \/\/ 4.6 and older\r\n                add_filter(\r\n                    'page_attributes_dropdown_pages_args',\r\n                    array( &amp;$this, 'register_upwork_templates' )\r\n                );\r\n            } else { \/\/ Add a filter to the wp 4.7 version attributes metabox\r\n                add_filter(\r\n                    'theme_page_templates', array( &amp;$this, 'add_upwork_template' )\r\n                );\r\n            }\r\n            \/\/ Add a filter to the save post to inject out template into the page cache\r\n            add_filter(\r\n                'wp_insert_post_data', \r\n                array( &amp;$this, 'register_upwork_templates' ) \r\n            );\r\n            \/\/ Add a filter to the template include to determine if the page has our \r\n            \/\/ template assigned and return it's path\r\n            add_filter(\r\n                'template_include', \r\n                array( &amp;$this, 'view_upwork_template') \r\n            );\r\n            \/\/ Add your templates to this array.\r\n            $this-&gt;templates = array(\r\n                'upwork-template.php' =&gt; 'Upwork Template',\r\n            );\r\n        } \/\/ END public function __construct\r\n        \r\n        \/**\r\n         * Adds our template to the page dropdown for v4.7+\r\n         *\r\n         *\/\r\n        public function add_upwork_template( $posts_templates ) {\r\n            $posts_templates = array_merge( $posts_templates, $this-&gt;templates );\r\n            return $posts_templates;\r\n        }\r\n        \/**\r\n         * Adds our template to the pages cache in order to trick WordPress\r\n         * into thinking the template file exists where it doens't really exist.\r\n         *\r\n         *\/\r\n        public function register_upwork_templates( $atts ) {\r\n            \/\/ Create the key used for the themes cache\r\n            $cache_key = 'page_templates-' . md5( get_theme_root() . '\/' . get_stylesheet() );\r\n            \/\/ Retrieve the cache list. \r\n            \/\/ If it doesn't exist, or it's empty prepare an array\r\n            $templates = wp_get_theme()-&gt;get_page_templates();\r\n            if ( empty( $templates ) ) {\r\n                $templates = array();\r\n            } \r\n            \/\/ New cache, therefore remove the old one\r\n            wp_cache_delete( $cache_key , 'themes');\r\n            \/\/ Now add our template to the list of templates by merging our templates\r\n            \/\/ with the existing templates array from the cache.\r\n            $templates = array_merge( $templates, $this-&gt;templates );\r\n            \/\/ Add the modified cache to allow WordPress to pick it up for listing\r\n            \/\/ available templates\r\n            wp_cache_add( $cache_key, $templates, 'themes', 1800 );\r\n            return $atts;\r\n        } \r\n        \/**\r\n         * Checks if the template is assigned to the page\r\n         *\/\r\n        public function view_upwork_template( $template ) {\r\n            \r\n            \/\/ Get global post\r\n            global $post;\r\n            \/\/ Return template if post is empty\r\n            if ( ! $post ) {\r\n                return $template;\r\n            }\r\n            \/\/ Return default template if we don't have a custom one defined\r\n            if ( !isset( $this-&gt;templates[get_post_meta( \r\n                $post-&gt;ID, '_wp_page_template', true \r\n            )] ) ) {\r\n                return $template;\r\n            } \r\n            $file = plugin_dir_path(__FILE__). get_post_meta( \r\n                $post-&gt;ID, '_wp_page_template', true\r\n            );\r\n            \/\/ Just to be safe, we check if the file exist first\r\n            if ( file_exists( $file ) ) {\r\n                echo \"File exist:\";\r\n                return $file;\r\n            } else {\r\n                echo \"File NOT exist:\".$file;\r\n            }\r\n            \/\/ Return template\r\n            return $template;\r\n        }\r\n        \r\n    } \/\/ END class WP_Upwork_Template\r\n} \/\/ END if(!class_exists('WP_Upwork_Template'))<\/pre>\n<p>The template name is in a file &#8216;upwork-template.php&#8217; in the same directory (\/includes\/). this file is the main page to connect to Upwork API (authenticate, authorize\/get access token and call the Upwork API functions). This content looks like same with https:\/\/github.com\/upwork\/php-upwork\/blob\/master\/example\/web.php. Only API key and API secret I got from database. For a test only and to prove it can work as expected, here is the file content:<\/p>\n<pre class=\"lang:default decode:true\">&lt;?php\r\n\/*\r\n * Template Name: Upwork Template\r\n * Description: A Page Template for displaying Upwork API capability.\r\n *\/\r\n\r\nsession_start();\r\nrequire WP_UPWORK_PLUGIN_DIR . '\/vendor\/autoload.php';\r\n$config = new \\Upwork\\API\\Config(\r\n    array(\r\n        'consumerKey'       =&gt; get_option('wp_upwork_api_key'),  \/\/ SETUP YOUR CONSUMER KEY\r\n        'consumerSecret'    =&gt; get_option('wp_upwork_api_secret'),                  \/\/ SETUP YOUR KEY SECRET\r\n        'accessToken'       =&gt; $_SESSION['access_token'],       \/\/ got access token\r\n        'accessSecret'      =&gt; $_SESSION['access_secret'],      \/\/ got access secret\r\n        'requestToken'      =&gt; $_SESSION['request_token'],      \/\/ got request token\r\n        'requestSecret'     =&gt; $_SESSION['request_secret'],     \/\/ got request secret\r\n        'verifier'          =&gt; $_GET['oauth_verifier'],         \/\/ got oauth verifier after authorization\r\n        'mode'              =&gt; 'web',                           \/\/ can be 'nonweb' for console apps (default),\r\n                                                                \/\/ and 'web' for web-based apps\r\n        'debug'             =&gt; true, \/\/ enables debug mode. Note that enabling debug in web-based applications can block redirects\r\n        'authType'          =&gt; 'OAuthPHPLib' \/\/ your own authentication type, see AuthTypes directory\r\n    )\r\n);\r\n$client = new \\Upwork\\API\\Client($config);\r\n\/\/var_dump($_SESSION);exit;\r\nif (empty($_SESSION['request_token']) &amp;&amp; empty($_SESSION['access_token'])) {\r\n    \/\/ we need to get and save the request token. It will be used again\r\n    \/\/ after the redirect from the Upwork site\r\n    $requestTokenInfo = $client-&gt;getRequestToken();\r\n    $_SESSION['request_token']  = $requestTokenInfo['oauth_token'];\r\n    $_SESSION['request_secret'] = $requestTokenInfo['oauth_token_secret'];\r\n    \/\/ request authorization\r\n    $client-&gt;auth();\r\n} elseif (empty($_SESSION['access_token'])) {\r\n    \/\/ the callback request should be pointed to this script as well as\r\n    \/\/ the request access token after the callback\r\n    $accessTokenInfo = $client-&gt;auth();\r\n    $_SESSION['access_token']   = $accessTokenInfo['access_token'];\r\n    $_SESSION['access_secret']  = $accessTokenInfo['access_secret'];\r\n}\r\n\/\/ $accessTokenInfo has the following structure\r\n\/\/ array('access_token' =&gt; ..., 'access_secret' =&gt; ...);\r\n\/\/ keeps the access token in a secure place\r\n\/\/ if authenticated\r\nif ($_SESSION['access_token']) {\r\n    \/\/var_dump($_SESSION);\r\n    \/\/ clean up session data\r\n    unset($_SESSION['request_token']);\r\n    unset($_SESSION['request_secret']);\r\n    \/\/ gets info of the authenticated user\r\n    $auth = new \\Upwork\\API\\Routers\\Auth($client);\r\n    $info = $auth-&gt;getUserInfo();\r\n    \r\n    \/\/$roles = new \\Upwork\\API\\Routers\\Hr\\Roles($client);\r\n    \/\/$info = $roles-&gt;getAll();\r\n    echo \"&lt;BR\/&gt;PROFILE:&lt;BR\/&gt;\".print_r($info);\r\n}<\/pre>\n<p>The template name is &#8216;Upwork Template&#8217;<\/li>\n<li>Then create a new page &#8216;Upwork&#8217; and select the template &#8216;Upwork Template&#8217;<a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-template.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-1182\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-template-1024x438.png\" alt=\"wp-plugin-upwork-template\" width=\"840\" height=\"359\" srcset=\"https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-template-1024x438.png 1024w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-template-300x128.png 300w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-template-768x329.png 768w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-template.png 1161w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/a>Okay. One more thing. It&#8217;s better to change the permalink of our page url to http:\/\/localhost\/works\/wordpress_local\/upwork\/ instead of http:\/\/localhost\/works\/wordpress_local\/?p=123. To do this, please go to Settings -&gt; Permalinks -&gt; Select &#8216;Post name&#8217; Then Click &#8216;Save Changes&#8217;. It&#8217;d change the page url like above. BUT if you open the link and show 404 error, it means something wrong on your .htaccess or the permission or the apache2 setting. I tried many thing from\n<pre class=\"lang:default decode:true\">teddy@teddy-K43SJ:~\/Documents\/works\/wordpress_local$ sudo chmod 777 .htaccess \r\nteddy@teddy-K43SJ:~\/Documents\/works\/wordpress_local$ sudo service apache2 restart<\/pre>\n<p>or<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy-K43SJ:~\/Documents\/works\/wordpress_local$ sudo a2enmod rewrite\r\nModule rewrite already enabled<\/pre>\n<p>BUT NOTHING IS WORKING. IT&#8217;S FINALLY WORKING IS FROM http:\/\/askubuntu.com\/questions\/48362\/how-to-enable-mod-rewrite-in-apache. I need to put &#8216;AllowOverride All&#8217; in the default apache2 configuration file:<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy-K43SJ:~\/Documents\/works\/wordpress_local$ sudo gedit \/etc\/apache2\/sites-available\/000-default.conf<\/pre>\n<p>Then add these lines:<\/p>\n<pre class=\"lang:default decode:true \">&lt;VirtualHost *:80&gt;\r\n\t...\r\n\tDocumentRoot \/var\/www\/html\r\n\t\r\n\t&lt;Directory \"\/var\/www\/html\"&gt;\r\n\t\tAllowOverride All\r\n\t&lt;\/Directory&gt;\r\n\r\n\t...\r\n&lt;\/VirtualHost&gt;<\/pre>\n<p>Then restart apache2 server.<br \/>\nOkay. It&#8217;s working now. It can open http:\/\/localhost\/works\/wordpress_local\/upwork correctly. ALSO DON&#8217;T FORGET TO CHANGE AND SAVE Callback URL IN UPWORK API PAGE (https:\/\/www.upwork.com\/services\/api\/keys).<br \/>\n<span class=\"rcp-restricted-content-message\">SORRY, ONLY ADMIN CAN SHOW THIS!<\/span><\/li>\n<li>Modify &#8216;upwork-template.php&#8217; so we can save the access token and no need to get new token each API call. I tried like this:\n<pre class=\"lang:default decode:true\">&lt;?php\r\n\/*\r\n * Template Name: Upwork Template\r\n * Description: A Page Template for displaying Upwork API capability.\r\n *\/\r\n\r\nsession_start();\r\nrequire WP_UPWORK_PLUGIN_DIR . '\/vendor\/autoload.php';\r\n$access_token=get_option('wp_upwork_access_token');\r\n$access_token_secret=get_option('wp_upwork_access_token_secret');\r\nif($access_token &amp;&amp; $access_token_secret){\r\n    $config = new \\Upwork\\API\\Config(\r\n        array(\r\n            'consumerKey'       =&gt; get_option('wp_upwork_api_key'),  \/\/ SETUP YOUR CONSUMER KEY\r\n            'consumerSecret'    =&gt; get_option('wp_upwork_api_secret'),                  \/\/ SETUP YOUR KEY SECRET\r\n            'accessToken'       =&gt; $access_token,                   \/\/ got access token\r\n            'accessSecret'      =&gt; $access_token_secret,            \/\/ got access secret\r\n            'mode'              =&gt; 'web',                           \/\/ can be 'nonweb' for console apps (default),\r\n                                                                    \/\/ and 'web' for web-based apps\r\n            'debug'             =&gt; true, \/\/ enables debug mode. Note that enabling debug in web-based applications can block redirects\r\n            'authType'          =&gt; 'OAuthPHPLib' \/\/ your own authentication type, see AuthTypes directory\r\n        )\r\n    );\r\n    $client = new \\Upwork\\API\\Client($config);\r\n}else{\r\n    $config = new \\Upwork\\API\\Config(\r\n        array(\r\n            'consumerKey'       =&gt; get_option('wp_upwork_api_key'),  \/\/ SETUP YOUR CONSUMER KEY\r\n            'consumerSecret'    =&gt; get_option('wp_upwork_api_secret'),                  \/\/ SETUP YOUR KEY SECRET\r\n            'accessToken'       =&gt; $_SESSION['access_token'],                   \/\/ got access token\r\n            'accessSecret'      =&gt; $_SESSION['access_secret'],            \/\/ got access secret\r\n            'requestToken'      =&gt; $_SESSION['request_token'],      \/\/ got request token\r\n            'requestSecret'     =&gt; $_SESSION['request_secret'],     \/\/ got request secret\r\n            'verifier'          =&gt; $_GET['oauth_verifier'],         \/\/ got oauth verifier after authorization\r\n            'mode'              =&gt; 'web',                           \/\/ can be 'nonweb' for console apps (default),\r\n                                                                    \/\/ and 'web' for web-based apps\r\n            'debug'             =&gt; true, \/\/ enables debug mode. Note that enabling debug in web-based applications can block redirects\r\n            'authType'          =&gt; 'OAuthPHPLib' \/\/ your own authentication type, see AuthTypes directory\r\n        )\r\n    );\r\n    $client = new \\Upwork\\API\\Client($config);\r\n    if (empty($_SESSION['request_token']) &amp;&amp; empty($_SESSION['access_token'])) {\r\n        \/\/ we need to get and save the request token. It will be used again\r\n        \/\/ after the redirect from the Upwork site\r\n        $requestTokenInfo = $client-&gt;getRequestToken();\r\n        $_SESSION['request_token']  = $requestTokenInfo['oauth_token'];\r\n        $_SESSION['request_secret'] = $requestTokenInfo['oauth_token_secret'];\r\n        \/\/ request authorization\r\n        $client-&gt;auth();\r\n    } elseif (empty($_SESSION['access_token'])) {\r\n        \/\/ the callback request should be pointed to this script as well as\r\n        \/\/ the request access token after the callback\r\n        $accessTokenInfo = $client-&gt;auth();\r\n        $_SESSION['access_token']   = $accessTokenInfo['access_token'];\r\n        $_SESSION['access_secret']  = $accessTokenInfo['access_secret'];\r\n        \r\n        update_option('wp_upwork_access_token',$accessTokenInfo['access_token']);\r\n        update_option('wp_upwork_access_token_secret',$accessTokenInfo['access_secret']);\r\n    }\r\n}\r\n\r\n\/\/ $accessTokenInfo has the following structure\r\n\/\/ array('access_token' =&gt; ..., 'access_secret' =&gt; ...);\r\n\/\/ keeps the access token in a secure place\r\n\/\/ if authenticated\r\nif ($access_token) {\r\n\/\/if ($_SESSION['access_token']) {\r\n    \/\/var_dump($_SESSION);\r\n    \/\/ clean up session data\r\n    unset($_SESSION['request_token']);\r\n    unset($_SESSION['request_secret']);\r\n    \/\/ gets info of the authenticated user\r\n    $auth = new \\Upwork\\API\\Routers\\Auth($client);\r\n    $info = $auth-&gt;getUserInfo();\r\n    \r\n    \/\/$roles = new \\Upwork\\API\\Routers\\Hr\\Roles($client);\r\n    \/\/$info = $roles-&gt;getAll();\r\n    echo \"&lt;BR\/&gt;PROFILE:&lt;BR\/&gt;\".print_r($info);\r\n}<\/pre>\n<p>THE RESULT CAN&#8217;T BE EXPECTED BECAUSE UPWORK SERVER IS NOT RELIABLE ENOUGH!!!!. THIS SUPPOSED TO WORK BUT I GOT THIS ERROR<\/p>\n<pre class=\"lang:default decode:true \">File exist:&lt;br \/&gt;\r\n&lt;b&gt;Notice&lt;\/b&gt;:  Undefined index: access_token in &lt;b&gt;\/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/includes\/upwork-template.php&lt;\/b&gt; on line &lt;b&gt;30&lt;\/b&gt;&lt;br \/&gt;\r\n&lt;br \/&gt;\r\n&lt;b&gt;Notice&lt;\/b&gt;:  Undefined index: access_secret in &lt;b&gt;\/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/includes\/upwork-template.php&lt;\/b&gt; on line &lt;b&gt;31&lt;\/b&gt;&lt;br \/&gt;\r\n&lt;br \/&gt;\r\n&lt;b&gt;Notice&lt;\/b&gt;:  Undefined index: request_token in &lt;b&gt;\/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/includes\/upwork-template.php&lt;\/b&gt; on line &lt;b&gt;32&lt;\/b&gt;&lt;br \/&gt;\r\n&lt;br \/&gt;\r\n&lt;b&gt;Notice&lt;\/b&gt;:  Undefined index: request_secret in &lt;b&gt;\/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/includes\/upwork-template.php&lt;\/b&gt; on line &lt;b&gt;33&lt;\/b&gt;&lt;br \/&gt;\r\n&lt;br \/&gt;\r\n&lt;b&gt;Notice&lt;\/b&gt;:  Undefined index: oauth_verifier in &lt;b&gt;\/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/includes\/upwork-template.php&lt;\/b&gt; on line &lt;b&gt;34&lt;\/b&gt;&lt;br \/&gt;\r\n&gt; preparing Client.\r\n&gt; starting Upwork\\API\\AuthTypes\\AbstractOAuth authentication.\r\n&gt; getRequestToken.\r\n&gt; query request token from server.\r\n&gt; get OAuth instance.\r\n&gt; create full url, based on global constant.\r\n&gt; url, dump: 'https:\/\/www.upwork.com\/api\/auth\/v1\/oauth\/token\/request'.\r\n&gt; create full url, based on global constant.\r\n&gt; url, dump: 'https:\/\/www.upwork.com\/api\/auth\/v1\/oauth\/token\/access'.\r\n&lt;br \/&gt;\r\n&lt;b&gt;Fatal error&lt;\/b&gt;:  Uncaught exception 'OAuthException2' with message 'Unexpected result from the server &amp;quot;https:\/\/www.upwork.com\/api\/auth\/v1\/oauth\/token\/request&amp;quot; (503) while requesting a request token' in \/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/vendor\/upwork\/php-upwork\/vendor-src\/oauth-php\/library\/OAuthRequester.php:169\r\nStack trace:\r\n#0 \/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/vendor\/upwork\/php-upwork\/src\/Upwork\/API\/AuthTypes\/OAuthPHPLib.php(84): OAuthRequester::requestRequestToken('4e5c4df53acfe8d...', 0, Array, 'POST', Array, Array)\r\n#1 \/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/vendor\/upwork\/php-upwork\/src\/Upwork\/API\/Client.php(82): Upwork\\API\\AuthTypes\\OAuthPHPLib-&amp;gt;setupRequestToken()\r\n#2 \/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/includes\/upwork-template.php(45): Upwork\\API\\Client-&amp;gt;getRequestToken()\r\n#3 \/home\/teddy\/Documents\/works\/wordpress_local\/wp-includes\/template-loader.php(75): include('\/home\/teddy\/Doc...')\r\n#4 \/ in &lt;b&gt;\/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/vendor\/upwork\/php-upwork\/vendor-src\/oauth-php\/library\/OAuthRequester.php&lt;\/b&gt; on line &lt;b&gt;169&lt;\/b&gt;&lt;br \/&gt;<\/pre>\n<p>IT&#8217;S REALLY EMBARRASSING. I NEED TO WAIT A FEW HOURS TO TRY IT AGAIN!<br \/>\nOKAY. IT&#8217;S WORKING NOW. I MODIFIED &#8216;upwork-template.php&#8217; file like this:<\/p>\n<pre class=\"lang:default decode:true\">&lt;?php\r\n\/*\r\n * Template Name: Upwork Template\r\n * Description: A Page Template for displaying Upwork API capability.\r\n *\/\r\n\r\nsession_start();\r\n\r\n\/\/SOMETIMES I HAVE TO DO THIS (CLEAR THE SESSION) IF THERE IS SOMETHING WRONG ON THE AUTHENTICATION\/AUTHORIZATION PROCESS!! THEN COMMENT ITS AGAIN!\r\n\/*unset($_SESSION['callback_url']);\r\nunset($_SESSION['access_token']);\r\nunset($_SESSION['access_secret']);\r\nunset($_SESSION['request_token']);\r\nunset($_SESSION['request_secret']);\r\nexit;\r\n*\/\r\n\r\n    \r\nrequire WP_UPWORK_PLUGIN_DIR . '\/vendor\/autoload.php';\r\n$access_token=get_option('wp_upwork_access_token');\r\n$access_token_secret=get_option('wp_upwork_access_token_secret');\r\nif($access_token &amp;&amp; $access_token_secret){\r\n    $config = new \\Upwork\\API\\Config(\r\n        array(\r\n            'consumerKey'       =&gt; get_option('wp_upwork_api_key'),  \/\/ SETUP YOUR CONSUMER KEY\r\n            'consumerSecret'    =&gt; get_option('wp_upwork_api_secret'),                  \/\/ SETUP YOUR KEY SECRET\r\n            'accessToken'       =&gt; $access_token,                   \/\/ got access token\r\n            'accessSecret'      =&gt; $access_token_secret,            \/\/ got access secret\r\n            'mode'              =&gt; 'web',                           \/\/ can be 'nonweb' for console apps (default),\r\n                                                                    \/\/ and 'web' for web-based apps\r\n            'debug'             =&gt; false, \/\/ enables debug mode. Note that enabling debug in web-based applications can block redirects\r\n            'authType'          =&gt; 'OAuthPHPLib' \/\/ your own authentication type, see AuthTypes directory\r\n        )\r\n    );\r\n    $client = new \\Upwork\\API\\Client($config);\r\n}else{\r\n    if(empty($_SESSION['callback_url']))\r\n        $_SESSION['callback_url']='http' . (isset($_SERVER['HTTPS']) ? 's' : '') . ':\/\/' . \"{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}\";\r\n    \r\n    $config = new \\Upwork\\API\\Config(\r\n        array(\r\n            'consumerKey'       =&gt; get_option('wp_upwork_api_key'),  \/\/ SETUP YOUR CONSUMER KEY\r\n            'consumerSecret'    =&gt; get_option('wp_upwork_api_secret'),                  \/\/ SETUP YOUR KEY SECRET\r\n            'accessToken'       =&gt; $_SESSION['access_token'],                   \/\/ got access token\r\n            'accessSecret'      =&gt; $_SESSION['access_secret'],            \/\/ got access secret\r\n            'requestToken'      =&gt; $_SESSION['request_token'],      \/\/ got request token\r\n            'requestSecret'     =&gt; $_SESSION['request_secret'],     \/\/ got request secret\r\n            'verifier'          =&gt; $_GET['oauth_verifier'],         \/\/ got oauth verifier after authorization\r\n            'mode'              =&gt; 'web',                           \/\/ can be 'nonweb' for console apps (default),\r\n                                                                    \/\/ and 'web' for web-based apps\r\n            'debug'             =&gt; true, \/\/ enables debug mode. Note that enabling debug in web-based applications can block redirects\r\n            'authType'          =&gt; 'OAuthPHPLib' \/\/ your own authentication type, see AuthTypes directory\r\n        )\r\n    );\r\n    $client = new \\Upwork\\API\\Client($config);\r\n    if (empty($_SESSION['request_token']) &amp;&amp; empty($_SESSION['access_token'])) {\r\n        \/\/ we need to get and save the request token. It will be used again\r\n        \/\/ after the redirect from the Upwork site\r\n        $requestTokenInfo = $client-&gt;getRequestToken();\r\n        $_SESSION['request_token']  = $requestTokenInfo['oauth_token'];\r\n        $_SESSION['request_secret'] = $requestTokenInfo['oauth_token_secret'];\r\n        \/\/ request authorization\r\n        $client-&gt;auth();\r\n    } elseif (empty($_SESSION['access_token'])) {\r\n        \/\/ the callback request should be pointed to this script as well as\r\n        \/\/ the request access token after the callback\r\n        $accessTokenInfo = $client-&gt;auth();\r\n        $_SESSION['access_token']   = $accessTokenInfo['access_token'];\r\n        $_SESSION['access_secret']  = $accessTokenInfo['access_secret'];\r\n        \r\n        update_option('wp_upwork_access_token',$accessTokenInfo['access_token']);\r\n        update_option('wp_upwork_access_token_secret',$accessTokenInfo['access_secret']);\r\n\r\n        \/\/$redirect_url=\"http:\/\/localhost\/works\/wordpress_local\/upwork\/\";\r\n        header(\"Location:\".$_SESSION['callback_url']);\r\n    }\r\n}\r\n\r\n\/\/ $accessTokenInfo has the following structure\r\n\/\/ array('access_token' =&gt; ..., 'access_secret' =&gt; ...);\r\n\/\/ keeps the access token in a secure place\r\n\/\/ if authenticated\r\nif ($access_token) {\r\n\/\/if ($_SESSION['access_token']) {\r\n    \/\/var_dump($_SESSION);\r\n    \/\/ clean up session data\r\n    unset($_SESSION['callback_url']);\r\n    unset($_SESSION['access_token']);\r\n    unset($_SESSION['access_secret']);\r\n    unset($_SESSION['request_token']);\r\n    unset($_SESSION['request_secret']);\r\n    \r\n    \/\/ gets info of the authenticated user\r\n    \/\/$auth = new \\Upwork\\API\\Routers\\Auth($client);\r\n    \/\/$info = $auth-&gt;getUserInfo();\r\n    \r\n    \/\/$roles = new \\Upwork\\API\\Routers\\Hr\\Roles($client);\r\n    \/\/$info = $roles-&gt;getAll();\r\n    \/\/echo \"&lt;BR\/&gt;PROFILE:&lt;BR\/&gt;\".print_r($info);\r\n    $jobs = new \\Upwork\\API\\Routers\\Jobs\\Search($client);\r\n    $params=array(\r\n        \"q\"=&gt;\"laravel\",\r\n        \"page\"=&gt;\"0;5\"  \/\/page param is not working anyway!!!\r\n    );\r\n    $result = $jobs-&gt;find($params);\r\n\r\n    get_header(); ?&gt;\r\n        &lt;div id=\"job_result\" class=\"job_result\" style=\"margin-top: -50px;\"&gt;\r\n\r\n            &lt;?php \r\n                $i=1;\r\n                foreach($result-&gt;jobs as $j){\r\n                    echo $i.\". \".$j-&gt;title.\"&lt;br\/&gt;\";\r\n                    $i++;\r\n                }\r\n\r\n            ?&gt;\r\n\r\n        &lt;\/div&gt;&lt;!-- #primary --&gt;\r\n    &lt;?php get_sidebar(); ?&gt;\r\n    &lt;?php get_footer(); ?&gt;\r\n&lt;?php\r\n}<\/pre>\n<p>With this changes, I can store the access token in database when it haven&#8217;t it yet and use the tokens from repeat Upwork API call without having to get the new token. From https:\/\/developers.upwork.com\/?lang=php#authentication_get-access-token, IT SAID &#8220;Once created, the Access token never expires.&#8221;.<br \/>\nNOTE: the &#8216;config&#8217; parameters is different when we already have the tokens. it no need the &#8216;request token&#8217; anymore (see above code at if($access_token &amp;&amp; $access_token_secret){) .<br \/>\nNOTE: I also need to clear the sessions if there is any error related with the Upwork API occured. I think it&#8217;d be better to put a new button &#8216;Reset Access Token&#8217; on the WP Upwork admin settings. The button would empty the tokens values in the database. This would give a chance to get the new token and fix the errors. The button would also be responsible to clear the sessions!<br \/>\nThis is a screenshots of the Upwork API to display job listing by some criteria. <a href=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-jobs.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1186\" src=\"http:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-jobs.png\" alt=\"wp-plugin-upwork-jobs\" width=\"709\" height=\"425\" srcset=\"https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-jobs.png 709w, https:\/\/myprojects.advchaweb.com\/wp-content\/uploads\/2016\/11\/wp-plugin-upwork-jobs-300x180.png 300w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px\" \/><\/a>NOTE: SOMEHOW I CAN&#8217;T MANAGE HOW TO GET THE RESULT MORE THAN 10 DATA<br \/>\nNEXT: HOW TO CATCH ANY ERROR FROM THE UPWORK API???<br \/>\nCREATE a new button &#8216;Reset Access Token&#8217; on the WP Upwork admin settings.<\/li>\n<li>SOME ERROR HAS HAPPENED. HERE THEY ARE AND THE SOLUTIONS:\n<pre class=\"lang:default decode:true \">&lt;br \/&gt;\r\n&lt;b&gt;Fatal error&lt;\/b&gt;:  Uncaught exception 'OAuthException2' with message 'Request failed with code 400: {&amp;quot;server_time&amp;quot;:1480603525,&amp;quot;error&amp;quot;:{&amp;quot;status&amp;quot;:400,&amp;quot;code&amp;quot;:400,&amp;quot;message&amp;quot;:&amp;quot;Your request has a missing obligatory OAuth parameter [oauth_token].&amp;quot;}}' in \/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/vendor\/upwork\/php-upwork\/vendor-src\/oauth-php\/library\/OAuthRequester.php:117\r\nStack trace:\r\n#0 \/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/vendor\/upwork\/php-upwork\/src\/Upwork\/API\/AuthTypes\/OAuthPHPLib.php(59): OAuthRequester-&amp;gt;doRequest(0, Array)\r\n#1 \/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/vendor\/upwork\/php-upwork\/src\/Upwork\/API\/Client.php(150): Upwork\\API\\AuthTypes\\OAuthPHPLib-&amp;gt;request('GET', '\/profiles\/v2\/se...', Array)\r\n#2 \/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/vendor\/upwork\/php-upwork\/src\/Upwork\/API\/Client.php(166): Upwork\\API\\Client-&amp;gt;_request('GET', '\/profiles\/v2\/se...', Array)\r\n#3 \/home\/teddy\/Documents\/works\/wordpress_local\/wp-conte in &lt;b&gt;\/home\/teddy\/Documents\/works\/wordpress_local\/wp-content\/plugins\/upwork\/vendor\/upwork\/php-upwork\/vendor-src\/oauth-php\/library\/OAuthRequester.php&lt;\/b&gt; on line &lt;b&gt;117&lt;\/b&gt;&lt;br \/&gt;<\/pre>\n<p>SOLUTIONS: Clear the sessions and empty the tokens values in the database then refresh the page again!<\/li>\n<li>Now, I already put the source code in my github repository: <a href=\"https:\/\/github.com\/advcha\/upwork\">https:\/\/github.com\/advcha\/upwork<\/a>.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Ref: APIS, WORDPRESS TIPS AND TRICKS, USING OAUTH IN WORDPRESS PLUGINS, PART 1: THE BASICS \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 How to write a WordPress plugin Make sure you already registered on Upwork (https:\/\/upwork.com) and have any Upwork key. If not go to https:\/\/developers.upwork.com and get the keys (API Key, API secret, redirect URL, etc). Apply for the API &hellip; <a href=\"https:\/\/myprojects.advchaweb.com\/index.php\/2016\/11\/28\/wordpress-plugin-to-connect-to-upwork-api\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;WordPress Plugin to Connect to Upwork API&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[45,13,44],"tags":[],"class_list":["post-1132","post","type-post","status-publish","format-standard","hentry","category-api-2","category-tutorial","category-wordpress-tutorial"],"_links":{"self":[{"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/posts\/1132","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/comments?post=1132"}],"version-history":[{"count":33,"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/posts\/1132\/revisions"}],"predecessor-version":[{"id":8691,"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/posts\/1132\/revisions\/8691"}],"wp:attachment":[{"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/media?parent=1132"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/categories?post=1132"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/tags?post=1132"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}