0 VDM\Joomla\Componentbuilder\Compiler\Language\Update::set(): Argument #2 ($target) must be of type string, array given, called in C:\laragon\www\joomla3\libraries\vendor_jcb\VDM.Joomla\src\Componentbuilder\Compiler\Language\Purge.php on line 165 #1172

Closed
opened 2024-09-15 09:11:46 +00:00 by dannunz81 · 8 comments

Steps to reproduce the issue

Good morning, I'm asking for your help in solving a problem that I can't overcome on my own. I'm trying to create a component for the first time. I just created an admin view with a couple of fields and then added the translations in my language.
The error appears when I try to compile the component.

Expected result

compiled component

Actual result

0 VDM\Joomla\Componentbuilder\Compiler\Language\Update::set(): Argument #2 ($target) must be of type string, array given, called in C:\laragon\www\joomla3\libraries\vendor_jcb\VDM.Joomla\src\Componentbuilder\Compiler\Language\Purge.php on line 165

System information (as much as possible)

  • OS Name & Version: Windows 11
  • MySql Version: 8.0.30 winx64
  • Apache Version: 2.4.54 win 64 VS 16
  • PHP Version: 7.4.30 - 8.1.10 - 8.1.27 - 8.2.14 - 8.3.1
  • Joomla Version: 3.10.12
  • JCB Version: 3.2.3
  • Browser: Firefox 130.0 (64 bit)

Additional comments

I would exclude the PHP version as the cause of the problem because I tried with different versions.

Thank you

### Steps to reproduce the issue Good morning, I'm asking for your help in solving a problem that I can't overcome on my own. I'm trying to create a component for the first time. I just created an admin view with a couple of fields and then added the translations in my language. The error appears when I try to compile the component. ### Expected result compiled component ### Actual result 0 VDM\Joomla\Componentbuilder\Compiler\Language\Update::set(): Argument #2 ($target) must be of type string, array given, called in C:\laragon\www\joomla3\libraries\vendor_jcb\VDM.Joomla\src\Componentbuilder\Compiler\Language\Purge.php on line 165 ### System information (as much as possible) - OS Name & Version: Windows 11 - MySql Version: 8.0.30 winx64 - Apache Version: 2.4.54 win 64 VS 16 - PHP Version: 7.4.30 - 8.1.10 - 8.1.27 - 8.2.14 - 8.3.1 - Joomla Version: 3.10.12 - JCB Version: 3.2.3 - Browser: Firefox 130.0 (64 bit) ### Additional comments I would exclude the PHP version as the cause of the problem because I tried with different versions. Thank you
Owner

I will take a look at this... are you able to debug this?

I will take a look at this... are you able to debug this?
Author

I don't know what to do...

I don't know what to do...
Member

I just ran into this same error when i upgraded a component dev enviro from j3 to j5. On J5 i can still compile fine for J3 but when i tick option to compile for J5 i get the exact same error.

I just ran into this same error when i upgraded a component dev enviro from j3 to j5. On J5 i can still compile fine for J3 but when i tick option to compile for J5 i get the exact same error.
Member

on this line you clearly see it is sending an array to a function that should get a string as second parameter:

$this->update->set($item['id'], $targets, $targets, 2, $today, $counter);

on this line you clearly see it is sending an array to a function that should get a string as second parameter: https://git.vdm.dev/joomla/Component-Builder/src/commit/3b502eb09bae69a2ccf8ed344d07b5741bb8b198/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Language/Purge.php#L165
Member

Link of the target function it is sent to:

public function set(int $id, string $target, array $targets, int $published, string $today, int $counter): void

Link of the target function it is sent to: https://git.vdm.dev/joomla/Component-Builder/src/commit/3b502eb09bae69a2ccf8ed344d07b5741bb8b198/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Language/Update.php#L75
Member

it's an empty array that is in the $targets variable.

it's an empty array that is in the $targets variable.
Owner

I refactored the Purge class a little, if you can drop it in place and test and let me know if it resolves the bug.

replace all code in libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Language/Purge.php with the code below

<?php
/**
 * @package    Joomla.Component.Builder
 *
 * @created    4th September, 2022
 * @author     Llewellyn van der Merwe <https://dev.vdm.io>
 * @git        Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
 * @copyright  Copyright (C) 2015 Vast Development Method. All rights reserved.
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 */

namespace VDM\Joomla\Componentbuilder\Compiler\Language;


use Joomla\CMS\Factory;
use VDM\Joomla\Componentbuilder\Compiler\Language\Update;
use VDM\Joomla\Utilities\JsonHelper;
use VDM\Joomla\Utilities\ArrayHelper;


/**
 * Compiler Remove Existing Language Strings
 * 
 * @since 5.0.2
 */
final class Purge
{
	/**
	 * The Update Class.
	 *
	 * @var   Update
	 * @since 5.0.2
	 */
	protected Update $update;

	/**
	 * Database object to query local DB
	 *
	 * @since 5.0.2
	 **/
	protected $db;

	/**
	 * Constructor.
	 *
	 * @param Update $update The Update Class.
	 *
	 * @since 5.0.2
	 */
	public function __construct(Update $update)
	{
		$this->update = $update;
		$this->db = Factory::getDbo();
	}

	/**
	 * Purge unused language strings linked to a component.
	 *
	 * This method removes or updates language strings that are no longer linked
	 * to the specified component. It checks if the strings are linked to other
	 * extensions and either updates, archives, or deletes them based on the
	 * conditions.
	 *
	 * @param array  $values     Active string sources.
	 * @param string $targetGuid The GUID of the target entity.
	 * @param string $target     Target extension type. Default: 'components'.
	 *
	 * @return void
	 * @since  5.0.2
	 */
	public function execute(array $values, string $targetGuid, string $target = 'components'): void
	{
		$validTargets = ['components' => 'components', 'modules' => 'modules', 'plugins' => 'plugins'];

		if (!isset($validTargets[$target]))
		{
			return;
		}

		$otherTargets = array_diff_key($validTargets, [$target => $target]);

		$query = $this->db->getQuery(true)
			->select($this->db->quoteName(['id', 'translation', 'components', 'modules', 'plugins']))
			->from($this->db->quoteName('#__componentbuilder_language_translation', 'a'))
			->where($this->db->quoteName('a.source') . ' NOT IN (' . implode(',', array_map([$this->db, 'quote'], $values)) . ')')
			->where($this->db->quoteName('a.published') . ' = 1');

		$this->db->setQuery($query);
		$this->db->execute();

		if (!$this->db->getNumRows())
		{
			return;
		}

		$today         = Factory::getDate()->toSql();
		$items         = $this->db->loadAssocList();
		$counterUpdate = 0;

		foreach ($items as $item)
		{
			if (!JsonHelper::check($item[$target]))
			{
				continue;
			}

			$targets = (array) json_decode((string) $item[$target], true);

			if (($key = array_search($targetGuid, $targets, true)) === false)
			{
				continue;
			}

			unset($targets[$key]);

			if (ArrayHelper::check($targets))
			{
				$this->update->set($item['id'], $target, $targets, 1, $today, $counterUpdate);
				$counterUpdate++;
				$this->update->execute(50);
			}
			else
			{
				$this->handleUnlinkedString($item, $otherTargets, $target, $targets, $today, $counterUpdate);
			}
		}

		$this->update->execute();
	}

	/**
	 * Handle strings no longer linked to the current component.
	 *
	 * @param array  $item        The language string item.
	 * @param array  $otherTypes  Other extension types.
	 * @param string $target      The current target extension type.
	 * @param array  $targets     Remaining targets to update.
	 * @param string $today       Current date in SQL format.
	 * @param int    $counter     Counter for updates.
	 *
	 * @return void
	 * @since  5.0.2
	 */
	protected function handleUnlinkedString(array $item, array $otherTypes, string $target,
		array $targets, string $today, int &$counter): void
	{
		$action = 1; // 1 = remove, 2 = archive, 0 = keep

		foreach ($otherTypes as $type)
		{
			if (JsonHelper::check($item[$type]))
			{
				$linked = json_decode((string) $item[$type], true);
				if (ArrayHelper::check($linked))
				{
					$action = 0;
					break;
				}
			}
		}

		if ($action && JsonHelper::check($item['translation']))
		{
			$translation = json_decode((string) $item['translation'], true);

			if (ArrayHelper::check($translation))
			{
				$this->update->set($item['id'], $target, $targets, 2, $today, $counter);
				$counter++;
				$this->update->execute(50);
				$action = 2; // just to show intent :)
				return;
			}
		}

		if ($action === 1)
		{
			$this->removeLanguageString($item['id']);
		}
	}

	/**
	 * Delete a language string by ID.
	 *
	 * @param int $id The ID of the string.
	 *
	 * @return void
	 * @since  5.0.2
	 */
	protected function removeLanguageString(int $id): void
	{
		$query = $this->db->getQuery(true)
			->delete($this->db->quoteName('#__componentbuilder_language_translation'))
			->where($this->db->quoteName('id') . ' = ' . (int) $id);

		$this->db->setQuery($query);
		$this->db->execute();
	}
}

