Undefined variable error in ExpressionEngine plugin - expressionengine

I'm working on a plugin that does device detection based on an external library.
This is what I have so far:
class Deetector {
// public $return_data;
/**
* Constructor
*/
public function __construct()
{
$this->EE =& get_instance();
$this->EE->load->add_package_path(PATH_THIRD.'/deetector');
$this->EE->load->library('detector');
$this->return_data = "";
}
public function deetector()
{
return $ua->ua;
}
public function user_agent()
{
return $ua->ua;
}
// ----------------------------------------------------------------
/**
* Plugin Usage
*/
public static function usage()
{
ob_start();
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
}
}
If I call {exp:deetector} I get no output in the template. If I call {exp:deetector:user_agent} I get Undefined variable: ua.
Ultimately I don't plan on setting up different functions for each of the variables that the Detector library returns but am just trying to get it to output something at the moment.
I had originally started doing this as an extension which added the Detector library's variables to the global variables array and that was working fine; it's only since trying to do it as a plugin that I've run into problems.

You haven't set $this->ua to anything. I assume it's a variable of the detector library you loaded, so you probably want to do something like this:
class Deetector {
public function __construct()
{
$this->EE =& get_instance();
// remove this line, it's probably not doing anything
// $this->EE->load->add_package_path(PATH_THIRD.'/deetector');
$this->EE->load->library('detector');
// note you use $this->return_data instead of "return blah" in the constructor
$this->return_data = $this->EE->detector->ua;
}
// remove this, you can't have both __construct() and deetector(), they mean the same thing
// public function deetector()
// {
// return $ua->ua;
// }
public function user_agent()
{
return $this->EE->detector->ua;
}
}
UPDATE:
I took a look at the Detector docs, and it doesn't follow normal library conventions (it defines the $ua variable when you include the file). For that reason you should ignore the standard EE load functions, and include the file directly:
class Deetector {
public function __construct()
{
$this->EE =& get_instance();
// manually include the detector library
include(PATH_THIRD.'/deetector/libraries/detector.php');
// save the local $ua variable so we can use it in other functions further down
$this->ua = $ua;
// output the user agent in our template
$this->return_data = $this->ua->ua;
}
}

Related

Maatwebsite excel Serialization of 'PDO' is not allowed

Im tring to export large data in queue on s3 and getting Serialization of 'PDO' is not allowed exception/ Here is my code:
Controller
$transactions = Transaction::query()
->with([
'user',
'user.profile',
'senderUser',
'receiverUser',
'senderUser.roles',
'receiverUser.roles'
])->filterByUser()
->filter($filters)
->orderByDesc('created_at');
if (request()->export_transactions){
(new TransactionsExport(auth('sanctum')->user(),$transactions))->store('transactions-exports/' . now()->format('d:m:Y') . '.csv', 's3', \Maatwebsite\Excel\Excel::CSV);
return response()->json('Export started');
}
Export file
class TransactionsExport implements FromQuery, WithMapping, WithHeadings, WithCustomQuerySize, ShouldQueue
{
use Exportable;
private $user;
private $transactions;
public function __construct(User $user, $transactions)
{
$this->user = $user;
$this->transactions = $transactions;
}
/**
* #return Builder
*/
public function query()
{
return $this->transactions;
}
public function querySize(): int
{
return $this->transactions->count();
}
public function headings(): array
{
return [
//headings
];
}
public function prepareRows($transactions): array
{
//code here
}
public function map($transaction): array
{
//code here
}
}
I also tried to trigger it like this (with additional paramethers and without and with different allowed methods (store, download etc.))
(new TransactionsExport(auth('sanctum')->user(),$transactions))->queue('transactions-exports/' . now()->format('d:m:Y') . '.csv', 's3', \Maatwebsite\Excel\Excel::CSV);
Also, I tried move Transaction::query() direct to query method in export file.
Also didnt help toSql() method (Call to a member function count() on string exception appears)
Don't know what I'm doing wrong. Thanks for help.
I have solved the problem by deleting the injection of classes in the constructor, it's not allowed in jobs (queues/ if you need an object of a class, better to call it like new Class()), and now all is working fine.

C# Unity InjectionFactory not working

