Comments (28)
Few updates have been made to the plugin which should hopefully resolve issues mentioned in this ticket. If anyone is still facing problem please reopen new issue with steps to reproduce.
from footprint.
Where is the save being called from?
from footprint.
I have an XpController
with an Add()
method.
public function add()
{
$xp = $this->Xp->newEntity();
if ($this->request->is('post')) {
$xp = $this->Xp->patchEntity($xp, $this->request->data);
if ($this->Xp->save($xp)) {
$response = ['result' => 'success', 'data' => $xp];
} else {
$response = ['result' => 'fail', 'data' => $xp];
}
}
$this->set('response', $response);
$this->set('_serialize', ['response']);
}
My full XpController
from footprint.
Weird.. Does your request data contain a user_id
by any chance?
from footprint.
Did you ever get this to work Cylindric? I noticed that you seem to be using https://github.com/ceeram/blame now. I'm having a similar issue.
from footprint.
@waspinator do u have a failing test? Would love to get to the end of this.
from footprint.
Sorry, yes I switched to Ceeram/blame just to get going. If I get time I'll try and spin up a test case, but I'm not massively familiar with tests for things like this, so it might take me a bit.
from footprint.
@Cylindric It's ok if you can't provide a test case. You can try to debug the issue and provide us some specifics about what's causing the problem.
from footprint.
I have the same issue, my options array in the FootprintBehaviour's beforeSave also looks weird:
object(ArrayObject) {
atomic => true
associated => [
'projects' => [],
'targetcompanies' => [],
'users' => [],
'cities' => [],
'companiestarget' => [],
'companies' => [],
'contacttypes' => []
]
checkRules => true
checkExisting => true
_primary => true
}
it doesn't contain any _footprint.id
plus, if I debug current(Hash::extract((array)$options, $this->config('propertiesMap.' . $field)))
it returns false....
from footprint.
@kristiyandobrev please answer the following so we can better assist you:
- what's the behavior's configuration like? (paste it please)
- what are you trying to do, what's the code for it?
- finally, what are you expecting?
from footprint.
Alright.
I will start from the last question 😸
finally, what are you expecting?
In my table ContactsTable I have a called created_by_id (note that it's not created_by) which I want to set to the current (logged) user's id, every time I am creating a new database record.
what are you trying to do, what's the code for it?
For the purpose I first install your plugin from the command line like:
composer require muffin/footprint:dev-master
then I add it to my bootstrap.php
Plugin::load('Muffin/Footprint');
As it was required I included the Muffin\Footprint\Auth\FootprintAwareTrait to my AppController:
My AuthComponent is configured to use the default Users table which in my case is also called Users therefore I didn't find necessary to add $this->_userModel = 'SomeOtherTable';
in the beforeFilter.
what's the behavior's configuration like? (paste it please)
As I mentioned above I want to set the created_by_id of my every new record ContactsTable to be the current/logged user's id, therefore I am adding the following behaviour to my ContactsTable.
To sum up, the above doesn't work for me. It inserts empty value for created_by_id in the ContactsTable.
I looked over the plugin, played a little bit with the debug option and what I found was that:
In FootprintListener
public function handleEvent(Event $event, $ormObject, $options)
{
$key = $this->config('optionKey');
if (empty($options[$key]) && !empty($this->_currentUser)) {
$options[$key] = $this->_currentUser;
}
debug($this->config('optionKey'));
}
The output of the above is actually a complete (not empty) entity of the logged user. But with further debugging I found that in FootprintBehaviour:
public function beforeSave(Event $event, Entity $entity, ArrayObject $options)
{
$eventName = $event->name();
$events = $this->config('events');
$new = $entity->isNew() !== false;
foreach ($events[$eventName] as $field => $when) {
if (!in_array($when, ['always', 'new', 'existing'])) {
throw new UnexpectedValueException(
sprintf('When should be one of "always", "new" or "existing". The passed value "%s" is invalid', $when)
);
}
if ($entity->dirty($field)) {
continue;
}
if ($when === 'always' ||
($when === 'new' && $new) ||
($when === 'existing' && !$new)
) {
$entity->set(
$field,
current(Hash::extract((array)$options, $this->config('propertiesMap.' . $field)))
debug(current(Hash::extract((array)$options, $this->config('propertiesMap.' . $field))));
);
}
}
}
The output of above debug is false and respectively I see empty value in my DB table (expects UUID not bool) which seems to be strange since the FootprintBehaviour I could actually see the entity that I need.
from footprint.
Hmm, this all seems good.
You are saying in the behavior you could see the user entity, in which case it would be an issue with extract that is heavily tested by cake's core.
Or maybe you meant you see the user in the listener? If so, could you please debug($options)
really early in the behavior's beforeSave()
method?
from footprint.
Here you go:
FootprintBehavior
public function beforeSave(Event $event, Entity $entity, ArrayObject $options)
{
debug($options);
die();
And the output is:
object(ArrayObject) {
atomic => true
associated => [
'projects' => [],
'targetcompanies' => [],
'createdby' => [],
'cities' => [],
'companiestarget' => [],
'companies' => [],
'contacttypes' => []
]
checkRules => true
checkExisting => true
_primary => true
}
Just like in my very first comment.
P.S
My doubts are that FootprintListener's handleEvent is not called at all in the beforeSave
from footprint.
The footprint listener is not used by the behavior, it listens to the controller. Am trying to grok this but all seems to be configured correctly.
I noticed you were pre-loading the models before setting up the Auth component which could have consequences. Any reason why you are _pre-_loading the models?
Have you been able to write a failing test?
from footprint.
Any reason why you are pre-loading the models?
Yes I need the for later actions.
Also here is the output of $this-Auth->user();--> LINK
Could it be because the user is not a clear entity but it has some associations ?
from footprint.
I can't grok the reason why it would fail. @ADmad any ideas?
from footprint.
Nope.
from footprint.
I'm having the same issue in my project, a little bit of investigation suggests the problem may be in CakePHP itself, as AuthComponent::_getUser() will short-circuit if the user can be retrieved from session storage without firing the Auth.afterIdentify event.
After adding the following on line 690 of AuthComponent, the event is now firing, and the current user gets as far as FootprintListener, but doesn't seem to be getting to the model.
$event = $this->dispatchEvent('Auth.afterIdentify', [$user]);
Going to keep investigating and see if I can find a fix
May be important, the model in question actually extends another model, so I have PostsTable
which extends Cake\ORM\Table
and QuestionsTable
which extends App\Model\Table\PostsTable
Edit: the above doesn't seem to be supported in CakePHP from what I can see reading cakephp/cakephp#4412
Second edit: Now seems to be working without me changing anything at all, might have been entirely due to the extending of the Table classes
from footprint.
I also have this problem. I use FootprintBehavior for two tables, with the first it works great, with the second it doesn't.
I put a breakpoint here:
Footprint/src/Event/FootprintListener.php
Line 80 in 0f31ad6
And another one here:
What I expect:
The first breakpoint fires at least once before the second breakpoint. (It is true for my table where it works)
What I observe:
The second breakpoint fires first! Variable inspection reveals that data is missing. The first breakpoint then fires several times.
I really do nothing special, I call parent::initialize() before loading models and AppController has the trait (obviously, as it wouldn't work for the other table otherwise). My behavior configuration is dead simple:
Case 1 (works):
$this->addBehavior('Muffin/Footprint.Footprint', [
'events' => ['Model.beforeSave' => ['user_id' => 'new']],
]);
Case 2 (doesn't work):
$this->addBehavior('Muffin/Footprint.Footprint', [
'events' => ['Model.beforeSave' => [
'owner_id' => 'new',
'modifiedby_id' => 'existing'
]],
]);
Thanks for any hints on how to further debug this!
from footprint.
Sorry everyone, really short on time, haven't looked into it yet.
If anyone can submit a failing test, it will definitely make things much easier ;)
from footprint.
I have the same issue by calling $table = TableRegistry::get($tableName);
in the Controller::beforeFilter()
event.
Sorry, but at the moment i do not have time to create a test case, but maybe this information helps.
from footprint.
I got some inspiration from Footprint plugin and end up with forking and modifying ceeram/blame plugin so that it can use custom fields. See the pull request here.
from footprint.
@kristiyandobrev Thanks for your reply. I was using https://github.com/ceeram/blame before, but this plugin is more flexible. For example in some models i need to insert automated information from models associated to the Users model.
from footprint.
@stmeyer A table initialized in Controller::beforeRender()
won't get the footprint since AuthComponent::startup()
has still not run. You can trying changing the auth config checkAuthIn
to 'Controller.initialize'
to make auth do the authentication check earlier and make user info available in beforeFilter().
from footprint.
@ADmad thanks for the hint. I changed the code so that I don't need to load tables in Controller::beforeFilter()
. If it is needed if future, if will test it
from footprint.
I finally found the source of my problems based on the discussion about AuthComponent::startup()
. I had called loadModel() in my controller's initialize()
. This is somewhat sensical, as also components are loaded in initialize()
.
I suggest to document that this plugin relies on late model loading.
from footprint.
The issues that I mentioned in my previous comment is still not resolved, after the update @ADmad @jadb any ideas ?
from footprint.
@kristiyandobrev You have messed up the behavior config and nested propertiesMap
inside events
.
from footprint.
Related Issues (20)
- Behaviour works in one model, does not in others HOT 1
- Does not work with Cake 3.5.* HOT 5
- Error on non existent element HOT 1
- Problem with foreign key constraint HOT 6
- CakePHP 3.6.12 Notice - Undefined property: UsersController::$_currentUserViewVar HOT 1
- Changing the _footprint option key HOT 2
- integration with authentication plugin HOT 1
- API Prefix routing error HOT 1
- updated_by field HOT 1
- Upgrade to cake 4.0.0 HOT 2
- Configuration problem HOT 6
- number of bound variables does not match number of tokens HOT 3
- Any way to make Muffin/Footprint work with CakeDC/Api?
- CakePHP 3.9.7 breaks muffin/footprint plugin #15377 HOT 5
- FootprintListener->handleEvent is never called HOT 3
- UnitTesting a controller whose model has footprint, fails under certain condition HOT 2
- Is the Authentication plugin required for this plugin to work? HOT 2
- (1.x) Add a configuration option for the Authentication event name to check HOT 1
- Cake5: Typed static property Muffin\Footprint\FootprintPlugin::$listener must not be accessed before initialization
- CakePHP 5 compatible stable release HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from footprint.