How do I order the friends list returned from the new Facebook Graph API? - facebook

You can get a list of friends of an authenticated user with:
https://graph.facebook.com/me/friends
Anyone have any idea how to order the list by user name? Because it doesn't by default. There's nothing in the documentation.

we do this in several apps just by sorting in javascript.
function sortByName(a, b) {
var x = a.name.toLowerCase();
var y = b.name.toLowerCase();
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}
var _friend_data = null
function lazy_load_friend_data(uid) {
if (_friend_data == null) {
FB.api('/me/friends', function(response) {
_friend_data = response.data.sort(sortByName);
}
)
}
}

Figured out a solution. Eventually, we'll probably be able to order graph results. For now, I'm just doing this (javascript). Assuming that I got "fb_uid" from my PHP session:
var friends = FB.Data.query("SELECT name, uid FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1={0}) ORDER BY name", parseInt(fb_uid));
friends.wait(function(rows){
console.log(rows);
});

I think the whole OpenGraph API is still in a bit of a transitional stage from FB Connect. In any case, I would just do a good old order-by query in FQL, which you can still use. I can't imagine it will be too hard to change once the open graph way of doing this gets established.
This very good tutorial shows you how to do it:
http://thinkdiff.net/facebook/php-sdk-graph-api-base-facebook-connect-tutorial/
$fql = "select name, hometown_location, sex, pic_square from user where uid=xxxxxxxxxxxxxxx";
$param = array(
'method' => 'fql.query',
'query' => $fql,
'callback' => ''
);
$fqlResult = $facebook->api($param);

What is the problem if you do it on caller side. That means, after you get all friends from that graph API, you can put all of them into a sorted data structure and then display all of them:)

Using FQL in one call.
SELECT uid, name FROM user WHERE uid IN
(SELECT uid2 FROM friend WHERE uid1 = me())
ORDER BY name ASC

for me a simple asort($friends); worked fine ;)

$friends = $facebook->api('me/friends');
foreach ($friends as $key=>$value) {
sort($value);
foreach ($value as $fkey=>$fvalue) {
echo "<img src='https://graph.facebook.com/".$fvalue[id]."/picture' width='50' height='50' title='".$fvalue[name]."' />";
}
}

Building off of #MainSocial's answer, but sorting by last then first name, instead of first name only:
function sortByName(a, b) {
var fn = function(x) { return x.name.toLowerCase(); };
var ln = function(x) { return x.last_name.toLowerCase(); };
if(ln(a) == ln(b)){
if(fn(a) == fn(b)) {
return 0;
}
return (fn(a) < fn(b)) ? -1 : 1;
}
return (ln(a) < ln(b)) ? -1 : 1;
}
function getFriendsList() {
FB.api('/me/friends', {fields: 'name,id,last_name'}, function(response) {
var friends = response.data.sort(sortByName);
for (i=0; i<friends.length; i++) {
$('body').append(friends[i].name + ' - ' + friends[i].id + '<br>');
}
});
}
getFriendsList()

private function _compareFacebookFriends($a, $b)
{
return strcasecmp($a['name'], $b['name']);
}
public function sortFacebookFriendsArray(&$array)
{
usort($array, '_compareFacebookFriends');
}
/* Add here $facebook's initialization. Use Facebook PHP SDK */
$fbFriends = $facebook->api('/me/friends');
sortFacebookFriendsArray($fbFriends);

Related

The data i get back to FETCH from my PHP file, had an added empty paragraph at the beginning