I am using Unity as IOC and trying to inject an interface with a factory method which takes a interface as a parameter.
For some reason the configReader parameter in the factory method GetTitleParser(), is null and not getting the injected ConfigurationReader() instance.
When i place a debug point at the line in RegisterTypes method where the new InjectionFactory exists, ITitleParser is not showing as mapped to a proper mapped type.
can anyone help what am i doing wrong here?
Here is my code:
public class UnityContainerBuilder
{
public static IUnityContainer Build()
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
}
public static void RegisterTypes(IUnityContainer container)
{
// NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
container.LoadConfiguration();
container.RegisterType<IConfigurationReader, ConfigurationReader>();
container.RegisterType<ITitleParser>(new InjectionFactory(c => ParserFactory.GetTitleParser()));
}
}
public class ParserFactory
{
public static ITitleParser GetTitleParser(IConfigurationReader configReader=null)
{
if(configReader==null) configReader = new ConfigurationReader();
/* rest of code here...*/
return parser;
}
}
It works when i use the following code. Is this the right way to do this?
container.RegisterType<IConfigurationReader, ConfigurationReader>();
container.RegisterType<ITitleParser>(new InjectionFactory(c =>
{
var configReader = c.Resolve<IConfigurationReader>();
var parser = ParserFactory.GetTitleParser(configReader);
return parser;
}));
When you use default parameters it's equal to:
container.RegisterType<ITitleParser>(
new InjectionFactory(c => ParserFactory.GetTitleParser(null)));
Because, compiler inserts all default values in method calls (null in your case).
So, your code is valid:
container.RegisterType<ITitleParser>(new InjectionFactory(c =>
{
var configReader = c.Resolve<IConfigurationReader>();
var parser = ParserFactory.GetTitleParser(configReader);
return parser;
}));
But i advice you to remove default value to make code more expressive.
Your code is valid but maybe you can avoid messing up with InjectionFactory parameters and ParserFactory.
public class UnityContainerBuilder
{
public static IUnityContainer Build()
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
}
public static void RegisterTypes(IUnityContainer container)
{
// NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
container.LoadConfiguration();
container.RegisterType<IConfigurationReader, ConfigurationReader>();
container.RegisterInstance<IAppConfig>(container.Resolve<IConfigurationReader>().ReadConfiguration());
container.RegisterType<ITitleParser, TitleParser>();
}
}
public class AppConfig: IAppConfig
{
public AppConfig(){}
//value1 property
//value2 property
//etc
}
public class ConfigurationReader: IConfigurationReader
{
public ConfigurationReader(){}
public IAppConfig ReadConfiguration(){
var currentConfig = new AppConfig();
//read config from file, DB, etc and init currentCongif
return currentConfig;
}
}
public class TitleParser : ITitleParser
{
public TitleParser(IAppConfif)
{
//config already readed, just do the work
}
}

How to create namespace hierarchy in node.js addon?

I'm creating a node.js addon, which has bunch of classes. I want to organize them in a hierarchical namespace. If I were doing this in Javascript it would look like this
var com = function() {};
com.example = function() {};
com.example.Person = function () {};
var p = new com.example.Person();
I'm using Nan to write my node.js binding. To achieve the above result I've written code as follows:
com.h
namespace addon {
void init(Local<Object> exports);
}
com.cpp
void addon::init(Local<Object> exports)
{
addon::Example::Init(exports);
}
NODE_MODULE(com, com::init)
example.h
namespace addon {
class Example : public Nan::ObjectWrap {
static void Init(v8::Local<v8::Object> exports);
}
}
example.cpp
void addon::Example::Init(v8::Local<v8::Object> exports) {
// Prepare constructor template
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("example").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
addon::Person::Init(tpl);
constructor.Reset(tpl->GetFunction());
}
person.h
namespace addon {
class Person : public Nan::ObjectWrap {
static void Init(v8::Local<v8::FunctionTemplate> exports);
}
}
person.cpp
void addon::Person::Init(v8::Local<v8::FunctionTemplate> nmspace) {
Nan::HandleScope scope;
// Prepare constructor template
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Person").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// Prototype
// ...
constructor.Reset(tpl->GetFunction());
nmspace->Set(Nan::New("Person").ToLocalChecked(), tpl->GetFunction()); // XXXXXX
}
This code compiles and also successfully passes the tests when run. However I get a warning when the addon is loaded.
(node) v8::FunctionTemplate::Set() with non-primitive values is deprecated
(node) and will stop working in the next major release.
It prints a stack trace. The top of this trace is at the line marked XXXXXX.
If this is not the recommended way to define a FunctionTemplate as a member of another FunctionTemplate, then what's the right way to achieve it? Any ideas?
I found an easy way to do this. It occured to me that I could achieve the same thing with the following Javascript code.
var com = {};
com.example = {};
com.example.Person = function () {};
var p = new com.example.Person();
So I found that it's totally unnecessary to define a ObjectWrap class for Example. Instead I defined it as a simple object
v8::Isolate *isolate = v8::Isolate::GetCurrent();
v8::Handle<Object> example = v8::Object::New(isolate);
and then passed it to Person::Init() like this
void addon::Person::Init(v8::Local<v8::Object> nmspace) {
// ...
nmspace->Set(Nan::New("Person").ToLocalChecked(), tpl->GetFunction());
}
The resulting code works without any warnings or errors.

