Get new acess_token after 3600 seconds - google-analytics

I'm trying to use google analytics api. I've already added the service account email that was created to the user list for the Google Analytics account in question.
I got the access_token and the refresh_token. But I do not know how to get the new access_token after 3600 seconds without the client having to re-authorize.
oauth2callback.php
<?php
require_once __DIR__.'/vendor/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$client->addScope(Google_Service_Analytics::ANALYTICS_READONLY);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
if (! isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
index.php
<?php
require_once __DIR__.'/vendor/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfig('client_secrets.json');
$client->setAccessType("offline");
$client->setIncludeGrantedScopes(true);
$client->setApprovalPrompt('force');
$client->addScope(Google_Service_Analytics::ANALYTICS_READONLY);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
print_r($_SESSION['access_token']);
} else {
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
After allowing access, the tokens generate normally. But I would like to get the new access_token automatically after 3600 seconds without the client having to give permission again.
Is this possible?
print_r($_SESSION['access_token']);
Array
(
[access_token] => ya29.GltpBl_Dkmt-uT9Z6t5aTSzKLmzsWP3xZCcVtRt8kLIOJj5M_TpLg-0x4Sm0eNxOLpdCahFy6Ec41nHnF-vhh-m3tbj7ecR-QHaR8vkP3ImYjuo_WPBLXBKMXCna
[expires_in] => 3600
[scope] => https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/analytics.readonly https://www.googleapis.com/auth/plus.me
[token_type] => Bearer
[id_token] => eyJhbGciOiJSUzI1NiIsImtpZCI6IjQ2M2ZlNDgwYzNjNTgzOWJiYjE1ODYxZTA4YzMyZDE4N2ZhZjlhNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI5NzI5NDE4MzY0MzctZ2o2ZmtxNHZ1NjU3dDkyMzhucDVyajY5NjRqZ3NyMWouYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI5NzI5NDE4MzY0MzctZ2o2ZmtxNHZ1NjU3dDkyMzhucDVyajY5NjRqZ3NyMWouYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDM3NzMzMDA1MzYwNTk3MzI0OTAiLCJlbWFpbCI6ImZhYnJpY2lvdmllaXJhLnN0ckBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6IndQcVUxc1I4c3Z6bFBBSWRUSjZoNGciLCJpYXQiOjE1NDQwMjg2MjEsImV4cCI6MTU0NDAzMjIyMX0.g_3w66FxAGViuXxFDGR2oErlo1yIMk376iDdOpgv8EfVz764hBywc-DuNXPE2y5p4nTd_y6oWbH7mK2DvFIGd7b_BLsNJJaZjJBFBHNk9Q1Z5VrpeZ9T1-0gQiXu0xS0pBdRnEtDwZN7qlL4_op6ojfHT02HbmyrlpdCbnp57LN5zJkufnL4VhQYp3Rqsui4ttL1VT0KBaHjzIzL6zWMuuMBdXKk9Ug6J1KuR0xCuWGytjb2y-YpsHVrgqvOfMEeAnxcpv6-ilUEpc-Mo4ZL4NGsDjK2BGFVCwfxZctzgERwSzYyH9P6g_raIJpqyXGvASOvkPJ7xHGI1wWO4QGsxA
[created] => 1544028621
[refresh_token] => 1/ifyxSjTnwv5kFMPcPEENx8kRWNSFmTYZUjMxcHJl8spoQqWdmaNh1ZjV3W2qR16W
)
1

The code you are using is not the code for a service account. If you are using the Code for a service account you dont need to worry about refreshing anything becouse it doesnt have a refresh token it just always has access.
require_once __DIR__ . '/vendor/autoload.php';
// Use the developers console and download your service account
// credentials in JSON format. Place the file in this directory or
// change the key file location if necessary.
putenv('GOOGLE_APPLICATION_CREDENTIALS='.__DIR__.'/service-account.json');
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
* Initializes a client object.
* #return A google client object.
*/
function getGoogleClient() {
return getServiceAccountClient();
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/api-client-library/php/auth/service-accounts
* Scopes will need to be changed depending upon the API's being accessed.
* array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* #return A google client object.
*/
function getServiceAccountClient() {
try {
// Create and configure a new client object.
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope([YOUR SCOPES HERE]);
return $client;
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
ServiceAccount.php

Sorted out:
<?php
require_once __DIR__ . '/vendor/autoload.php';
$KEY_FILE_LOCATION = __DIR__ . '/service-account.json';
$client = new Google_Client();
$client->setAuthConfig($KEY_FILE_LOCATION);
$client->setAccessType('offline');
$client->setScopes(['https://www.googleapis.com/auth/analytics.readonly']);
$client->refreshTokenWithAssertion();
$analytics = new Google_Service_Analytics($client);
$token = $client->getAccessToken();
?>
<!DOCTYPE html>
<html>
<head>
<title>Embed API Demo</title>
<style>
body{
overflow: hidden;
}
</style>
</head>
<body>
<!-- Step 1: Create the containing elements. -->
<div id="chart-1-container"></div>
<div id="chart-2-container"></div>
<!-- Step 2: Load the library. -->
<script>
(function(w,d,s,g,js,fs){
g=w.gapi||(w.gapi={});g.analytics={q:[],ready:function(f){this.q.push(f);}};
js=d.createElement(s);fs=d.getElementsByTagName(s)[0];
js.src='https://apis.google.com/js/platform.js';
fs.parentNode.insertBefore(js,fs);js.onload=function(){g.load('analytics');};
}(window,document,'script'));
</script>
<script>
gapi.analytics.ready(function() {
/**
* Authorize the user with an access token obtained server side.
*/
gapi.analytics.auth.authorize({
'serverAuth': {
'access_token': '<?php echo $token['access_token']; ?>'
}
});
/**
* Creates a new DataChart instance showing sessions over the past 30 days.
* It will be rendered inside an element with the id "chart-1-container".
*/
var dataChart1 = new gapi.analytics.googleCharts.DataChart({
query: {
'ids': 'ga:171325437', // <-- Replace with the ids value for your view.
'start-date': '30daysAgo',
'end-date': 'yesterday',
'metrics': 'ga:sessions,ga:users',
'dimensions': 'ga:date'
},
chart: {
'container': 'chart-1-container',
'type': 'LINE',
'options': {
'width': '100%'
}
}
});
dataChart1.execute();
/**
* Creates a new DataChart instance showing top 5 most popular demos/tools
* amongst returning users only.
* It will be rendered inside an element with the id "chart-3-container".
*/
var dataChart2 = new gapi.analytics.googleCharts.DataChart({
query: {
'ids': 'ga:171325437', // <-- Replace with the ids value for your view.
'start-date': '30daysAgo',
'end-date': 'yesterday',
'metrics': 'ga:pageviews',
'dimensions': 'ga:pagePathLevel1',
'sort': '-ga:pageviews',
'filters': 'ga:pagePathLevel1!=/',
'max-results': 7
},
chart: {
'container': 'chart-2-container',
'type': 'PIE',
'options': {
'width': '100%',
'pieHole': 4/9,
}
}
});
dataChart2.execute();
});
</script>
</body>
</html>

Related

WooCommerce WC()->session->set not working

I want to add some of the fields from a form into custom fields on a product so I can use them into an API call after payment is made. I have a redirection on my form that gets to the checkout page and add the product in the basket, code below:
<script>
document.addEventListener( 'wpcf7mailsent', function( event ) {
if (jQuery("input[type='checkbox'][name='try[]']").is(':checked')) {
location = 'http://www.thelittlegym.co.za/checkout/?add-to-cart=2506';
}
}, false );
</script>
Then, I have some code in my function.php to save the form data in the WC session.
I had to add declare the new session otherwise the set function didn't work.
If I do the init then I get an error saying "wc_empty_cart();" isn't defined (this function is from the WooCommerce plugin.
add_action('wpcf7_before_send_mail', 'send_form_data_to_wc_session', 5, 1);
function send_form_data_to_wc_session($contact_form) {
$submission = WPCF7_Submission::get_instance();
if($submission) {
$posted_data = $submission->get_posted_data();
if (!empty($posted_data['try'][0])) {
// Set data to WooCommerce session
WC()->session = new WC_Session_Handler();
// WC()->session->init();
WC()->session->set('cf7_posted_data', $posted_data);
}
}
}
Finally, I'm trying to retrieve the session data with the code below.
The var dump just returns NULL.
add_action('woocommerce_checkout_before_customer_details', 'wc_save_cf7_data_to_order', 10, 1);
function wc_save_cf7_data_to_order($order_id) {
$posted_data = WC()->session->get('cf7_posted_data');
var_dump($posted_data);
if(!empty($posted_data)) {
foreach($posted_data as $key => $data) {
echo '<b>', $key, ' : </b> ', $data, '<br />';
}
WC()->session->__unset('cf7_posted_data');
}
}
I believe the WC session set isn't working. I'm looking in the console for the Session Storage and can only see "wc_cart_hash_xxxxxxx", "wc_fragment_xxxxxxx" and "wc_cart_created".
Any idea how I can go ahead to debug this?
I've found an alternative solution on another topic, which solved my problem even if it doesn't explain why the code above didn't work.
add_action('wpcf7_before_send_mail', 'send_form_data_to_wc_session', 5, 1);
function send_form_data_to_wc_session($contact_form) {
$submission = WPCF7_Submission::get_instance();
if($submission) {
$posted_data = $submission->get_posted_data();
if (!empty($posted_data['try'][0])) {
// Set data to Session
session_start();//place this at the top of all code
$_SESSION['cf7_posted_data']=$posted_data;
}
}
}
and to retrieve:
add_action('woocommerce_checkout_before_customer_details', 'wc_save_cf7_data_to_order', 10, 1);
function wc_save_cf7_data_to_order($order_id) {
session_start();
$posted_data = $_SESSION['cf7_posted_data'];
var_dump($posted_data);
}

How to add events to Google Calendar using FullCalendar?

I'm trying in my FullCalendar add events to my google calendar, followed the example below,
How to add events to Google Calendar using FullCalendar
but does not work me, if anyone knows how to do please help.
this my code
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'/>
<link href='../fullcalendar.css' rel='stylesheet'/>
<link href='../fullcalendar.print.css' rel='stylesheet' media='print'/>
<script src='../lib/moment.min.js'></script>
<script src='../lib/jquery.min.js'></script>
<script src='../fullcalendar.min.js'></script>
<script src='../gcal.js'></script>
<script>
$(document).ready(function () {
$('#calendar').fullCalendar({
selectable: true,
selectHelper: true,
var eventData, title;
select: function(start, end) {
title = prompt('Event Title:');
},
editable: true
}
if (title) {
$('#calendar').fullCalendar('renderEvent',
{
title: title,
start: start,
end: end
},
true // make the event "stick"
);
// Now we push it to Google also :
add_event_gcal(title,start,end);
}
}
$('#calendar').fullCalendar('unselect');
});
});
/****** NOW WE ASK THE EVENT TO BE PUSHED TO GOOGLE **************/
function add_event_gcal(title,start,end) {
alert(title);
// I will create the eventInsert script in a new page, and I name it here :
var url = "php/calendrier_add.php",
data = {'titre_event' :title, 'start' : start, 'end' :end};
// I want to check in the page the result of what happened
$('#gcal_loader').load(url,data,function(responseTxt,statusTxt,xhr){
if(statusTxt == "error") alert("Error: " + xhr.status + ": " + xhr.statusText);
});
}
</script>
<style>
body {
margin: 40px 10px;
padding: 0;
font-family: "Lucida Grande", Helvetica, Arial, Verdana, sans-serif;
font-size: 14px;
}
#loading {
display: none;
position: absolute;
top: 10px;
right: 10px;
}
#calendar {
max-width: 900px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id='loading'>loading...</div>
<div id='calendar'></div>
</body>
</html>
this is file php
<?php
// variables can only be got with $_REQUEST ?
$titre_event = $_REQUEST['titre_event'];
$start = $_REQUEST['start'];
$end = $_REQUEST['end'];
$allday = $_REQUEST['allday'];
/*$where_event = $_REQUEST['where_event'];
$content_event = $_REQUEST['content_event'];*/
/********************************************
GOOGLE API CONNECTION
********************************************/
/************************************************
Make an API request authenticated with a service account.
************************************************/
require_once realpath(dirname(__FILE__) . '/../google/autoload.php');// or wherever autoload.php is located
$path = realpath(dirname(__FILE__) . '/../google/autoload.php');
/************************************************
The name is the email address value provided as part of the service account (not your address!)
cf. : https://console.developers.google.com/project/<your account>
************************************************/
$client_id = '1020443454327******'; // YOUR Client ID
$service_account_name ='102044345*****'; // Email Address in the console account
$key_file_location = realpath(dirname(__FILE__) . '/../google/Mi proyecto-edc74d9206de.p12'); // key.p12 to create in the Google API console
echo "key".$key_file_location;
if (strpos($client_id, "googleusercontent") == false || !strlen($service_account_name) || !strlen($key_file_location)) {
echo "no credentials were set.";
exit;
}
/** We create service access ***/
$client = new Google_Client();
/************************************************
If we have an access token, we can carry on. (Otherwise, we'll get one with the help of an assertion credential.)
Here we have to list the scopes manually. We also supply the service account
************************************************/
if (isset($_SESSION['service_token'])) {
$client->setAccessToken($_SESSION['service_token']);
}
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array('https://www.googleapis.com/auth/calendar'), // ou calendar_readonly
$key
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();
/********************************************
END OF GOOGLE API CONNECTION
********************************************/
/*********** AT LAAAAST, WE PUSH THE EVENT IN GOOGLE CALENDAR ***************/
// Get the API client and construct the service object.
$service = new Google_Service_Calendar($client);
// We get the calendar
$calendarId = 'qv8rv593gn5g8pumu0bid6bco0#group.calendar.google.com'; // or whatever calendar you like where you have editable rights
/************* INSERT ****************/
$event = new Google_Service_Calendar_Event(array(
'summary' => $titre_event,
//'location' => $where_event,
// 'description' => $content_event,
'start' => array(
'dateTime' => $start, //'2015-06-08T15:00:00Z'
'timeZone' => 'Europe/Paris',
),
'end' => array(
'dateTime' => $end,
'timeZone' => 'Europe/Paris',
),
/* in case you need that :
'attendees' => array(
array('email' => 'lpage#example.com'),
array('email' => 'sbrin#example.com'),
),*/
'reminders' => array(
'useDefault' => FALSE,
'overrides' => array(
array('method' => 'email', 'minutes' => 20)
),
),
));
$event = $service->events->insert($calendarId, $event);
printf('Event created: %s', $event->htmlLink);
?>
I found the answer
https://developers.google.com/google-apps/calendar/v3/reference/events/insert#examples
1)
//Global variables to access the calendar
clientId = 'Your cliendID',
scopes = 'https://www.googleapis.com/auth/calendar',
calendarId = 'Your google calendar id',
eventsList = [];
//Autorice the user
checkAuth();
//authorization in google
function checkAuth() {
gapi.auth.authorize(
{
'client_id': clientId,
'scope': scopes,
'immediate': true
}, handleAuthResult);
}
//checks if authorized
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
loadCalendarApi();
} else {
handleAuthClick();
}
}
//request credentials
function handleAuthClick() {
gapi.auth.authorize(
{
client_id: clientId,
scope: scopes,
immediate: false
}, handleAuthResult);
return false;
}
function loadCalendarApi() {
gapi.client.load('calendar', 'v3', makeApiCall);
}`
2)
// Load the API and make an API call. Display the results on the screen.
function makeApiCall() {
requestList = gapi.client.calendar.events.list({
'calendarId': calendarId
});
console.log('--- eventsList ---');
console.log(eventsList);
uiCalendarConfig.calendars['myCalendar'].fullCalendar('removeEventSource', eventsList);
eventsList = [];
// Step 6: Execute the API request
requestList
.then(function (resp) {
if (resp.result.error) {
reportError('Google Calendar API: ' + data.error.message, data.error.errors);
} else if (resp.result.items) {
resp.result.items.forEach(function (entry, index) {
eventsList.push({
id: entry.id,
title: entry.summary,
start: entry.start.dateTime || entry.start.date, // try timed. will fall back to all-day
end: entry.end.dateTime || entry.end.date, // same
url: url,
location: entry.location,
description: entry.description
});
});
}
if (eventsList.length > 0) {
uiCalendarConfig.calendars['myCalendar'].fullCalendar('addEventSource', eventsList, true);
}
}, function (reason) {
console.log('Error: ' + reason.result.error.message);
});
}`
3)
//insert into calendar
function makeRpcRequest(eventData) {
gapi
.client
.load('calendar', 'v3')
.then(function () {
request = gapi.client.calendar.events.insert({
'calendarId': calendarId,
'resource': eventData
});
request.then(function (resp) {
if (resp.result.error) {
reportError('Google Calendar API: ' + data.error.message, data.error.errors);
} else {
makeApiCall();
console.log(resp);
var creator = resp.result.creator.email;
var calendarEntry = resp.result.htmlLink;
console.log('--- Calendar entry successfully created by---');
console.log(creator);
console.log('--- dd ---');
console.log(calendarEntry);
}
}, function (reason) {
console.log('Error: ' + reason.result.error.message);
});
});
}`

Upload image/video to facebook asynchronously using php sdk 4

I am trying to upload video/image to facebook albumb using php sdk 4 asynchronously.I googled and found that php asynchronous call be sent using fsockopen. However, it is not working for facebook request. I have two files, one for checking login and getting token. Then second file is called for uploading the file to facebook. Below is the code for first file:
// start session
session_start();
Yii::import('application.vendor.*');
require_once('facebook-4/autoload.php');
use Facebook\HttpClients\FacebookHttpable;
use Facebook\HttpClients\FacebookCurl;
use Facebook\HttpClients\FacebookCurlHttpClient;
use Facebook\Entities\AccessToken;
use Facebook\Entities\SignedRequest;
use Facebook\FacebookSession;
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookRequest;
use Facebook\FacebookResponse;
use Facebook\FacebookSDKException;
use Facebook\FacebookRequestException;
use Facebook\FacebookOtherException;
use Facebook\FacebookAuthorizationException;
use Facebook\GraphObject;
use Facebook\GraphSessionInfo;
// init app with app id and secret
FacebookSession::setDefaultApplication('xxxxx', 'yyyy');
// login helper with redirect_uri
$helper = new FacebookRedirectLoginHelper( 'http://website.com/user/login/page/view/fb-share-php1' );
// see if a existing session exists
if ( isset( $_SESSION ) && isset( $_SESSION['fb_token'] ) ) {
// create new session from saved access_token
$session = new FacebookSession( $_SESSION['fb_token'] );
// validate the access_token to make sure it's still valid
try {
if ( !$session->validate() ) {
$session = null;
}
}catch ( Exception $e ) {
// catch any exceptions
$session = null;
}
}
if ( !isset( $session ) || $session === null ) {
// no session exists
try {
$session = $helper->getSessionFromRedirect();
} catch( FacebookRequestException $ex ) {
// When Facebook returns an error
// handle this better in production code
print_r( $ex );
} catch( Exception $ex ) {
// When validation fails or other local issues
// handle this better in production code
print_r( $ex );
}
}
// see if we have a session
if ( isset( $session ) ) {
// save the session
$_SESSION['fb'] = $session;
$_SESSION['fb_token'] = $session->getToken();
// create a session using saved token or the new one we generated at login
//$session = new FacebookSession( $session->getToken() );
// graph api request for user data
//$request = new FacebookRequest( $session, 'GET', '/me' );
//$response = $request->execute();
backgroundPost('http://website.com/user/login/page/view/fb-share-php');
// get response
//$graphObject = $response->getGraphObject()->asArray();
// print profile data
//echo '<pre>' . print_r( $graphObject, 1 ) . '</pre>';
// print logout url using session and redirect_uri (logout.php page should destroy the session)
echo 'Logout';
}else {
// show login url
echo 'Login';
}
function backgroundPost($url){
$parts=parse_url($url);
//print_r($parts);exit;
$fp = fsockopen($parts['host'],
isset($parts['port'])?$parts['port']:80,
$errno, $errstr, 30);
if (!$fp) {
echo "test";
return false;
} else {
$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ". 0 ."\r\n";
$out .= "Cookie: PHPSESSID=" . $_COOKIE['PHPSESSID'] . "\r\n";
$out .= "Connection: Close\r\n\r\n";
if (isset($parts['query'])) $out.= $parts['query'];
// print_r($out);exit;
fwrite($fp, $out);
fclose($fp);
return true;
}
}
And second file is:
// start session
session_start();
Yii::import('application.vendor.*');
require_once('facebook-4/autoload.php');
use Facebook\HttpClients\FacebookHttpable;
use Facebook\HttpClients\FacebookCurl;
use Facebook\HttpClients\FacebookCurlHttpClient;
use Facebook\Entities\AccessToken;
use Facebook\Entities\SignedRequest;
use Facebook\FacebookSession;
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookRequest;
use Facebook\FacebookResponse;
use Facebook\FacebookSDKException;
use Facebook\FacebookRequestException;
use Facebook\FacebookOtherException;
use Facebook\FacebookAuthorizationException;
use Facebook\GraphObject;
use Facebook\GraphSessionInfo;
$session = $_SESSION['fb'] ;
file_put_contents('file.txt', serialize($session));
try {
// Upload to a user's profile. The photo will be in the
// first album in the profile. You can also upload to
// a specific album by using /ALBUM_ID as the path
$response = (new FacebookRequest(
$session, 'POST', '/me/photos', array(
'source' => '#/var/www/website-root/images/add_more.png',
'message' => 'User provided message'
)
))->execute()->getGraphObject();
file_put_contents('files.txt', serialize($session));
// If you're not using PHP 5.5 or later, change the file reference to:
// 'source' => '#/path/to/file.name'
//echo "Posted with id: " . $response->getProperty('id');
} catch(FacebookRequestException $e) {
echo "Exception occured, code: " . $e->getCode();
echo " with message: " . $e->getMessage();
}
Finally, I figured out the way to achieve it. Now, I am using facebook javascript sdk with php sdk. Following is the process:
1)Get access token from javascript sdk(first file) and pass it to background along with the url of image/video. Code may be modified, if image/video is being uploaded through source.
2) php file(2nd file) containing function for executing backend-process(which is in third file) receives the posted data and and call the third file(in the form of url) and pass the data to it as well.
3) File(s) are uploaded to facebook through php sdk 4(third file)
Below is the code for first file containing javascript sdk code:
<script>
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
window.fbAsyncInit = function() {
FB.init({
appId : 'your app id',
xfbml : true,
version : 'v2.0'
});
FB.login(function(response){
console.log(response);
if (response.status === 'connected') {
var data = new Array();
alert('Logged into your app and Facebook.');
//type: 0 for photo and type:1 for video. Create data array dynamically for real word applications
data[0]= {url: 'http://url-of-video-file.mov',privacy : 'SELF', message: "title of video", type:1};
data[1]= {url: 'http://url-to-image-file.png',privacy : 'SELF', message: "photo caption", type:0};
$.ajax({
url: 'http://url-of-second-file/containing-code-for/backend-process',
data: {data: data, accessToken:response.authResponse.accessToken},
type: 'POST',
success:function(){
alert("photo uploaded");
}
});
},{scope:'email'});
}
</script>
Now code of second file which receives data and execute back-end process:
<?php
//session_start();
ignore_user_abort(true);
set_time_limit(0);
function backgroundPost($url){
$parts=parse_url($url);
//print_r($parts);exit;
$fp = fsockopen($parts['host'],
isset($parts['port'])?$parts['port']:80,
$errno, $errstr, 30);
if (!$fp) {
echo "test";
return false;
} else {
$vars = $_POST;
$content = http_build_query($vars);
//file_put_contents('url.txt',$content);exit;
$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ". strlen($content) ."\r\n";
//$out .= "Cookie: PHPSESSID=" . $_COOKIE['PHPSESSID'] . "\r\n";
$out .= "Connection: Close\r\n\r\n";
if (isset($parts['query'])) $out.= $parts['query'];
// print_r($out);exit;
fwrite($fp, $out);
fwrite($fp,$content);
fclose($fp);
return true;
}
}
backgroundPost('http://link-to-third-file/containing-code-for-facebook-upload');
Now code of third file, which will actually upload the files. Please note, video files need to be downloaded before it can be uploaded.
<?php
// start session
//session_start();
error_reporting(1);
ignore_user_abort(true);
set_time_limit(0);
#ini_set('display_errors', 1);
//include facebook library through autoload
require_once('facebook-4/autoload.php');
use Facebook\HttpClients\FacebookHttpable;
use Facebook\HttpClients\FacebookCurl;
use Facebook\HttpClients\FacebookCurlHttpClient;
use Facebook\Entities\AccessToken;
use Facebook\Entities\SignedRequest;
use Facebook\FacebookSession;
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookRequest;
use Facebook\FacebookResponse;
use Facebook\FacebookSDKException;
use Facebook\FacebookRequestException;
use Facebook\FacebookOtherException;
use Facebook\FacebookAuthorizationException;
use Facebook\GraphObject;
use Facebook\GraphSessionInfo;
// init app with app id and secret
FacebookSession::setDefaultApplication('app_id','secret_key' );
$session = new FacebookSession( $_POST['accessToken'] );
foreach($_POST['data'] as $key => $data){
if($data['type'] == 1){
$ext = substr($data['url'],strrpos($data['url'],'.'));
$file = '/path/to/temp/location/for/saving/video/'.time().$ext;
if(file_put_contents($file,file_get_contents($data['url']))){
try {
// Upload to a user's profile. The photo will be in the
// first album in the profile. You can also upload to
// a specific album by using /ALBUM_ID as the path
$response = (new FacebookRequest(
$session, 'POST', '/me/videos', array(
'source' => '#'.$file,
'title' => $data['message'],
'privacy' => json_encode(array('value' => $data['privacy'])),
'published' => true
)
))->execute()->getGraphObject()->asArray();
// If you're not using PHP 5.5 or later, change the file reference to:
// 'source' => '#/path/to/file.name'
//echo "Posted with id: " . $response->getProperty('id');
} catch(FacebookRequestException $e) {
echo "Exception occured, code: " . $e->getCode();
echo " with message: " . $e->getMessage();
}
}
}else{
try {
// Upload to a user's profile. The photo will be in the
// first album in the profile. You can also upload to
// a specific album by using /ALBUM_ID as the path
$response = (new FacebookRequest(
$session, 'POST', '/me/photos', array(
'url' => $data['url'],
'message' => $data['message'],
'privacy' => json_encode(array('value' => $data['privacy'])),
'published' => true
)
))->execute()->getGraphObject()->asArray();
// If you're not using PHP 5.5 or later, change the file reference to:
// 'source' => '#/path/to/file.name'
//echo "Posted with id: " . $response->getProperty('id');
} catch(FacebookRequestException $e) {
echo "Exception occured, code: " . $e->getCode();
echo " with message: " . $e->getMessage();
}
}
}
?>

Improving FrontEnd Uploads in Wordpress

I want to improve the process of uploading pictures in a Real Estate Website. This website is running WordPress 3.8. The theme offers front end submission with a very simple interface. The user selects the images (one by one) and then clicks to add. Finally when the user submit the listing all the images are uploaded at once. This is the screenshot of how it looks: Original Option: Listing Images.
This is the JQuery Plugin I am currently using,
/*!
* jQuery imagesLoaded plugin v2.1.1
* http://github.com/desandro/imagesloaded
*
* MIT License. by Paul Irish et al.
*/
/*jshint curly: true, eqeqeq: true, noempty: true, strict: true, undef: true, browser: true */
/*global jQuery: false */
;(function($, undefined) {
'use strict';
// blank image data-uri bypasses webkit log warning (thx doug jones)
var BLANK = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';
$.fn.imagesLoaded = function( callback ) {
var $this = this,
deferred = $.isFunction($.Deferred) ? $.Deferred() : 0,
hasNotify = $.isFunction(deferred.notify),
$images = $this.find('img').add( $this.filter('img') ),
loaded = [],
proper = [],
broken = [];
// Register deferred callbacks
if ($.isPlainObject(callback)) {
$.each(callback, function (key, value) {
if (key === 'callback') {
callback = value;
} else if (deferred) {
deferred[key](value);
}
});
}
function doneLoading() {
var $proper = $(proper),
$broken = $(broken);
if ( deferred ) {
if ( broken.length ) {
deferred.reject( $images, $proper, $broken );
} else {
deferred.resolve( $images );
}
}
if ( $.isFunction( callback ) ) {
callback.call( $this, $images, $proper, $broken );
}
}
function imgLoadedHandler( event ) {
imgLoaded( event.target, event.type === 'error' );
}
function imgLoaded( img, isBroken ) {
// don't proceed if BLANK image, or image is already loaded
if ( img.src === BLANK || $.inArray( img, loaded ) !== -1 ) {
return;
}
// store element in loaded images array
loaded.push( img );
// keep track of broken and properly loaded images
if ( isBroken ) {
broken.push( img );
} else {
proper.push( img );
}
// cache image and its state for future calls
$.data( img, 'imagesLoaded', { isBroken: isBroken, src: img.src } );
// trigger deferred progress method if present
if ( hasNotify ) {
deferred.notifyWith( $(img), [ isBroken, $images, $(proper), $(broken) ] );
}
// call doneLoading and clean listeners if all images are loaded
if ( $images.length === loaded.length ) {
setTimeout( doneLoading );
$images.unbind( '.imagesLoaded', imgLoadedHandler );
}
}
// if no images, trigger immediately
if ( !$images.length ) {
doneLoading();
} else {
$images.bind( 'load.imagesLoaded error.imagesLoaded', imgLoadedHandler )
.each( function( i, el ) {
var src = el.src;
// find out if this image has been already checked for status
// if it was, and src has not changed, call imgLoaded on it
var cached = $.data( el, 'imagesLoaded' );
if ( cached && cached.src === src ) {
imgLoaded( el, cached.isBroken );
return;
}
// if complete is true and browser supports natural sizes, try
// to check for image status manually
if ( el.complete && el.naturalWidth !== undefined ) {
imgLoaded( el, el.naturalWidth === 0 || el.naturalHeight === 0 );
return;
}
// cached images don't fire load sometimes, so we reset src, but only when
// dealing with IE, or image is complete (loaded) and failed manual check
// webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
if ( el.readyState || el.complete ) {
el.src = BLANK;
el.src = src;
}
});
}
return deferred ? deferred.promise( $this ) : $this;
};
})(jQuery);
My goal is to have a more flexible system, where all the images can be selected at the same time and it starts loading right away. This will speed up the process and improve user experience. Also to arrange them in any order by moving them around. This is an example I found on another website. See screenshot: New Option: Multiple Image Upload
What programing language is good for this development? Any recommendations of where I can find code snippets for this application? Thanks in advance for your help!!
rough draft.....you need jquery and wordpress media js..just watch the js variable names below if there are errors it will be with these...
php in functions file:
if(function_exists( 'wp_enqueue_media' )){
wp_enqueue_media();
}
javascript...add to the page header..wp_enqueue_scripts or to your template (do this first to make sure its working!) you'll need your element called upload_image_button or change accordinely
// Uploading files
var media_uploader;
jQuery('.upload_image_button').live('click', function( event ){
var button = jQuery( this );
// If the media uploader already exists, reopen it.
if ( media_uploader ) {
media_uploader.open();
return;
}
// Create the media uploader.
media_uploader = wp.media.frames.media_uploader = wp.media({
title: button.data( 'uploader-title' ),
// Tell the modal to show only images.
library: {
type: 'image',
query: false
},
button: {
text: button.data( 'uploader-button-text' ),
},
multiple: button.data( 'uploader-allow-multiple' )
});
// Create a callback when the uploader is called
media_uploader.on( 'select', function() {
var selection = media_uploader.state().get('selection'),
input_name = button.data( 'input-name' ),
bucket = $( '#' + input_name + '-thumbnails');
selection.map( function( attachment ) {
attachment = attachment.toJSON();
// console.log(attachment);
bucket.append(function() {
return '<img src="'+attachment.sizes.thumbnail.url+'" width="'+attachment.sizes.thumbnail.width+'" height="'+attachment.sizes.thumbnail.height+'" class="submission_thumb thumbnail" /><input name="'+input_name+'[]" type="hidden" value="'+attachment.id+'" />'
});
});
});
// Open the uploader
media_uploader.open();
});
template file:
<span class="upload_image_button alt_button" data-input-name="images" data-uploader- title="Upload Images" data-uploader-button-text="Add to Submission" data-uploader-allow-multiple="true">Upload</span>
php $_POST return
if ( !empty( $_POST['submission_images'] ) ) {
// do something with the files, set featured img, add to content or save post_meta
}
or..............i came across a plugin that does this a lot better........sorry its in OOP and designed on back end but you can modify for front end! The problem with multi file uploader from WP is it required users to hit "CTRL" + click with no guidance....massive problem on front-end forms...this one you can add more guidance to easily...sorry i havent a frontend sample yet, i have yet to create :)
"Multi File Upload"
e.g.
public function render_meta_box_content($post)
{
// Add an nonce field so we can check for it later.
wp_nonce_field('miu_inner_custom_box', 'miu_inner_custom_box_nonce');
// Use get_post_meta to retrieve an existing value from the database.
$value = get_post_meta($post->ID, '_ad_images', true);
$metabox_content = '<div id="miu_images"></div><input type="button" onClick="addRow()" value="Add Image" class="button" />';
echo $metabox_content;
$images = unserialize($value);
$script = "<script>
itemsCount= 0;";
if (!empty($images))
{
foreach ($images as $image)
{
$script.="addRow('{$image}');";
}
}
$script .="</script>";
echo $script;
}
save function
public function save_image($post_id)
{
/*
* We need to verify this came from the our screen and with proper authorization,
* because save_post can be triggered at other times.
*/
// Check if our nonce is set.
if (!isset($_POST['miu_inner_custom_box_nonce']))
return $post_id;
$nonce = $_POST['miu_inner_custom_box_nonce'];
// Verify that the nonce is valid.
if (!wp_verify_nonce($nonce, 'miu_inner_custom_box'))
return $post_id;
// If this is an autosave, our form has not been submitted,
// so we don't want to do anything.
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
return $post_id;
// Check the user's permissions.
if ('page' == $_POST['post_type'])
{
if (!current_user_can('edit_page', $post_id))
return $post_id;
} else
{
if (!current_user_can('edit_post', $post_id))
return $post_id;
}
/* OK, its safe for us to save the data now. */
// Validate user input.
$posted_images = $_POST['miu_images'];
$miu_images = array();
foreach ($posted_images as $image_url)
{
if(!empty ($image_url))
$miu_images[] = esc_url_raw($image_url);
}
// Update the miu_images meta field.
update_post_meta($post_id, '_ad_images', serialize($miu_images));
}
js file
jQuery(document).ready(function(){
jQuery('.miu-remove').live( "click", function(e) {
e.preventDefault();
var id = jQuery(this).attr("id")
var btn = id.split("-");
var img_id = btn[1];
jQuery("#row-"+img_id ).remove();
});
var formfield;
var img_id;
jQuery('.Image_button').live( "click", function(e) {
e.preventDefault();
var id = jQuery(this).attr("id")
var btn = id.split("-");
img_id = btn[1];
jQuery('html').addClass('Image');
formfield = jQuery('#img-'+img_id).attr('name');
tb_show('', 'media-upload.php?type=image&TB_iframe=true');
return false;
});
window.original_send_to_editor = window.send_to_editor;
window.send_to_editor = function(html){
if (formfield) {
fileurl = jQuery('img',html).attr('src');
jQuery('#img-'+img_id).val(fileurl);
tb_remove();
jQuery('html').removeClass('Image');
} else {
window.original_send_to_editor(html);
}
};
});
function addRow(image_url){
if(typeof(image_url)==='undefined') image_url = "";
itemsCount+=1;
var emptyRowTemplate = '<div id=row-'+itemsCount+'> <input style=\'width:70%\' id=img- '+itemsCount+' type=\'text\' name=\'miu_images['+itemsCount+']\' value=\''+image_url+'\' />'
+'<input type=\'button\' href=\'#\' class=\'Image_button button\' id=\'Image_button- '+itemsCount+'\' value=\'Upload\'>'
+'<input class="miu-remove button" type=\'button\' value=\'Remove\' id=\'remove-'+itemsCount+'\' /></div>';
jQuery('#miu_images').append(emptyRowTemplate);
}

Is it possible to create a WordPress plugin zip file from an installed plugin?

I have a WordPress installation and some plugins installed and activated. But I have lost the original plugins .zip files. I would like to install some of the plugins into a new WordPress.
I do not want to migrate/move/backup-restore the whole current WP installation. I just want to re-create the original plugin .zip files for some of the plugins that are installed. I do have access to the whole file tree as well as the database. Is there any method for doing that?
Yes, first add a download link to the plugin action links:
/**
* Add action links to each plugin
* #author brasofilo
*/
add_filter( 'plugin_action_links', function ( $plugin_meta, $plugin_file, $plugin_data, $status )
{
$plugin_dir = dirname( $plugin_file );
if( !empty( $plugin_dir ) && '.' !== $plugin_dir )
$plugin_meta[] = sprintf(
"<a href='#' class='down-zip down-icon' data-file='%s' title='%s'></a>",
$plugin_dir,
'Download zip file for ' . $plugin_data['Name']
);
else
$plugin_meta[] = "Root plugin, cannot zip";
return $plugin_meta;
}, 10, 4 );
Then style and attach JS actions:
/**
* Style and actions for wp-admin/plugins.php
* #author brasofilo
*/
add_action( 'admin_footer-plugins.php', function() {
?>
<style>
.down-icon:before { /* http://melchoyce.github.io/dashicons/ */
content: "\f316";
display: inline-block;
-webkit-font-smoothing: antialiased;
font: normal 20px/1 'dashicons';
vertical-align: top;
}
</style>
<script>
root_wp = '<?php echo WP_PLUGIN_DIR; ?>' + '/';
/**
* Virtual $_POST
* creates form, appends and submits
*
* #author https://stackoverflow.com/a/9815335/1287812
*/
function b5f_submit_form_post( path, params, method )
{
$ = jQuery;
method = method || "post"; // Set method to post by default, if not specified.
var form = $(document.createElement( "form" ))
.attr( {"method": method, "action": path} );
$.each( params, function(key,value)
{
$.each( value instanceof Array? value : [value], function(i,val)
{
$(document.createElement("input"))
.attr({ "type": "hidden", "name": key, "value": val })
.appendTo( form );
});
});
form.appendTo( document.body ).submit();
}
jQuery(document).ready(function($)
{
/**
* Fire a plugin download
*/
$("a.down-zip").click(function()
{
event.preventDefault();
b5f_submit_form_post( '', {
action: 'zip_a_plugin',
plugin_to_zip: root_wp + $(this).data('file'),
plugin_name: $(this).data('file')
});
});
});
</script>
<?php
});
Capture the custom $_POSTed data and process the plugin directory to zip:
/**
* Dispatch $_POST['action']=>'zip_a_plugin' custom action
* #author brasofilo https://stackoverflow.com/a/23546276/1287812
*/
add_action('admin_action_zip_a_plugin', function()
{
if( empty( $_REQUEST['plugin_to_zip'] ) )
return;
zipFile( $_REQUEST['plugin_to_zip'], $_REQUEST['plugin_name'], false );
});
And finally, using a zipping function found here on the Stack
/**
* Makes zip from folder
* #author https://stackoverflow.com/a/17585672/1287812
*/
function zipFile($source, $destination, $flag = '')
{
if ( !extension_loaded('zip') ) {
return false;
}
$zip = new ZipArchive();
$tmp_file = tempnam(WP_CONTENT_DIR,'');
if (!$zip->open($tmp_file, ZIPARCHIVE::CREATE)) {
return false;
}
$source = str_replace('\\', '/', realpath($source));
if($flag)
{
$flag = basename($source) . '/';
//$zip->addEmptyDir(basename($source) . '/');
}
if (is_dir($source) === true)
{
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file)
{
$file = str_replace('\\', '/', realpath($file));
if (is_dir($file) === true)
{
$src = str_replace($source . '/', '', $flag.$file . '/');
if( WP_PLUGIN_DIR.'/' !== $src ) # Workaround, as it was creating a strange empty folder like /www_dev/dev.plugins/wp-content/plugins/
$zip->addEmptyDir( $src );
}
else if (is_file($file) === true)
{
$src = str_replace($source . '/', '', $flag.$file);
$zip->addFromString( $src, file_get_contents($file));
}
}
}
else if (is_file($source) === true)
{
$zip->addFromString($flag.basename($source), file_get_contents($source));
}
$tt = $zip->close();
if(file_exists($tmp_file))
{
// push to download the zip
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="'.$destination.'"');
readfile($tmp_file);
// remove zip file is exists in temp path
exit();
}
else {
echo $tt;
die();
}
}
Funnily enough, it's actually trivial to create a zip file from an existing plugin.
Simply create a zip file containing the plugin folder. The unix commands to do that are:
$ cd wp-content/plugins
$ zip -r my-plugin.zip my-plugin
You can then download the resulting my-plugin.zip file which can then be used in WordPress plugin install via upload on new sites (ie: WP Admin -> Plugins -> Add New -> Upload).
Obviously the zip file won't contain any database tables/mods, but most plugins test for this on install and perform any needed database upgrades at install time. Unfortunately there's no way to know whether this will be a problem without testing or checking the plugin source code, or both.
The easiest, code-less way is with another plugin, such as WordPress Downloader.

Resources