I use the FETCH API to pull data from the backend, but since some time I am getting an empty paragraph at the beginning of each response. Unfortunately for me, I am not able to track down what change was made that has caused this, so I am looking for possible reasons why this would happen in order to eliminate it.
Below is once such fetch:
await fetch('__transport.php', {
method: "POST",
body: new URLSearchParams("pk="+pk+"&drvr="+drvr+"&col="+col)
})
.then(response => response.text())
.then((response) => {
if(response.substr(0,6) == "Failed") {
alert(response)
} else {
document.getElementById(id).innerHTML = response;
}
})
.catch(err => console.log('s/g went wrong', err));
and here the backend, the mysql query was removed from the end, but it returns a name
$pk = $_POST['pk'];
$drvr = ($_POST['drvr'] != 0 ? $_POST['drvr']:'NULL');
$col = $_POST['col'];
$sql = "UPDATE mytable
SET
$col = $drvr
WHERE pkcolumn = $pk";
if ($conn->Execute($sql)==false) {
exit("Failed to update database\n\n".$conn->ErrorMsg()."\n\n".$sql);
} else if($drvr != 'NULL'){
//mysql query removed for simplification as I get the same result with this
$name = "Jack Sparrow";
exit($name); //returns the name to the above FETCH
} else {
exit(' '); //returns no name as the field should be blank in this case
}
I am expecting the return "Jack Sparrow" to be received by the JavaScript in the variable "response", as:
"Jack Sparrow"
What I get is and empty paragraph followed by the name:
"
Jack Sparrow"

sequelize.query returns empty array

