Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling the ChannelEntry model within a ft file while editing an entry causes havoc #2117

Open
litzinger opened this issue Jun 21, 2022 · 5 comments

Comments

@litzinger
Copy link
Contributor

In my Advanced Categories field I need to figure out what categories are assigned to the current channel, so I end up making this call within an ft file:

$entry = ee('Model')->get('ChannelEntry', $entryId)->first();

but in doing so, it really messes up the current context of $this, as it in nullifies basically everything if I try to reference something like $this->content_id - it's just null. I'm having to capture relevant properties from the ft file in an array, make the ChannelEntry model call, then reset the properties on $this just so it would work.

I don't know what the root issue is here, probably something deep in the Model classes, but it would be nicer if the ft file actually knew what entry it was being loaded in, and better yet, have a reference to the current channel. For example, these would be a really helpful property to have in ft files:

$this->ChannelEntry;
$this->Channel;

For full context, here is some code from my ft file:

/**
     * @return array
     */
    private function getEntryCategories(): array
    {
        $entryId = $this->content_id;

        if (!$entryId) {
            return [];
        }

        if ($cache = $this->cache->get('entryCategories')) {
            return $cache;
        }

        $context = [
            'field_id' => $this->field_id,
            'field_name' => $this->field_name,
            'id' => $this->id,
            'name' => $this->name,
            'content_id' => $this->content_id,
            'content_type' => $this->content_type,
            'settings' => $this->settings,
        ];

        $entry = ee('Model')->get('ChannelEntry', $entryId)->first();
        $this->fixContext($context);

        // Cast them to a string just so it's consistent with what is return from the saved JSON object in the custom field.
        $cats = array_map(function ($value) {
            return (string) $value;
        }, $entry->Categories->pluck('cat_id'));

        $this->cache->set('entryCategories', $cats);

        return $cats;
    }

    /**
     * @param int $entryId
     * @return ChannelModel
     */
    private function getChannel($entryId = 0): ChannelModel
    {
        if ($cache = $this->cache->get('channel')) {
            return $cache;
        }

        $context = [
            'field_id' => $this->field_id,
            'field_name' => $this->field_name,
            'id' => $this->id,
            'name' => $this->name,
            'content_id' => $this->content_id,
            'content_type' => $this->content_type,
            'settings' => $this->settings,
        ];

        if ($entryId) {
            $entry = ee('Model')->get('ChannelEntry', $entryId)->first();
            $this->fixContext($context);
            $this->cache->set('channel', $entry->Channel);

            return $entry->Channel;
        }

        if (!$entryId && preg_match('/cp\/publish\/create\/(\d+)/', ee()->uri->query_string, $matches)) {
            $channel = ee('Model')->get('Channel', (int) $matches[1])->first();
            $this->fixContext($context);
            $this->cache->set('channel', $channel);

            return $channel;
        }

        if (!$entryId && preg_match('/cp\/publish\/edit\/entry\/(\d+)/', ee()->uri->query_string, $matches)) {
            $entry = ee('Model')->get('ChannelEntry', $matches[1])->first();
            $this->fixContext($context);
            $this->cache->set('channel', $entry->Channel);
        }

        return $entry->Channel;
    }

    /**
     * Fix some _really_ weird behavior where calling ee('Model')->get('ChannelEntry', $entryId)->first() resets
     * the properties on the current context of $this, which should be an instance of Advanced_categories_ft
     * Behavior seems to have started in a more recent version of EE, because this used to not be an issue.
     *
     * @param array $context
     * @return void
     */
    private function fixContext(array $context = [])
    {
        foreach ($context as $property => $value) {
            $this->{$property} = $value;
        }
    }
@TomJaeger
Copy link
Contributor

Any chance you happen to know if this came up in a specific version or anything along those lines?

@litzinger
Copy link
Contributor Author

I don't have specifics. I just know that I'm pretty confident this wasn't an issue when I first created at the add-on, then recently it was very easy to replicate. I upgraded to 6.3.4 just a couple weeks ago. I don't recall the version I had before 6.3.4, but I might have skipped a few versions.

I have not gotten around to trying to replicate this in a fresh EE install either.

@TomJaeger
Copy link
Contributor

Solid, thank you!

Was it EE 6 before the upgrade to 6.3.4 though?

@litzinger
Copy link
Contributor Author

litzinger commented Jun 26, 2022

I tested this in a separate EE environment in 6.3.4 with the following code. If I'm editing entry #80678, the second var_dump has null values for all the keys. If I choose another random entry id, such as #80682, as the parameter in the get() function while still viewing #80678, the second var_dump is identical to the first. So by calling ChannelEntry model with the same ID as the currently viewed entry, seems to cause the problem.

$context = [
            'field_id' => $this->field_id,
            'field_name' => $this->field_name,
            'id' => $this->id,
            'name' => $this->name,
            'content_id' => $this->content_id,
            'content_type' => $this->content_type,
            'settings' => $this->settings,
        ];

        $entry = ee('Model')->get('ChannelEntry', 80678)->first();

        var_dump($context, [
            'field_id' => $this->field_id,
            'field_name' => $this->field_name,
            'id' => $this->id,
            'name' => $this->name,
            'content_id' => $this->content_id,
            'content_type' => $this->content_type,
            'settings' => $this->settings,
        ]); 
die;

@litzinger
Copy link
Contributor Author

I tried the same thing in a 6.2.2 version of the same environment, and the issue didn't happen. So something changed between 6.2.2 and 6.3.4 to introduce this behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants