Is it possible to use custom fields and filtering in asset views and filter by a range of birth dates?

@jgOhYeah Hey! Just got off the weekly farmOS dev call and we discussed the “Asset Ownership” issue a bit.

Have you created a module that adds an Owner field to assets already? One of the things we discussed on the call was adding that field in farmOS core, in the same module that adds it to Logs: farmOS/farm_owner.module at eb6f1043da00b7b21d122d3cba626c4d026371c3 · farmOS/farmOS · GitHub

It would be easy enough for farmOS core to provide this field. But I realized this could create a conflict with your custom module in the future if you create a field with the same name.

Would you like to open a PR to add the field to farmOS core in that module, instead of doing it in your own module?

We discussed a few of the considerations around “asset ownership” more generally on the call as well… I will put a few notes in the issue: Asset ownership [#2400065] | Drupal.org

Hello,
I have just submitted a pull request for adding to the fields documentation (Improving fields documentation by jgOhYeah · Pull Request #505 · farmOS/farmOS · GitHub).

I did make a custom module, but haven’t gotten around to publishing it (implementation is almost exactly the same as the logs ownership, with label being 'Owner(s)' and description being 'Who owns this asset.'). It’s field name is farm_owners, so hopefully shouldn’t cause too many conflicts. Entering stuff in from scratch wouldn’t take long, especially if there is a batch assign feature added like there currently is for the logs.

I am happy to create a pull request to add it in, probably following direction 1 in your notes (making it an assignment to, keeping the same wording as the logs rather than ownership of). A legal_ownership field could be added later or as a custom module (potentially this module would handle lease agreements as well) if needed, although direction 1 would be good enough for us.

1 Like

Hello,
I’ve got a development environment set up and am working in this branch. I have changed the if ($entity_type->id() == 'log') { line in farm_owner.module to if ($entity_type->id() == 'log' || $entity_type->id() == 'asset') { and and reinstalled farmOS, While assets now have an owner field, this does not show up in any of the views of assets. Is there something else that needs to be done for the field to show up or am I doing something wrong?

I had a similar experience with writing my own module, but found using a bundle field rather than a base field allowed ithe field to appear in views for each asset type and temporarily used that instead.

Thanks.

1 Like

Yes, so when adding a new “base field” like this, we will also need to add it to the default farm_asset View provided by the farm_ui_views module: farmOS/views.view.farm_asset.yml at 2.x · farmOS/farmOS · GitHub

The “right” way to do that is to edit the View through the Drupal UI (enable the views_ui module and go to /admin/structure/views/view/farm_asset), then export the YML and commit that (enable the “Configuration Manager” module and go to /admin/config/development/configuration/single/export/view/farm_asset to get the YML).

Be sure to stick to the same patterns/conventions when you add the new column via the Views UI (look to other asset reference fields for an example), and be thoughtful about where that field is organized among the columns - maybe after the “Parents” column?

1 Like

Thanks for the instructions. I have gotten that part working.

I think the next step is to get the bulk assign owners working like in the logs. I have had a look at the code and am thinking that the plugin in the owner module would need to be restructured a bit to be more like that in the flag module to cope with multiple entity types. Is this the case or is there a simpler method that I am missing? I have had a small attempt at the rearranging on my local copy, but seem to have created a moderate mess and need to go and do a bit more reading up how it is meant to work before trying again :). If this is painfully obvious or this feature is needed in a hurry, anybody feel free to have a go. Otherwise, I can keep having a look when I have a chance.

1 Like

I agree that’s probably the logical next step.

Note that there are three parts to the “Assign log” action…

  1. The action plugin: farmOS/LogAssign.php at 2.x · farmOS/farmOS · GitHub
  2. The action form: farmOS/LogAssignActionForm.php at 2.x · farmOS/farmOS · GitHub
  3. The routing configuration, which creates the /log/assign path and loads the LogAssignActionForm: farmOS/farm_owner.routing.yml at 2.x · farmOS/farmOS · GitHub

It may be possible to generalize LogAssignActionForm.php to AssignActionForm.php, such that it can be used for both. This looks to be the most important line, where it specifically loads the log entity type definition: farmOS/LogAssignActionForm.php at d2b512725ea2659bec10fbabf53fa60a9c3ddbe0 · farmOS/farmOS · GitHub

The routing config can be refactored to provide two paths: /log/assign and /asset/assign, and provide an additional argument to the LogAssignActionForm to define the entity type (asset or log). That should take care of the form.

As for src/Plugin/Action/LogAssign.php - I would probably create a new AssignBase.php class, which that extends from. Then create another AssetAssign.php action plugin class that also extends from it. The most important thing that needs to differ in each is this: farmOS/LogAssign.php at d2b512725ea2659bec10fbabf53fa60a9c3ddbe0 · farmOS/farmOS · GitHub

@jgOhYeah Another thought just came to mind… In the /people page, we have a column “Assigned logs”. It probably makes sense for there to be another column for “Assigned assets” alongside this new asset owner field.

Thanks for the instructions and hints. I thought of this too and had a go at making this work using the views ui and copying the settings from the assigned logs button, although I forgot I had done it to mention it :slight_smile: .

A couple of screenshots of it currently:


2 Likes

@jgOhYeah: Very nice!!

Hello again,
Apologies it has taken so long, but I think I have got everything working for adding assign users to assets… when installing from scratch. This is pretty much along the lines of the changes you suggested.

I have attempted to write an update hook to add the changes required. The update.php file crashes, but seems to install the updates ok with drush (drush updatedb). Everything then works except that the bulk assign assets option doesn’t appear.

I have been simulating updating by starting from beta 4 and entering some example data, before checking out the branch I have been working in. The update . I also tried to update from beta 2 to this branch on our production system with the same results.

The error (useful part) from running update.php:

[Mon Apr 25 01:17:38.167000 2022] [php7:notice] [pid 14117] [client 192.168.0.186:60250] Uncaught PHP Exception Drupal\\Core\\Entity\\Sql\\SqlContentEntityStorageException: "Table information not available for the 'owner' field." at /var/www/html/farmOS/web/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php line 391

Does anyone know or can give hints on what I am doing wrong or what I should be doing to get this working? Thanks for your help.

1 Like

The update.php file crashes, but seems to install the updates ok with drush ( drush updatedb ).

Hmm that’s suspicious. Can you check /admin/reports/dblog to see if there are any error messages or clues about the error/crash?

Edit: oops I should have finished reading your comment. :slight_smile:

It sounds like the field is not being created in the database. Hmm…

Everything then works except that the bulk assign assets option doesn’t appear.

Ah yea there’s another small thing that needs to be done for this, I think. You need to create a config entity for the action in order to enable it.

Here is the equivalent config for the existing “Assign” action for logs: farmOS/system.action.log_assign_action.yml at 2.x · farmOS/farmOS · GitHub

That config entity gets created automatically when the module is installed. But for existing installations you will need to create it via your update hook.

I think it would look like this (untested):

use Drupal\system\Entity\Action;

...
/**
 * Add 'owner' field to assets.
 */
function farm_owner_update_9001() {

  // ... your other code

  // Create action for assigning assets to users.
  $action = Action::create([
    'id' => 'asset_assign_action',
    'label' => t('Assign asset'),
    'type' => 'asset',
    'plugin' => 'asset_assign_action',
    'configuration' => [],
  ]);
  $action->save();
}
1 Like

Thanks. That makes sense. I will have more of a look tomorrow.

1 Like

It sounds like the field is not being created in the database. Hmm…

I’m a bit stumped on this… without testing directly myself. It looks like what you’re doing is correct.

Did I share that example update hook code with you or did you find it somewhere? Can’t remember… :slight_smile:

I’m looking at a recent example where I did this myself, and I actually used hook_post_update_NAME() instead of hook_update_N()

https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Extension!module.api.php/function/hook_post_update_NAME

Example: farm_surveystack/farm_surveystack.post_update.php at 61b85d7e237bc5971919ac7c44c5c29849737e94 · mstenta/farm_surveystack · GitHub

Post-update hooks run after other update hooks, and have a few other important differences (see doc link above for more info). Notably, they have a full Drupal bootstrap available to them, whereas some things are not possible in hook_update_N(). So maybe creating field definitions in this way (perhaps also specifically using the farm_field.factory service like this) is not possible in hook_update_N().

In either case, I’m starting to use post update hooks myself more often, so it would probably be best to move to that anyway. Let’s see if that solves this…

1 Like

Sorry it has taken a while to get back - had a few assignments / tasks needing doing.

The update code was based off the Drupal examples and documentation. I can’t find the exact page, but this example is pretty similar to what I based it off.

I pasted this into the update hook and the assign action does appear and work for assets when running through drush.

Ta for linking that - make a bit more sense of what to aim for. farm_owner.install has been updated to be fairly similar in structure to the example you gave and renamed to farm_owner.post_update.php to match just in case. This works with drush, but still no luck with update.php.

Issue potentially found

I was about to add a few observations and press send, but then I happened to come across what I think is related or is the cause.

Line 17 in farm_owner.module causes the crash if || $entity_type->id() == 'asset' is present. If commented out so that the line is just if ($entity_type->id() == 'log') {, update.php is happy, although the owner field isn’t added to assets. Do you know of a workaround for this or is this likely a wild goose chase and the issue lies elsewhere? Thanks.

1 Like

Huh - that is strange.

One thing I was going to suggest (unrelated to that bug, but for the same line of code) is to change it to:

if (in_array($entity_type->id(), ['asset', 'log'])) {

I don’t know why the original code is causing any issue, though, so I’m not sure that would fix it. Still… maybe worth a try?

I’ve replaced this line with the in_array version, but no change. I will go over the rest of the changes in the next few days to make sure there isn’t something obviously wrong somewhere else, which is about all I can think to do at the moment.

1 Like

I don’t really understand why this would be an issue only during update.php - that’s the most confusing part… :thinking:

I might just have to carve out some time to test this myself.

@jgOhYeah I was able to replicate this locally. And I can roughly see what’s happening (with the help of XDebug). Still thinking through how to solve it…

Loading update.php seems to cause this code to run: src/EntityViewsData.php · efc5ae471b40427f19fca3cfe1524f7557d0cabc · project / entity · GitLab

Basically, the Entity API module is trying to add reverse relationships for all entity reference fields so that the Views module knows how to use them. In this case, it’s trying to figure out the database table name for the asset owner field - but this is running before the field is actually created.

I’m not sure why the same thing doesn’t happen during drush updb - or why this code runs while loading update.php

Here is the stack trace that leads up to the call to getFieldTableName() that happens when loading update.php (for future reference):

DefaultTableMapping.php:391, Drupal\Core\Entity\Sql\DefaultTableMapping->getFieldTableName()
EntityViewsData.php:371, Drupal\entity\EntityViewsData->addReverseRelationships()
EntityViewsDataTaxonomyFilterTrait.php:17, Drupal\farm_entity_views\FarmEntityViewsData->addReverseRelationships()
EntityViewsData.php:79, Drupal\entity\EntityViewsData->getViewsData()
views.views.inc:180, views_views_data()
ModuleHandler.php:392, call_user_func_array:{/opt/drupal/web/core/lib/Drupal/Core/Extension/ModuleHandler.php:392}()
ModuleHandler.php:392, Drupal\Core\Extension\ModuleHandler->invoke()
ViewsData.php:237, Drupal\views\ViewsData->getData()
ViewsData.php:154, Drupal\views\ViewsData->get()
ViewsEntityRow.php:91, Drupal\views\Plugin\Derivative\ViewsEntityRow->getDerivativeDefinitions()
DerivativeDiscoveryDecorator.php:101, Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator->getDerivatives()
DerivativeDiscoveryDecorator.php:87, Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator->getDefinitions()
DefaultPluginManager.php:285, Drupal\Core\Plugin\DefaultPluginManager->findDefinitions()
DefaultPluginManager.php:175, Drupal\Core\Plugin\DefaultPluginManager->getDefinitions()
views.module:146, views_theme()
Registry.php:469, Drupal\Core\Theme\Registry->processExtension()
Registry.php:356, Drupal\Core\Theme\Registry->build()
Registry.php:255, Drupal\Core\Theme\Registry->get()
ThemeRegistry.php:88, Drupal\Core\Utility\ThemeRegistry->initializeRegistry()
ThemeRegistry.php:69, Drupal\Core\Utility\ThemeRegistry->__construct()
Registry.php:275, Drupal\Core\Theme\Registry->getRuntime()
ThemeManager.php:142, Drupal\Core\Theme\ThemeManager->render()
Renderer.php:422, Drupal\Core\Render\Renderer->doRender()
Renderer.php:201, Drupal\Core\Render\Renderer->render()
Renderer.php:145, Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure:/opt/drupal/web/core/lib/Drupal/Core/Render/Renderer.php:144-146}()
Renderer.php:564, Drupal\Core\Render\Renderer->executeInRenderContext()
Renderer.php:146, Drupal\Core\Render\Renderer->renderRoot()
BareHtmlPageRenderer.php:66, Drupal\Core\Render\BareHtmlPageRenderer->renderBarePage()
BareHtmlPageRenderer.php:76, Drupal\Core\ProxyClass\Render\BareHtmlPageRenderer->renderBarePage()
DbUpdateController.php:196, Drupal\system\Controller\DbUpdateController->handle()
UpdateKernel.php:115, call_user_func_array:{/opt/drupal/web/core/lib/Drupal/Core/Update/UpdateKernel.php:115}()
UpdateKernel.php:115, Drupal\Core\Update\UpdateKernel->handleRaw()
UpdateKernel.php:76, Drupal\Core\Update\UpdateKernel->handle()
update.php:27, {main}()

This may be related to (or caused by) this patch that we are applying to the Entity API module: Provide reverse relationships for bundle plugin entity_reference fields. [#3206703] | Drupal.org

In fact, I notice that @paul121 ran into the same error during the development of that patch: Provide reverse relationships for bundle plugin entity_reference fields. [#3206703] | Drupal.org

It may be that we need to expand that patch to handle this new case you’ve identified @jgOhYeah. Perhaps update.php wasn’t tested during that patch’s development, so it slipped between the cracks…