File: //home/xedaptot/tracking.naniguide.com/app/controllers/api/QRController.php
<?php
/**
* =======================================================================================
* GemFramework (c) GemPixel
* ---------------------------------------------------------------------------------------
* This software is packaged with an exclusive framework as such distribution
* or modification of this framework is not allowed before prior consent from
* GemPixel. If you find that this framework is packaged in a software not distributed
* by GemPixel or authorized parties, you must not use this software and contact GemPixel
* at https://gempixel.com/contact to inform them of this misuse.
* =======================================================================================
*
* @package GemPixel\Premium-URL-Shortener
* @author GemPixel (https://gempixel.com)
* @license https://gempixel.com/licenses
* @link https://gempixel.com
*/
namespace API;
use \Core\Helper;
use \Core\Request;
use \Core\Response;
use \Core\DB;
use \Core\Auth;
use \Models\User;
class QR {
use \Traits\Links;
/**
* Check if is admin
*
* @author GemPixel <https://gempixel.com>
* @version 6.0
*/
public function __construct(){
$user = Auth::ApiUser();
if(!$user->keyCan('qr')) return die(Response::factory(['error' => true, 'message' => 'You do not have access to this endpoint with this API key.'])->json());
if(!$user->has('qr')){
die(Response::factory(['error' => 1, 'message' => 'You do not have permission to access this endpoint.'], 403)->json());
}
}
/**
* List all plans
*
* @author GemPixel <https://gempixel.com>
* @version 6.0
* @param \Core\Request $request
* @return void
*/
public function get(Request $request){
$qrs = [];
$query = DB::qrs()->where('userid', Auth::ApiUser()->id);
$page = (int) currentpage();
$limit = 15;
if( $request->limit && \is_numeric($request->limit) ){
$limit = (int) $request->limit;
}
$total = $query->count();
$results = $query->limit($limit)->offset(($page-1)*$limit)->findMany();
if(($total % $limit)<>0) {
$max = floor($total/$limit)+1;
} else {
$max = floor($total/$limit);
}
foreach($results as $qr){
$scan = 0;
if($url = DB::url()->select('click')->first($qr->urlid)){
$scan = $url->click;
}
$qrs[] = [
"id" => $qr->id,
"name" => $qr->name,
"link" => route('qr.generate', $qr->alias),
"scans" => $scan,
"date" => $qr->created_at
];
}
return Response::factory(['error' => 0, 'data' => ['result' => $total, 'perpage' => $limit, 'currentpage' => $page, 'nextpage' => $max == 0 || $page == $max ? null : $page+1, 'maxpage' => $max, 'qrs' => $qrs]])->json();
}
/**
* Get a single QR
*
* @author GemPixel <https://gempixel.com>
* @version 6.0
* @param integer $id
* @return void
*/
public function single(int $id){
if(!$qr = DB::qrs()->where('id', $id)->where('userid', Auth::ApiUser()->id)->first()){
return Response::factory(['error' => 1, 'message' => 'QR does not exist.'])->json();
}
if($qr->urlid && $url = DB::url()->first($qr->urlid)){
// Countries
$countries = DB::stats()
->select('country', 'country')
->selectExpr('COUNT(country)', 'count')
->where('urlid', $url->id)
->groupBy('country')
->orderByDesc('count')
->limit(10)
->findMany();
$i = 0;
$top_country = [];
foreach ($countries as $country) {
if(empty($country->country)) $country->country = "Unknown";
$top_country[ucwords($country->country)] = $country->count;
}
arsort($top_country);
// referrers
$top_referrers = [];
$referrers = DB::stats()
->select('domain', 'domain')
->selectExpr('COUNT(domain)', 'count')
->where('urlid', $url->id)
->groupBy('domain')
->limit(10)
->orderByDesc('count')
->findMany();
$browsers = DB::stats()
->select('browser', 'browser')
->selectExpr('COUNT(browser)', 'count')
->where('urlid', $url->id)
->groupBy('browser')
->limit(10)
->orderByDesc('count')
->findMany();
$os = DB::stats()
->select('os', 'os')
->selectExpr('COUNT(os)', 'count')
->where('urlid', $url->id)
->groupBy('os')
->limit(10)
->orderByDesc('count')
->findMany();
$facebook = DB::stats()
->where('urlid', $url->id)
->whereRaw("(domain LIKE '%facebook.%' OR domain LIKE '%fb.%')")
->count();
$twitter = DB::stats()
->where('urlid', $url->id)
->whereRaw("(domain LIKE '%twitter.%' OR domain LIKE '%t.co%')")
->count();
$instagram = DB::stats()
->where('urlid', $url->id)
->whereRaw("(domain LIKE '%instagram.%')")
->count();
$linkedin = DB::stats()
->where('urlid', $url->id)
->whereRaw("(domain LIKE '%linkedin.%')")
->count();
foreach ($referrers as $referrer) {
if(empty($referrer->domain)) $referrer->domain = e("Direct, email and other");
if(!preg_match("~facebook.~", $referrer->domain) && !preg_match("~fb.~", $referrer->domain) && !preg_match("~t.co~", $referrer->domain) && !preg_match("~twitter.~", $referrer->domain)){
$top_referrers[$referrer->domain] = $referrer->count;
}
}
$top_browsers = [];
foreach ($browsers as $browser) {
$top_browsers[ucwords($browser->browser)] = $browser->count;
}
$top_os = [];
foreach ($os as $o) {
$top_os[ucwords($o->os)] = $o->count;
}
arsort($top_referrers);
arsort($top_browsers);
arsort($top_os);
}
$response = [
"error" => 0,
"details" => [
"id" => $qr->id,
"name" => $qr->name,
"link" => route('qr.generate', $qr->alias),
"scans" => (isset($url) && $url) ? $url->click : 0,
"data" => $qr->created_at
],
];
if(isset($url) && $url){
$response['data'] = [
"clicks" => (int) $url->click,
"uniqueClicks" => (int) $url->uniqueclick,
"topCountries" => $top_country,
"topReferrers" => $top_referrers,
"topBrowsers" => $top_browsers,
"topOs" => $top_os,
"socialCount" => [
"facebook" => (int) $facebook,
"twitter" => (int) $twitter,
"instagram" => (int) $instagram,
"linkedin" => (int) $linkedin
]
];
}
return Response::factory($response)->json();
}
/**
* Create QR Code
*
* @author GemPixel <https://gempixel.com>
* @version 6.0
* @param \Core\Request $body
* @return void
*/
public function create(Request $body){
$user = Auth::ApiUser();
$count = DB::qrs()->where('userid', $user->rID())->count();
$total = $user->hasLimit('qr');
if($total != 0 && $count > $total){
return Response::factory(['error' => 1, 'message' => 'You have reached your limit.'])->json();
}
$request = $body->getJSON();
if(!isset($request->type) || !isset($request->data)) return Response::factory(['error' => 1, 'message' => 'Invalid QR format or missing data.'])->json();
if(!\Helpers\QR::typeExists($request->type)) return Response::factory(['error' => 1, 'message' => 'Invalid QR format or missing data.'])->json();
$input = $request->data;
$data = call_user_func([\Helpers\QR::class, 'type'.ucfirst($request->type)], clean($input));
$qrdata = [];
$qrdata['type'] = clean($request->type);
$qrdata['data'] = $input;
if(isset($request->background)){
$qrdata['color']['bg'] = clean($request->background);
}
if(isset($request->foreground)){
$qrdata['color']['fg'] = clean($request->foreground);
}
if(isset($request->logo)){
if(!in_array(Helper::extension($request->logo), ['jpg', 'png'])) return Response::factory(['error' => 1, 'message' =>'Logo must be either a PNG or a JPEG (Max 500kb).'])->json();
$filename = "qr_logo".Helper::rand(6).md5($request->logo).'.'.Helper::extension($request->logo);
copy($request->logo, appConfig('app.storage')['qr']['path'].'/'.$filename);
$qrdata['custom'] = $filename;
}
$url = null;
$alias = \substr(md5($user->rID().Helper::rand(32).$data), 0, 6);
if(!in_array($request->type, ['text', 'sms','wifi','staticvcard'])){
$url = DB::url()->create();
$url->userid = $user->rID();
$url->url = $data;
$url->alias = $alias;
$url->date = Helper::dtime();
if($user->domain){
$url->domain = $user->domain;
}
$url->save();
}
$qr = DB::qrs()->create();
$qr->userid = $user->rID();
$qr->alias = $alias;
$qr->urlid = $url ? $url->id : null;
$qr->name = isset($request->name) ? clean($request->name) : 'Via API';
$qr->data = json_encode($qrdata);
$qr->status = 1;
$qr->created_at = Helper::dtime();
$qr->save();
if($url){
$url->qrid = $qr->id;
$url->save();
}
return Response::factory(['error' => 0, 'id' => (int) $qr->id, 'link' => route('qr.generate', $qr->alias)])->json();
}
/**
* Update QR
*
* @author GemPixel <https://gempixel.com>
* @version 6.0
* @param integer $id
* @return void
*/
public function update(Request $body, int $id){
$user = Auth::ApiUser();
if(!$qr = DB::qrs()->where('id', $id)->where('userid', $user->id)->first()){
return Response::factory(['error' => 1, 'message' => 'QR does not exist.'])->json();
}
$request = $body->getJSON();
$qr->data = json_decode($qr->data);
if(isset($request->data)){
$input = $request->data;
$data = call_user_func([\Helpers\QR::class, 'type'.ucfirst($qr->data->type)], clean($input));
$qr->data->data = $input;
if($qr->urlid && $url = DB::url()->where('id', $qr->urlid)->first()){
$url->url = $data;
$url->save();
}
}
if(isset($request->background)){
$qr->data->color->bg = clean($request->background);
}
if(isset($request->foreground)){
$qr->data->color->fg = clean($request->foreground);
}
if(isset($request->logo)){
if(!in_array(Helper::extension($request->logo), ['jpg', 'png'])) return Response::factory(['error' => 1, 'message' =>'Logo must be either a PNG or a JPEG (Max 500kb).'])->json();
if(isset($qr->data->custom) && !empty($qr->data->custom)){
\Helpers\App::delete( appConfig('app.storage')['qr']['path'].'/'.$qr->data->custom);
}
$filename = "qr_logo".Helper::rand(6).md5($request->logo).Helper::extension($request->logo);
copy($request->logo, appConfig('app.storage')['qr']['path'].'/'.$filename);
$qr->data->custom = $filename;
}
$qr->data = json_encode($qr->data);
$qr->save();
\Helpers\App::delete( appConfig('app.storage')['qr']['path'].'/'.$qr->filename);
return Response::factory(['error' => 0, 'message' => 'QR has been updated successfully.'])->json();
}
/**
* Delete QR
*
* @author GemPixel <https://gempixel.com>
* @version 6.0
* @param integer $id
* @return void
*/
public function delete(int $id){
if(!$qr = DB::qrs()->where('id', $id)->where('userid', Auth::ApiUser()->id)->first()){
return Response::factory(['error' => 1, 'message' => 'QR does not exist.'])->json();
}
$qr->delete();
if($url = DB::url()->where('qrid', $id)->where('userid', $qr->userid)->first()){
$this->deleteLink($url->id);
}
return Response::factory(['error' => 0, 'message' => 'QR has been deleted successfully.'])->json();
}
}