How to exclude private events in laravel 5.5? - php

I have this piece of legacy code to return all events to the front end:
/**
* #param $request
*
* #return mixed
*/
public function index( EventsFilterRequest $request ) {
$keys = $request->all();
if ( \count( $keys ) === 0 ) {
return $this->eventsQueryBuilder()->isVisibleFor( authUser()->id )->ofOrder( 'starts_at', 'ASC' )->ofCountry( runtime()->country()->id )->ofStatus( 'future' );
}
$events = $this->eventsQueryBuilder()->isVisibleFor( authUser()->id )->ofOrder( 'starts_at', 'ASC' )->ofStatus( 'future' )->ofCountry( runtime()->country()->id );
foreach ( $keys as $key => $value ) {
if ( array_key_exists( $key, $this->_methods ) ) {
$events = $this->_methods[$key]( $events, $request, $this );
}
}
return $events;
}
In the events table there's a column called privacy that contains public or private. How can I exclude private events from being returned ?

I am new to laravel but you can use where clause in your query. Something like
$events = DB::table('events')->where('privacy', 'public')->get();
For more check this link LARAVEL QUERY

Related

Wordpress - Testing custom API endpoint with class dependency

Sorry I feel like really stuck here.
I have a plugin introducing a new Rest API controller (WP_REST_Controller) with basically a single endpoint which uses a separate class as a client to fetch some data. Let's say:
#my_plugin.php
function register_items_routes() {
if ( ! class_exists( 'WP_REST_My_Controller' ) ) {
require_once __DIR__ . '/class-wp-my-controller.php';
}
$controller = new WP_REST_My_Controller();
$controller->register_routes();
}
add_action( 'rest_api_init', 'register_items_routes' );
_
#class-wp-my-controller.php
class WP_REST_My_Controller extends WP_REST_Controller {
/**
* Registers the routes.
*/
public function register_routes() {
$namespace = 'my/namespace';
$path = 'get-items';
register_rest_route( $namespace, '/' . $path, [
array(
'methods' => 'GET',
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' )
),
] );
}
public function get_items_permissions_check( $request ) {
return true;
}
/**
* Get items from My_Class and return them.
*
* #param WP_REST_Request $request The incoming HTTP request.
*
* #return WP_REST_Response|WP_Error The response containing the items in JSON, WP_Error in case of error.
*/
public function get_items( $request ) {
$client = new My_Class();
try {
$items = $client->fetch_some_items();
} catch ( Exception $e ) {
return new WP_Error(
'some-client-error',
$e->getMessage()
);
// Code to be tested. - Do some stuff with items and return.
return new WP_REST_Response( $items );
}
How am I supposed to stub the My_Class dependency from PhpUnit in order to return a predefined set of items which I could test with?
public function test_get_items() {
$request = new WP_REST_Request( 'GET', '/my/namespace/get-items' );
$data = rest_get_server()->dispatch( $request );
$expected_items = [
'some_key1' => 'some_value1',
'some_key2' => 'some_value2',
];
$this->assertTrue( count($data['items']) == count($expected_items) );
}

Laravel 5.2: dimsav Call to a member function translateOrNew() on a non-object

I am using
Laravel 5.2
Package dimsav laravel-translatable 6.*
This is my worked controller
$about = new About();
$about->link = $request->link;
$about->save();
$localization = $request['localization'];
//dd($localization);
// check if locales arabic and english only
$locales = array_keys($localization);
foreach ($locales as $locale) {
if (!in_array($locale, array('en', 'ar'))) {
Session::flash('message', 'Lang Error');
return Redirect::back();
}
}
foreach ($localization as $locale => $parameters) {
$about->translateOrNew($locale)->title = $parameters['title'];
$about->translateOrNew($locale)->details = $parameters['details'];
}
$about->save();
but when I try to use mass-assignment
$input = $request->all();
$localization = $input['localization'];
// check if locales arabic and english only
$locales = array_keys( $localization );
foreach ( $locales as $locale ) {
if ( ! in_array( $locale, array( 'en', 'ar' ) ) ) {
Session::flash( 'message', 'Lang Error' );
return Redirect::back();
}
}
foreach ( $localization as $locale => $parameters ) {
$input->translateOrNew( $locale )->title = $parameters['title'];
$input->translateOrNew($locale)->details = $parameters['details'];
}
dd($input);
About::create( $input );
Got an error
Call to a member function translateOrNew() on a non-object
any help please what I am doing wrong here.
Edit :
My about Model
use Dimsav\Translatable\Translatable;
use Illuminate\Database\Eloquent\Model;
class About extends Model {
use Translatable;
public $translatedAttributes = [ 'title', 'details' ];
protected $fillable = [ 'link' ];
}
my abouttranslation model
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class AboutTranslation extends Model
{
public $timestamps = false;
protected $fillable = ['title', 'details', 'about_id'];
}
In your mass assignment version you are getting an array from using
$input = $request->all();
You want to use the function translateOrNew() on that array which is not working because the array has no function. You have to call the function from somewhere else and save an array with create. I provide a simple example:
$input = $request->all();
$localization = $input['localization'];
// check if locales arabic and english only
$locales = array_keys( $localization );
foreach ( $locales as $locale ) {
if ( ! in_array( $locale, array( 'en', 'ar' ) ) ) {
Session::flash( 'message', 'Lang Error' );
return Redirect::back();
}
}
$input = array();
foreach ( $localization as $locale => $parameters ) {
$input[About::translateOrNew( $locale )->title] = $parameters['title'];
$input[About::translateOrNew($locale)->details] = $parameters['details'];
}
About::create( $input );
I have to assume many things, since I do not know how the About model looks like. Additionally I assume that there is a static method translateOrNew() available in this model. Please provide more information about your script, that will improve the answer.
Update:
On second thought, why not use this much simpler approach?
<?php
$input = $request->all();
$localization = $input['localization'];
// check if locales arabic and english only
$locales = array_keys( $localization );
foreach ( $locales as $locale ) {
if ( ! in_array( $locale, array( 'en', 'ar' ) ) ) {
Session::flash( 'message', 'Lang Error' );
return Redirect::back();
}
}
$model_about = new About();
$input = array();
foreach ( $localization as $locale => $parameters ) {
$model_about->translateOrNew($locale)->title = $parameters['title'];
$model_about->translateOrNew($locale)->details = $parameters['details'];
}
$model_about->save();
Just create a model object, use its function and save it afterwards.
You forgot to include the following in the model class.
Use \Dimsav\Translatable\Translatable; in your Model file, which is here: \App\Article.php

Elasticsearch in laravel 5.1

I want to integrate elasticsearch in my laravel project.
I have installed using following line :
Run command on terminal :
composer require shift31/laravel-elasticsearch:~1.0
Then i have created elasticsearch.php in app/config/ and added following code.
<?php
use Monolog\Logger;
return array(
'hosts' => array(
'your.elasticsearch.server:9200' // what should be my host ?
),
'logPath' => 'path/to/your/elasticsearch/log',
'logLevel' => Logger::INFO
);
My first question : What should i write in place of host name
Right now my project is running on local server with localhost:8000.
I have added Shift31\LaravelElasticsearch\ElasticsearchServiceProvider in app/config/app.php for enable the 'Es' facade.
Above all things done. Now in which file i should add the code of elasticsearch to add, update, delete and search the records.
I have product table I need to add product records in elasticsearch, when update product, records should be update.
I have no idea of the further process. Please guide me I have searched on google but no any example help me.
Create the following helper classes in their respective paths:
App\Traits\ElasticSearchEventTrait.php
<?php
Namespace App\Traits;
trait ElasticSearchEventTrait {
public $esRemoveDefault = array('created_at','updated_at','deleted_at');
public static function boot()
{
parent::boot();
static::bootElasticSearchEvent();
}
public static function bootElasticSearchEvent()
{
static::created(function ($model) {
if(isset($model->esEnabled) && $model->esEnabled === true)
{
$model->esCreate();
}
});
static::updated(function ($model) {
if(isset($model->esEnabled) && $model->esEnabled === true)
{
$model->esUpdate();
}
});
static::deleted(function ($model) {
if(isset($model->esEnabled) && $model->esEnabled === true)
{
$model->esUpdate();
}
});
}
private function esCreate()
{
//esContext is false for polymorphic relations with no elasticsearch indexing
if(isset($this->esMain) && $this->esMain === true && $this->esContext !== false)
{
\Queue::push('ElasticSearchHelper#indexTask',array('id'=>$this->esGetId(),'class'=>get_class($this),'context'=>$this->esGetContext(),'info-context'=>$this->esGetInfoContext(),'excludes'=>$this->esGetRemove()));
}
else
{
$this->esUpdate();
}
}
private function esUpdate()
{
//esContext is false for polymorphic relations with no elasticsearch indexing
if($this->esContext !== false)
{
\Queue::push('ElasticSearchHelper#updateTask',array('id'=>$this->esGetId(),'class'=>get_class($this),'context'=>$this->esGetContext(),'info-context'=>$this->esGetInfoContext(),'excludes'=>$this->esGetRemove()));
}
}
/*
* Get Id of Model
*/
public function esGetId()
{
if(isset($this->esId))
{
return $this->esId;
}
else
{
return $this->id;
}
}
public function esGetInfoContext()
{
if(isset($this->esInfoContext))
{
return $this->esInfoContext;
}
else
{
throw new \RuntimeException("esInfoContext attribute or esGetInfoContext() is not set in class '".get_class($this)."'");
}
}
/*
* Name of main context of model
*/
public function esGetContext()
{
if(isset($this->esContext))
{
return $this->esContext;
}
else
{
throw new \RuntimeException("esContext attribute or esGetContext() method must be set in class '".get_class($this)."'");
}
}
/*
* All attributes that needs to be removed from model
*/
public function esGetRemove()
{
if(isset($this->esRemove))
{
return array_unique(array_merge($this->esRemoveDefault,$this->esRemove));
}
else
{
return $this->esRemoveDefault;
}
}
/*
* Extends Illuminate Collection to provide additional array functions
*/
public function newCollection(array $models = Array())
{
return new Core\Collection($models);
}
/**
* Return a timestamp as DateTime object.
*
* #param mixed $value
* #return \Carbon\Carbon
*/
public function asEsDateTime($value)
{
// If this value is an integer, we will assume it is a UNIX timestamp's value
// and format a Carbon object from this timestamp. This allows flexibility
// when defining your date fields as they might be UNIX timestamps here.
if (is_numeric($value))
{
return \Carbon::createFromTimestamp($value);
}
// If the value is in simply year, month, day format, we will instantiate the
// Carbon instances from that format. Again, this provides for simple date
// fields on the database, while still supporting Carbonized conversion.
elseif (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $value))
{
return \Carbon::createFromFormat('Y-m-d', $value)->startOfDay();
}
// Finally, we will just assume this date is in the format used by default on
// the database connection and use that format to create the Carbon object
// that is returned back out to the developers after we convert it here.
elseif ( ! $value instanceof DateTime)
{
$format = $this->getEsDateFormat();
return \Carbon::createFromFormat($format, $value);
}
return \Carbon::instance($value);
}
/**
* Get the format for database stored dates.
*
* #return string
*/
private function getEsDateFormat()
{
return $this->getConnection()->getQueryGrammar()->getDateFormat();
}
/*
* Converts model to a suitable format for ElasticSearch
*/
public function getEsSaveFormat()
{
$obj = clone $this;
//Go through ES Accessors
\ElasticSearchHelper::esAccessor($obj);
$dates = $this->getDates();
//Convert to array, then change Date to appropriate Elasticsearch format.
//Why? Because eloquent's date accessors is playing me.
$dataArray = $obj->attributesToArray();
//Remove all Excludes
foreach($this->esGetRemove() as $ex)
{
if(array_key_exists($ex,$dataArray))
{
unset($dataArray[$ex]);
}
}
if(!empty($dates))
{
foreach($dates as $d)
{
if(isset($dataArray[$d]) && $dataArray[$d] !== "" )
{
//Trigger Eloquent Getter which will provide a Carbon instance
$dataArray[$d] = $this->{$d}->toIso8601String();
}
}
}
return $dataArray;
}
}
App\Services\ElasticServiceHelper.php
<?php
/**
* Description of ElasticSearchHelper: Helps with Indexing/Updating with Elastic Search Server (https://www.elastic.co)
*
* #author kpudaruth
*/
Namespace App\Services;
class ElasticSearchHelper {
/*
* Laravel Queue - Index Task
* #param array $job
* #param array $data
*/
public function indexTask($job,$data)
{
if(\Config::get('website.elasticsearch') === true)
{
if(isset($data['context']))
{
$this->indexEs($data);
}
else
{
\Log::error('ElasticSearchHelper: No context set for the following dataset: '.json_encode($data));
}
}
$job->delete();
}
/*
* Laravel Queue - Update Task
* #param array $job
* #param array $data
*/
public function updateTask($job,$data)
{
if(\Config::get('website.elasticsearch') === true)
{
if(isset($data['context']))
{
$this->updateEs($data);
}
else
{
\Log::error('ElasticSearchHelper: No context set for the following dataset: '.json_encode($data));
}
}
$job->delete();
}
/*
* Index Elastic Search Document
* #param array $data
*/
public function indexEs($data)
{
$params = array();
$params['index'] = \App::environment();
$params['type'] = $data['context'];
$model = new $data['class'];
$form = $model::find($data['id']);
if($form)
{
$params['id'] = $form->id;
if($form->timestamps)
{
$params['timestamp'] = $form->updated_at->toIso8601String();
}
$params['body'][$data['context']] = $this->saveFormat($form);
\Es::index($params);
}
}
/*
* Update Elastic Search
* #param array $data
*/
public function updateEs($data)
{
$params = array();
$params['index'] = \App::environment();
$params['type'] = $data['context'];
$model = new $data['class'];
$form = $model::withTrashed()->find($data['id']);
if(count($form))
{
/*
* Main form is being updated
*/
if($data['info-context'] === $data['context'])
{
$params['id'] = $data['id'];
$params['body']['doc'][$data['info-context']] = $this->saveFormat($form);
}
else
{
//Form is child, we get parent
$parent = $form->esGetParent();
if(count($parent))
{
//Id is always that of parent
$params['id'] = $parent->id;
//fetch all children, given that we cannot save per children basis
$children = $parent->{$data['info-context']}()->get();
if(count($children))
{
//Get data in a format that can be saved by Elastic Search
$params['body']['doc'][$data['info-context']] = $this->saveFormat($children);
}
else
{
//Empty it is
$params['body']['doc'][$data['info-context']] = array();
}
}
else
{
\Log::error("Parent not found for {$data['context']} - {$data['class']}, Id: {$data['id']}");
return false;
}
}
//Check if Parent Exists
try
{
$result = \Es::get([
'id' => $params['id'],
'index' => $params['index'],
'type' => $data['context']
]);
} catch (\Exception $ex) {
if($ex instanceof \Elasticsearch\Common\Exceptions\Missing404Exception || $ex instanceof \Guzzle\Http\Exception\ClientErrorResponseException)
{
//if not, we set it
if (isset($parent) && $parent)
{
$this->indexEs([
'context' => $data['context'],
'class' => get_class($parent),
'id' => $parent->id,
]);
}
else
{
\Log::error('Unexpected error in updating elasticsearch records, parent not set with message: '.$ex->getMessage());
return false;
}
}
else
{
\Log::error('Unexpected error in updating elasticsearch records: '.$ex->getMessage());
return false;
}
}
\Es::update($params);
}
}
/*
* Iterate through all Es accessors of the model.
* #param \Illuminate\Database\Eloquent\Model $object
*/
public function esAccessor(&$object)
{
if(is_object($object))
{
$attributes = $object->getAttributes();
foreach($attributes as $name => $value)
{
$esMutator = 'get' . studly_case($name) . 'EsAttribute';
if (method_exists($object, $esMutator)) {
$object->{$name} = $object->$esMutator($object->{$name});
}
}
}
else
{
throw New \RuntimeException("Expected type object");
}
}
/*
* Iterates over a collection applying the getEsSaveFormat function
* #param mixed $object
*
* #return array
*/
public function saveFormat($object)
{
if($object instanceof \Illuminate\Database\Eloquent\Model)
{
return $object->getEsSaveFormat();
}
else
{
return array_map(function($value)
{
return $value->getEsSaveFormat();
}, $object->all());
}
}
}
A couple of gotchas from the above helper classes:
The default ElasticSearch index is set to the name of the App's Environment
The ..task() functions are meant for the old laravel 4.2 queue format. I've yet to port those to laravel 5.x. Same goes for the Queue::push commands.
Example
ElasticSearch Mapping:
[
'automobile' => [
"dynamic" => "strict",
'properties' => [
'automobile' => [
'properties' => [
'id' => [
'type' => 'long',
'index' => 'not_analyzed'
],
'manufacturer_name' => [
'type' => 'string',
],
'manufactured_on' => [
'type' => 'date'
]
]
],
'car' => [
'properties' => [
'id' => [
'type' => 'long',
'index' => 'not_analyzed'
],
'name' => [
'type' => 'string',
],
'model_id' => [
'type' => 'string'
]
]
],
"car-model" => [
'properties' => [
'id' => [
'type' => 'long',
'index' => 'not_analyzed'
],
'description' => [
'type' => 'string',
],
'name' => [
'type' => 'string'
]
]
]
]
]
]
Top level document is called 'automobile'. Underneath it, you have 'automobile', 'car' & 'car-model'. Consider 'car' & 'car-model' as relations to the automobile. They are known as sub documents on elasticsearch. (See: https://www.elastic.co/guide/en/elasticsearch/guide/current/document.html)
Model: App\Models\Car.php
namespace App\Models;
class Car extends \Eloquent {
use \Illuminate\Database\Eloquent\SoftDeletingTrait;
use \App\Traits\ElasticSearchEventTrait;
protected $table = 'car';
protected $fillable = [
'name',
'serie',
'model_id',
'automobile_id'
];
protected $dates = [
'deleted_at'
];
/* Elastic Search */
//Indexing Enabled
public $esEnabled = true;
//Context for Indexing - Top Level name in the mapping
public $esContext = "automobile";
//Info Context - Secondary level name in the mapping.
public $esInfoContext = "car";
//The following fields will not be saved in elasticsearch.
public $esRemove = ['automobile_id'];
//Fetches parent relation of car, so that we can retrieve its id for saving in the appropriate elasticsearch record
public function esGetParent()
{
return $this->automobile;
}
/*
* Event Observers
*/
public static function boot() {
parent:: boot();
//Attach events to model on start
static::bootElasticSearchEvent();
}
/*
* ElasticSearch Accessor
*
* Sometimes you might wish to format the data before storing it in elasticsearch,
* The accessor name is in the format of: get + attribute's name camel case + EsAttribute
* The $val parameter will always be the value of the attribute that is being accessed.
*
* #param mixed $val
*/
/*
* Elasticsearch Accessor: Model Id
*
* Get the model name and save it
*
* #param int $model_id
* #return string
*/
public function getModelIdEsAttribute($model_id) {
//Fetch model from table
$model = \App\Models\CarModel::find($model_id);
if($model) {
//Return name of model if found
return $model->name;
} else {
return '';
}
}
/*
* Automobile Relationship: Belongs To
*/
public function automobile()
{
return $this->belongsTo('\App\Models\Automobile','automobile_id');
}
}
Example of Search Query:
/**
* Get search results
*
* #param string $search (Search string)
*
*/
public function getAll($search)
{
$params = array();
$params['index'] = App::environment();
//Declare your mapping names in the array which you wish to search on.
$params['type'] = array('automobile');
/*
* Build Query String
*/
//Exact match is favored instead of fuzzy ones
$params['body']['query']['bool']['should'][0]['match']['name']['query'] = $search;
$params['body']['query']['bool']['should'][0]['match']['name']['operator'] = "and";
$params['body']['query']['bool']['should'][0]['match']['name']['boost'] = 2;
$params['body']['query']['bool']['should'][1]['fuzzy_like_this']['like_text'] = $search;
$params['body']['query']['bool']['should'][1]['fuzzy_like_this']['fuzziness'] = 0.5;
$params['body']['query']['bool']['should'][1]['fuzzy_like_this']['prefix_length'] = 2;
$params['body']['query']['bool']['minimum_should_match'] = 1;
//Highlight matches
$params['body']['highlight']['fields']['*'] = new \stdClass();
$params['body']['highlight']['pre_tags'] = array('<b>');
$params['body']['highlight']['post_tags'] = array('</b>');
//Exclude laravel timestamps
$params['body']['_source']['exclude'] = array( "*.created_at","*.updated_at","*.deleted_at");
/*
* Poll search server until we have some results
*/
$from_offset = 0;
$result = array();
//Loop through all the search results
do
{
try
{
$params['body']['from'] = $from_offset;
$params['body']['size'] = 5;
$queryResponse = \Es::search($params);
//Custom function to process the result
//Since we will receive a bunch of arrays, we need to reformat the data and display it properly.
$result = $this->processSearchResult($queryResponse);
$from_offset+= 5;
}
catch (\Exception $e)
{
\Log::error($e->getMessage());
return Response::make("An error occured with the search server.",500);
}
}
while (count($result) === 0 && $queryResponse['hits']['total'] > 0);
echo json_encode($result);
}
/*
* Format search results as necessary
* #param array $queryResponse
*/
private function processSearchResult(array $queryResponse)
{
$result = array();
//Check if we have results in the array
if($queryResponse['hits']['total'] > 0 && $queryResponse['timed_out'] === false)
{
//Loop through each result
foreach($queryResponse['hits']['hits'] as $line)
{
//Elasticsearch will highlight the relevant sections in your query in an array. The below creates a readable format with · as delimiter.
$highlight = "";
if(isset($line['highlight']))
{
foreach($line['highlight'] as $k=>$v)
{
foreach($v as $val)
{
$highlight[] = str_replace("_"," ",implode(" - ",explode(".",$k)))." : ".$val;
}
}
$highlight = implode(" · ",$highlight);
}
//Check the mapping type
switch($line['_type'])
{
case "automobile":
$result[] = array('icon'=>'fa-automobile',
'title'=> 'Automobile',
'id' => $line['_id'],
//name to be displayed on my search result page
'value'=>$line['_source'][$line['_type']]['name']." (Code: ".$line['_id'].")",
//Using a helper to generate the url. Build your own class.
'url'=>\App\Helpers\URLGenerator::generate($line['_type'],$line['_id']),
//And the highlights as formatted above.
'highlight'=>$highlight);
break;
}
}
}
return $result;
}

CodeIgniter redirect loop in post controller hook

Here is my Controller:
<?php
class Check_Login {
var $CI;
var $class;
var $allowed_klasses = array('user', 'testing', 'home', 'lesson_assets', 's3_handler', 'ajax', 'api', 'pages', 'invite', 'mail', 'partner', 'renew', 'store', 'news', 'breathe','popup','subscription', 'lessons');
public function __construct() {
$this->CI =& get_instance();
if(!isset($this->CI->session)) {
$this->CI->load->library('session');
}
if(!nash_logged_in()) {
$this->CI->session->sess_destroy();
redirect('/');
}
$this->_set_accessed_klass();
}
public function auth_check() {
if($this->CI->session->userdata('id')) {
$query = $CI->db->query("SELECT authentication_token FROM users WHERE id = ".$this->CI->session->userdata('id')." AND authentication_token IS NOT NULL");
if(!in_array($this->class, $this->allowed_klasses)) {
if($query->num_rows() == 0){
redirect('/user/logout');
}
}else{
return;
}
}else{
return;
}
}
private function _set_accessed_klass() {
$this->class = $this->CI->router->fetch_class();
}
}
The lines that I am referring too are:
if(!nash_logged_in()) {
$this->CI->session->sess_destroy();
redirect('/');
}
Essentially, the app uses the nash_logged_in() method to check against our OAuth system to see if the user is truly "logged in". When this happens a redirect loop happens.
The nash_logged_in method simply returns a JSON key of either TRUE or FALSE. Any reason why I would be running into this redirect loop?
nash_logged_in method:
if(!function_exists('nash_logged_in')) {
function nash_logged_in(){
$url = NASH_OAUTH_URL . '/api/v1/loggedin.json';
$json = file_get_contents($url);
$data = json_decode($json);
return $data->loggedin;
}
}
If nash_logged_in() does not return a boolean false or integer 0 or null, then the statement is evaluated as true therefore your redirect.
Post nash_logged_in() here to see what's going on there.
You wont need to use hooks for this method
post controller hook
You could just extend CI_Controller and run the Authentication library in the __constructor of the child classes that need to be authenticated.
You current controller is a little messy and it looks like a library to me, not a controller, you don't need to re-instantiate the super object if your doing it all in your controller!
However, my suggestion is to move everything to a library(as there are a number of controllers/classes that depend on it).
Some elements of your code don't make sense to me, possibly because I can't see the bigger picture from the code you have posted.
This might give you some food for though(or not) regardless this is how I would approach it.
application/libraries/authentication.php
class Authentication
{
protected $allowedClasses = array ( ) ;
protected $userId = null ;
protected $nashURL ;
const NASH_OAUTH_URL = '' ;
public function __construct ()
{
$this->nashURL = static::NASH_OAUTH_URL . '/api/v1/loggedin.json' ;
//check for a user id in session
//this may not be set yet!!
$this->userId = (isset ( $this->session->userdata ( 'id' ) ))
? $this->session->userdata ( 'id' )
: null ;
/** Load dependancies * */
$this->load->model ( 'Authentication_Model' ) ;
$this->load->library ( 'Session' ) ;
}
/**
* nashCheckLoginViaCurl
* #return boolean
*/
protected function nashCheckLoginViaCurl ()
{
if ( function_exists ( 'curl_init' ) )
{
return show_error ( "Enabled CURL please!" , 500 ) ;
}
$curl = curl_init () ;
curl_setopt_array ( $curl ,
array (
CURLOPT_URL => $this->nashURL ,
/** CHECK CURL DOCS FOR FULL LIST OF OPTIONS - FILL THE REST YOURSELF * */
) ) ;
if ( curl_errno ( $curl ) )
{
return false ;
}
$info = curl_getinfo ( $curl ) ;
$responce = curl_exec ( $curl ) ;
curl_close ( $curl ) ;
//Check and make sure responce is a BOOLEAN and not a STRING
//we will typecast below just incase
$responce = json_decode ( $responce ) ;
return ($info[ 'http_code' ] == '200' and ( bool ) $responce->loggedin === true)
? true
: false ;
}
/**
* verifyAccess
* #param CI_Controller $class (Dependancy Injection)
* #return Mixed
*
*/
public function verifyAccess ( CI_Controller $class )
{
//Is there a userId in the session
//ie: is user logged In
if ( is_null ( $this->userId ) or ! ( int ) $this->userId )
{
return false ;
}
//grab list of allowed classes
$this->allowedClasses = $this->listAllowedClasses () ;
//check to see if $class is in list of allowed classes
if ( ! in_array ( $class , $this->allowedClasses ) )
{
return false ;
}
//check to see if nashCheckLoginViaCurl returned true
if ( ! $this->nashCheckLoginViaCurl () )
{
$this->logout () ;
return false ;
}
//return boolean or $authentication_token based on DB query
return $this->Authentication_Model->isUserIdRegistered ( $this->userId ) ;
}
/**
* logout
* #return void
*/
public function logout ()
{
$this->session->unset_userdata ( array ( 'id' => 0 ) ) ;
$this->session->sess_destroy () ;
$this->session->sess_start () ;
return redirect ( '/' ) ;
}
/**
* listAllowedClasses
* MAYBE USE A CONFIG FILE FOR THIS?
* #return array
*/
protected function listAllowedClasses ()
{
return array (
'user' , 'testing' , 'home' , 'lesson_assets' , 's3_handler' , 'ajax' ,
'api' ,
'pages' , 'invite' , 'mail' , 'partner' , 'renew' , 'store' , 'news' ,
'breathe' ,
'popup' , 'subscription' , 'lessons'
) ;
}
/**
* Load CI Super object object
*
* #param string $object
* #return object
*/
public function __get ( $object )
{
return get_instance ()->$object ;
}
}
application/models/authentication_model.php
class Authentication_Model extends CI_Model
{
public function isUserIdRegistered ( $uid )
{
$this->db->select ( 'authentication_token' )
->from ( 'users' )
->where ( 'id' , $uid )
->where ( 'authentication_token IS NOT' , 'NULL' )
->limit ( 1 ) ;
$query = $this->db->get () ;
return ( $query->num_rows () > 0 )
? $query->result ()
: FALSE ;
}
}
application/core/MY_Controller.php
class MY_Controller extends CI_Controller
{
protected $authentication_token ;
public function __construct ()
{
parent::__construct () ;
$this->load->library ( 'authentication' ) ;
}
protected function _verifyAccess ( $class )
{
$authorized = $this->authentication->verifyAccess ( strtolower ( $class ) ) ;
if ( ! $authorized )
{
//kill further script execution by returning
//redirect url
return redirect ( 'login' ) ;
}
else
{
$this->authentication_token = $authorized ;
}
return ; //return control back to the controller who called me
}
}
*Testing Different Controllers - simulate post controller hook *
class Some_Controller extends MY_Controller
{
public function __construct ()
{
parent::__construct () ;
$this->_verifyAccess ( __CLASS__ ) ;
}
}
-
class Another_Controller extends MY_Controller
{
public function __construct ()
{
parent::__construct () ;
$this->_verifyAccess ( __CLASS__ ) ;
}
}

zend framework rest controller question

I have a rest controller example im trying to run that is giving me a headache.
My url im trying to access is localhost/books/edit/1
For some weird reason this route seems to call the getAction with the Controller instead of the editAction. And it throws errors saying that the object doesnt exist.
The controller is,
class BooksController extends Zend_Rest_Controller {
private $_booksTable;
private $_form;
public function init() {
$bootstrap = $this->getInvokeArg ( 'bootstrap' );
$db = $bootstrap->getResource ( 'db' );
$options = $bootstrap->getOption ( 'resources' );
$dbFile = $options ['db'] ['params'] ['dbname'];
if (! file_exists ( $dbFile )) {
$createTable = "CREATE TABLE IF NOT EXISTS books (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name VARCHAR(32) NOT NULL,
price DECIMAL(5,2) NOT NULL
)";
$db->query ( $createTable );
$insert1 = "INSERT INTO books (name, price) VALUES ('jQuery in Action', 39.99)";
$insert2 = "INSERT INTO books (name, price) VALUES ('PHP in Action', 45.99)";
$db->query ( $insert1 );
$db->query ( $insert2 );
}
$this->_booksTable = new Zend_Db_Table ( 'books' );
$this->_form = new Default_Form_Book ();
}
/**
* The index action handles index/list requests; it should respond with a
* list of the requested resources.
*/
public function indexAction() {
$this->view->books = $this->_booksTable->fetchAll ();
}
/**
* The list action is the default for the rest controller
* Forward to index
*/
public function listAction() {
$this->_forward ( 'index' );
}
/**
* The get action handles GET requests and receives an 'id' parameter; it
* should respond with the server resource state of the resource identified
* by the 'id' value.
*/
public function getAction() {
$this->view->book = $this->_booksTable->find ( $this->_getParam ( 'id' ) )->current ();
}
/**
* Show the new book form
*/
public function newAction() {
$this->view->form = $this->_form;
}
/**
* The post action handles POST requests; it should accept and digest a
* POSTed resource representation and persist the resource state.
*/
public function postAction() {
if ($this->_form->isValid ( $this->_request->getParams () )) {
$this->_booksTable->createRow ( $this->_form->getValues () )->save ();
$this->_redirect ( 'books' );
} else {
$this->view->form = $this->_form;
$this->render ( 'new' );
}
}
/**
* Show the edit book form. Url format: /books/edit/2
*/
public function editAction() {
var_dump ($this->getRequest()->getParam ( 'edit' ));
$book = $this->_booksTable->find ( $this->getRequest()->getParam ( 'id' ) )->current ();
var_dump ($book->toArray ());
$this->_form->populate ( $book->toArray () );
$this->view->form = $this->_form;
$this->view->book = $book;
}
/**
* The put action handles PUT requests and receives an 'id' parameter; it
* should update the server resource state of the resource identified by
* the 'id' value.
*/
public function putAction() {
$book = $this->_booksTable->find ( $this->_getParam ( 'id' ) )->current ();
if ($this->_form->isValid ( $this->_request->getParams () )) {
$book->setFromArray ( $this->_form->getValues () )->save ();
$this->_redirect ( 'books' );
} else {
$this->view->book = $book;
$this->view->form = $this->_form;
$this->render ( 'edit' );
}
}
/**
* The delete action handles DELETE requests and receives an 'id'
* parameter; it should update the server resource state of the resource
* identified by the 'id' value.
*/
public function deleteAction() {
$book = $this->_booksTable->find ( $this->_getParam ( 'id' ) )->current ();
$book->delete ();
$this->_redirect ( 'books' );
}
}
The bootstrap is,
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
protected function _initAutoload() {
$autoloader = new Zend_Application_Module_Autoloader ( array (
'namespace' => 'Default_',
'basePath' => dirname ( __FILE__ )
) );
return $autoloader;
}
protected function _initRestRoute() {
$this->bootstrap ( 'Request' );
$front = $this->getResource ( 'FrontController' );
$restRoute = new Zend_Rest_Route ( $front, array (), array (
'default' => array ('books' )
) );
$front->getRouter ()->addRoute ( 'rest', $restRoute );
}
protected function _initRequest() {
$this->bootstrap ( 'FrontController' );
$front = $this->getResource ( 'FrontController' );
$request = $front->getRequest ();
if (null === $front->getRequest ()) {
$request = new Zend_Controller_Request_Http ();
$front->setRequest ( $request );
}
return $request;
}
}
Can anyone see what might be causing the getAction to be called when browsing to that link ???
edit should follow the identifier, so the correct edit URL is http://localhost/books/1/edit

Categories