Using Sequelize 4.38.1 against PostgreSQL 10.5, I have the following code:
const criteria = {
attended: '2018-09-21',
location: 'Squirrel Hill',
teacher: 'Doe, John',
classTitle: 'Yoga 1'
};
const sql = `
SELECT
"Attendances"._id,
"Attendances"."UserId",
"Users"."lastName" || ', ' || "Users"."firstName" AS name
FROM
"Attendances" INNER JOIN "Users" ON "Attendances"."UserId" = "Users"._id
WHERE
"Attendances".attended = :attended AND
"Attendances".location = :location AND
"Attendances".teacher = :teacher AND
"Attendances"."classTitle" = :classTitle
ORDER BY "Users"."lastName", "Users"."firstName";`;
sequelize.query(
sql,
{
replacements: criteria,
type: sequelize.QueryTypes.SELECT
})
.then(attendeeList => {
console.log(attendeeList);
return res.status(200).json(attendeeList);
})
With sequelize logging turned on, my query is correctly parameterized with the replacements and executed:
SELECT
"Attendances"._id,
"Attendances"."UserId",
"Users"."lastName" || ', ' || "Users"."firstName" AS name
FROM
"Attendances" INNER JOIN "Users" ON "Attendances"."UserId" = "Users"._id
WHERE
"Attendances".attended = '2018-09-21' AND
"Attendances".location = 'Squirrel Hill' AND
"Attendances".teacher = 'Doe, John' AND
"Attendances"."classTitle" = 'Yoga 1'
ORDER BY "Users"."lastName", "Users"."firstName";
The problem: my results (attendeeList) are getting returned as []. When I run the same query using pgAdmin, I get one row:
_id UserId name
40 24601 "Doe, John"
Anyone have any thoughts as to what I'm doing wrong?
I submitted the example above as an Issue on Sequelize's Github repo as I was able to make it work with a query that did not include an INNER JOIN.
For my situation, pg-native is a better fit (considering ripping out sequelize elsewhere as it's slower)...
const client = new PGNativeClient();
client.connect(config.sequelize.uri, err => {
if(err) {
res.status(401).json({ message: 'Not able to connect to database to get list of attendees.' });
return;
}
const sql = `
SELECT
"Attendances"._id,
"Attendances"."UserId",
"Users"."lastName" || ', ' || "Users"."firstName" AS name
FROM
"Attendances" INNER JOIN "Users" ON "Attendances"."UserId" = "Users"._id
WHERE
"Attendances".attended = $1::DATE AND
"Attendances".location = $2 AND
"Attendances".teacher = $3 AND
"Attendances"."classTitle" = $4
ORDER BY "Users"."lastName", "Users"."firstName";`;
const { attended, location, teacher, classTitle } = req.query;
client.query(sql, [attended, location, teacher, classTitle], (err, rows) => {
if(err) {
res.status(424).json({ message: 'Not able to retrieve attendees from database (but connected successfully).' });
return;
}
res.status(200).json(rows);
});

How to prevent SQL injection in PhalconPHP when using sql in model?

Let's say I am building a search that finds all the teacher and got an input where the user can put in the search term. I tried reading the phalcon documentation but I only see things like binding parameters. I read the other thread about needing prepare statements do I need that in Phalcon as well?
And my function in the model would be something like this:
public function findTeachers($q, $userId, $isUser, $page, $limit, $sort)
{
$sql = 'SELECT id FROM tags WHERE name LIKE "%' . $q . '%"';
$result = new Resultset(null, $this,
$this->getReadConnection()->query($sql, array()));
$tagResult = $result->toArray();
$tagList = array();
foreach ($tagResult as $key => $value) {
$tagList[] = $value['id'];
....
}
}
My question is for the Phalcon framework is there any settings or formats I should code for this line $sql = 'SELECT id FROM tags WHERE name LIKE "%' . $q . '%"';
And also any general recommendation for preventing SQL Injection in PhalconPHP controllers and index would be appreciated.
For reference:
My controller:
public function searchAction()
{
$this->view->disable();
$q = $this->request->get("q");
$sort = $this->request->get("sort");
$searchUserModel = new SearchUsers();
$loginUser = $this->component->user->getSessionUser();
if (!$loginUser) {
$loginUser = new stdClass;
$loginUser->id = '';
}
$page = $this->request->get("page");
$limit = 2;
if (!$page){
$page = 1;
}
$list = $searchUserModel->findTeachers($q, $loginUser->id, ($loginUser->id)?true:false, $page, $limit, $sort);
if ($list){
$list['status'] = true;
}
echo json_encode($list);
}
My Ajax:
function(cb){
$.ajax({
url: '/search/search?q=' + mapObject.q + '&sort=<?php echo $sort;?>' + '&page=' + mapObject.page,
data:{},
success: function(res) {
//console.log(res);
var result = JSON.parse(res);
if (!result.status){
return cb(null, result.list);
}else{
return cb(null, []);
}
},
error: function(xhr, ajaxOptions, thrownError) {
cb(null, []);
}
});
with q being the user's search term.
You should bind the query parameter to avoid an SQL injection. From what I can remember Phalcon can be a bit funny with putting the '%' wildcard in the conditions value so I put them in the bind.
This would be better than just filtering the query.
$tags = Tags::find([
'conditions' => 'name LIKE :name:',
'bind' => [
'name' => "%" . $q . "%"
]
])
Phalcon\Filter is helpful when interacting with the database.
In your controller you can say, remove everything except letters and numbers from $q.
$q = $this->request->get("q");
$q = $this->filter->sanitize($q, 'alphanum');
The shortest way for requests:
$q = $this->request->get('q', 'alphanum');

Filter information and custom repository with Symfony2?

From GET parameters, I want to get information from my entities.
In my view I created a form with 3 selects (not multiple ones), like this:
http://pix.toile-libre.org/upload/original/1393414663.png
If I filter only by user I got this in the url: ?category=0&user=6&status=0
I'll have to handle the 0 values...
This form used to filter my tasks.
This is a part of my action in my controller:
if($request->query->has('user')) {
$category_id = $request->query->get('category');
$user_id = $request->query->get('user');
$status_id = $request->query->get('status');
// A little test to see if it works.
echo $category_id . '<br>' . $user_id . '<br>' . $status_id;
// I will pass these variables to a repository
$tasks = $em->getRepository('LanCrmBundle:Task')->findFiltered($category_id, $user_id, $status_id);
} else {
$tasks = $em->getRepository('LanCrmBundle:Task')->findAll();
}
I create a repository with this method:
public function findFiltered($category_id, $user_id, $status_id)
{
/**
* Get filtered tasks.
*
* Get only title, priority, created_at, category_id, user_id and status_id fields (optimization)
*
* Where field category_id = $category_id unless $category_id is smaller than 1 (not secure enough)
* Where field user_id = $user_id unless $user_id is smaller than 1 (not secure enough)
* Where field status_id = $status_id unless $status_id is smaller than 1 (not secure enough)
* Should I do these tests here or in the controller?
*/
}
How to do this query ? Do you have any other elegant suggestions to solve this problem?
You can try:
public function findFiltered($category_id, $user_id, $status_id)
{
$queryBuilder = $this->createQueryBuilder('t');
if(!empty($category_id) && is_numeric($category_id)) {
$queryBuilder->andWhere('t.category = :category')->setParameter('category', $category_id);
}
if(!empty($user_id) && is_numeric($user_id)) {
$queryBuilder->andWhere('t.user = :user')->setParameter('user', $user_id);
}
if(!empty($status_id) && is_numeric($status_id)) {
$queryBuilder->andWhere('t.status = :status')->setParameter('status', $status_id);
}
return $queryBuilder->getQuery()->getResult();
}

Fetching friends' birthdays from facebook profile

I want to fetch 'birthdays' of users, and their friends on my website, from their facebook profiles (with their facebook credentials supplied).
Is their a feature in Facebook API/Connect that I can use to fetch these details from facebook as possible on Native Facebook Apps using Facebook API.
I want to store this data in my DB, and users will be asked for their facebook credentials and consent before this is done.
Read the api documentation things like this are easily done. You can do it like this:
$facebook = new Facebook( $apikey, $secret );
$uid = $facebook->require_login();
$friends = $facebook->api_client->friends_get(); // $friends is an array holding the user ids of your friends
foreach( $friends as $f ) {
$data = $facebook->api_client->fql_query( "SELECT birthday_date FROM user WHERE uid=$f" );
// $data[0] is an array with 'birthday_date' => "02/29/1904"
// see api documentation for other fields and do a print_r
}
So recently I wanted to check my friends to see if any of them had their birthday for the current day. Using FQL this is super easy and I encourage you to explore FQL more because it will yield a more efficient solution than, say, what Pierre kindly offered. Here is a small snippet of the code:
$friends = $facebook->api_client->friends_get();
$uids = "";
foreach($friends as $f) {
$uids .= "uid=$f OR ";
}
$query_uids = substr($uids,0,strlen($query_uids)-4);
date_default_timezone_set('UTC');
$current_date = date("m/d");
echo "<br />Searching for birthdays for the given month/day: $current_date<br />";
$data = $facebook->api_client->fql_query( "SELECT name, uid FROM user WHERE ( ($query_uids) AND strpos(birthday_date,'$current_date') >= 0 )" );
if(count($data) > 0) {
foreach($data as $d) {
print_r($d);
}
} else {
echo "<br />No Birthdays Today<br />";
}
require_once('facebook-platform/client/facebook.php');
$facebook = new Facebook(API_KEY, SECRET);
$facebook->require_login();
function getInfo($user_list, $fields)
{
try
{
$u = $facebook->api_client->users_getInfo($user_list, $fields);
return $u;
}
catch (FacebookRestClientException $e)
{
echo $e->getCode() . ' ' . $e->getMessage();
}
}
function getFriendsBirthdays($user_id)
{
$f = $_REQUEST['fb_sig_friends'];
$f = explode(',', $f);
$birthdays = array();
foreach($f as $friend_id)
{
$birthdays[] = getInfo($friend_id, 'birthday');
}
return $birthdays;
}
Do something like that or use the Batch API to do multiple calls at once. Check the Facebook API.
You could fetch it via the API, but Facebook's terms strictly forbid you from storing anything other than their user ID in your database - see the developer wiki for details. You will need to query the API each time.