I refactored the Purge class a little, if you can drop it in place and test and let me know if it resolves the bug. > replace all code in `libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Language/Purge.php` with the code below ```php <?php /** * @package Joomla.Component.Builder * * @created 4th September, 2022 * @author Llewellyn van der Merwe <https://dev.vdm.io> * @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder> * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace VDM\Joomla\Componentbuilder\Compiler\Language; use Joomla\CMS\Factory; use VDM\Joomla\Componentbuilder\Compiler\Language\Update; use VDM\Joomla\Utilities\JsonHelper; use VDM\Joomla\Utilities\ArrayHelper; /** * Compiler Remove Existing Language Strings * * @since 5.0.2 */ final class Purge { /** * The Update Class. * * @var Update * @since 5.0.2 */ protected Update $update; /** * Database object to query local DB * * @since 5.0.2 **/ protected $db; /** * Constructor. * * @param Update $update The Update Class. * * @since 5.0.2 */ public function __construct(Update $update) { $this->update = $update; $this->db = Factory::getDbo(); } /** * Purge unused language strings linked to a component. * * This method removes or updates language strings that are no longer linked * to the specified component. It checks if the strings are linked to other * extensions and either updates, archives, or deletes them based on the * conditions. * * @param array $values Active string sources. * @param string $targetGuid The GUID of the target entity. * @param string $target Target extension type. Default: 'components'. * * @return void * @since 5.0.2 */ public function execute(array $values, string $targetGuid, string $target = 'components'): void { $validTargets = ['components' => 'components', 'modules' => 'modules', 'plugins' => 'plugins']; if (!isset($validTargets[$target])) { return; } $otherTargets = array_diff_key($validTargets, [$target => $target]); $query = $this->db->getQuery(true) ->select($this->db->quoteName(['id', 'translation', 'components', 'modules', 'plugins'])) ->from($this->db->quoteName('#__componentbuilder_language_translation', 'a')) ->where($this->db->quoteName('a.source') . ' NOT IN (' . implode(',', array_map([$this->db, 'quote'], $values)) . ')') ->where($this->db->quoteName('a.published') . ' = 1'); $this->db->setQuery($query); $this->db->execute(); if (!$this->db->getNumRows()) { return; } $today = Factory::getDate()->toSql(); $items = $this->db->loadAssocList(); $counterUpdate = 0; foreach ($items as $item) { if (!JsonHelper::check($item[$target])) { continue; } $targets = (array) json_decode((string) $item[$target], true); if (($key = array_search($targetGuid, $targets, true)) === false) { continue; } unset($targets[$key]); if (ArrayHelper::check($targets)) { $this->update->set($item['id'], $target, $targets, 1, $today, $counterUpdate); $counterUpdate++; $this->update->execute(50); } else { $this->handleUnlinkedString($item, $otherTargets, $target, $targets, $today, $counterUpdate); } } $this->update->execute(); } /** * Handle strings no longer linked to the current component. * * @param array $item The language string item. * @param array $otherTypes Other extension types. * @param string $target The current target extension type. * @param array $targets Remaining targets to update. * @param string $today Current date in SQL format. * @param int $counter Counter for updates. * * @return void * @since 5.0.2 */ protected function handleUnlinkedString(array $item, array $otherTypes, string $target, array $targets, string $today, int &$counter): void { $action = 1; // 1 = remove, 2 = archive, 0 = keep foreach ($otherTypes as $type) { if (JsonHelper::check($item[$type])) { $linked = json_decode((string) $item[$type], true); if (ArrayHelper::check($linked)) { $action = 0; break; } } } if ($action && JsonHelper::check($item['translation'])) { $translation = json_decode((string) $item['translation'], true); if (ArrayHelper::check($translation)) { $this->update->set($item['id'], $target, $targets, 2, $today, $counter); $counter++; $this->update->execute(50); $action = 2; // just to show intent :) return; } } if ($action === 1) { $this->removeLanguageString($item['id']); } } /** * Delete a language string by ID. * * @param int $id The ID of the string. * * @return void * @since 5.0.2 */ protected function removeLanguageString(int $id): void { $query = $this->db->getQuery(true) ->delete($this->db->quoteName('#__componentbuilder_language_translation')) ->where($this->db->quoteName('id') . ' = ' . (int) $id); $this->db->setQuery($query); $this->db->execute(); } } ```
Owner

This bug has been resolved in newer versions of JCB and is no longer present in the current JCB 4.x, 5.x, and 6.x implementations.

Since the refactoring work explained here in this issue has been moved into JCB and is in the latest release, we will be closing this issue.

This bug has been resolved in [newer versions of JCB](https://git.vdm.dev/joomla/pkg-component-builder/releases/) and is no longer present in the current JCB [4.x](https://git.vdm.dev/joomla/pkg-component-builder/releases/tag/v4.2.0), [5.x](https://git.vdm.dev/joomla/pkg-component-builder/releases/tag/v5.2.0), and [6.x](https://git.vdm.dev/joomla/pkg-component-builder/releases/tag/v6.2.0) implementations. Since the refactoring work explained here in this issue has been moved into JCB and is in the latest release, we will be closing this issue.
Sign in to join this conversation.
4 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: joomla/Component-Builder#1172