Method MyClass::__get() must take exactly 1 argument

Im getting error, when im trying to create new instance of my class.
class MyClass
{
public $link;
public function __construct()
{
$this->Connect();
}
private function Connect()
{
$db_host = DB_HOST; // defined in included file
$db_name = DB_NAME; // defined in included file
$this->link = new PDO("mysql:host=$db_host;dbname=$db_name;charset=UTF-8", DB_USER, DB_PASSWORD);
$this->link->setAttribute(PDO::ATTR_AUTOCOMMIT,FALSE);
}
// other methods here
// there is no custom __get() method
}
Im trying to create new instance and use one of methods:
include "inc/myclass.php";
$db = new MyClass();
$db->InsertPost("2012-01-01 10:00", "Test content", "Test title");
Im getting error:
Method MyClass::__get() must take exactly 1 argument
I tried to add accessor without any parameter:
public function __get()
{
return $this;
}
But im still getting this error.
I had to override default accessor (get) like this:
public function __get($name)
{
return $this;
}
I don't understand why i need $name there, but it works perfect.

ViewHelper newable/injectable dilemma

I'm trying to design an application following Misko Heverys insights. It's an interesting experiment and a challenge. Currently I'm struggling with my ViewHelper implementation.
The ViewHelper decouples the model from the view. In my implementation it wraps the model and provides the API for the view to use. I'm using PHP, but I hope the implementation is readable for everyone:
class PostViewHelper {
private $postModel;
public function __construct(PostModel $postModel) {
$this->postModel = $postModel;
}
public function title() {
return $this->postModel->getTitle();
}
}
In my template (view) file this could be called like this:
<h1><?php echo $this->post->title(); ?></h1>
So far so good. The problem I have is when I want to attach a filter to the ViewHelpers. I want to have plugins that filter the output of the title() call. The method would become like this:
public function title() {
return $this->filter($this->postModel->getTitle());
}
I need to get observers in there, or an EventHandler, or whatever service (in what I see as a newable, so it needs to be passed in through the stack). How can I do this following the principles of Misko Hevery? I know how I can do this without it. I'm interested in how for I can take it and currently I don't see a solution. ViewHelper could be an injectable too, but then getting the model in there is the problem.
I didn't find the blog post you referenced very interesting or insightful.
What you are describing seems more like a Decorator than anything to do with dependency injection. Dependency injection is how you construct your object graphs, not their state once constructed.
That said, I'd suggest taking your Decorator pattern and running with it.
interface PostInterface
{
public function title();
}
class PostModel implements PostInterface
{
public function title()
{
return $this->title;
}
}
class PostViewHelper implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->post = $post;
}
public function title()
{
return $this->post->title();
}
}
class PostFilter implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->post = $post;
}
public function title()
{
return $this->filter($this->post->title());
}
protected function filter($str)
{
return "FILTERED:$str";
}
}
You'd simply use whatever DI framework you have to build this object graph like so:
$post = new PostFilter(new PostViewHelper($model)));
I often use this approach when building complex nested objects.
One problem you might run into is defining "too many" functions in your PostInterface. It can be a pain to have to implement these in every decorator class. I take advantage of the PHP magic functions to get around this.
interface PostInterface
{
/**
* Minimal interface. This is the accessor
* for the unique ID of this Post.
*/
public function getId();
}
class SomeDecoratedPost implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->_post = $post;
}
public function getId()
{
return $this->_post->getId();
}
/**
* The following magic functions proxy all
* calls back to the decorated Post
*/
public function __call($name, $arguments)
{
return call_user_func_array(array($this->_post, $name), $arguments);
}
public function __get($name)
{
return $this->_post->get($name);
}
public function __set($name, $value)
{
$this->_post->__set($name, $value);
}
public function __isset($name)
{
return $this->_post->__isset($name);
}
public function __unset($name)
{
$this->_post->__unset($name);
}
}
With this type of decorator in use, I can selectively override whatever method I need to provide the decorated functionality. Anything I don't override is passed back to the underlying object. Multiple decorations can occur all while maintaining the interface of the underlying object.

Resources