Getting ready for Joomla 4 #126

Closed
opened 2017-09-26 16:21:56 +00:00 by Llewellyn · 46 comments
Owner

You will see JCB is removing all repeatable fields from its back-end, this is because it has been deprecated.

I do not have the time to always be on top of the latest changes in the Joomla API, if you notice a change that will effect JCB, please open an issue on Github to give me and other a heads-up.

Lets work together so the JCB will function like a ship for us all over the troubled waters of Joomla's community driven development.

Objective is that JCB will always compile your component for the latest stable release of Joomla .

I am open for suggestions here, but it seems most doable to just keep adapting the compiler to work in the latest release of Joomla. So if you want to compile for earlier versions, you simply install and earlier JCB.

The other option is to allow compiling for each main release, like Joomla 3, then Joomla 4 and so on. This may cause JCB to become so large that it will be hard to manage, JCB was build with this as the way forward. So it will naturally scale this way.

You will see JCB is removing all repeatable fields from its back-end, this is because it has been [deprecated](https://docs.joomla.org/Repeatable_form_field_type). ## I do not have the time to always be on top of the latest changes in the Joomla API, if you notice a change that will effect JCB, please open an issue on Github to give me and other a heads-up. Lets work together so the JCB will function like a ship for **us all** over the troubled waters of Joomla's community driven development. ## Objective is that JCB will always compile your component for the latest stable release of Joomla . I am open for suggestions here, but it seems most doable to just keep adapting the compiler to work in the latest release of Joomla. So if you want to compile for earlier versions, you simply install and earlier JCB. The other option is to allow compiling for each main release, like Joomla 3, then Joomla 4 and so on. This may cause JCB to become so large that it will be hard to manage, JCB was build with this as the way forward. So it will naturally scale this way.
mwweb commented 2017-09-26 17:14:13 +00:00 (Migrated from github.com)
Author
Owner

I keep my eyes open, as I can, for any changes in joomla.

As far as consoling for each main release, that could be a tough on. As you said it could make JCB very large in size.

And when joomla moves to a new major release, let's say from 3 to 4, version will be the next official version, but 3 is supported for 2 years.

In some ways I think that it would be nice to be able to compile for 2 different main versions, but on the other hand it could end up being problematic. A new feature or field type could be introduced for joomla 4, as an example, that isn't supported in version. So if you're building your component and it has this new field, it would fail on joomla since it's a joomla 4 field.

I let others provide input as well, but I think allowing compiling of multiple major versions could end up causing issues, incompatibility problem, and just overall a major headache.

I keep my eyes open, as I can, for any changes in joomla. As far as consoling for each main release, that could be a tough on. As you said it could make JCB very large in size. And when joomla moves to a new major release, let's say from 3 to 4, version will be the next official version, but 3 is supported for 2 years. In some ways I think that it would be nice to be able to compile for 2 different main versions, but on the other hand it could end up being problematic. A new feature or field type could be introduced for joomla 4, as an example, that isn't supported in version. So if you're building your component and it has this new field, it would fail on joomla since it's a joomla 4 field. I let others provide input as well, but I think allowing compiling of multiple major versions could end up causing issues, incompatibility problem, and just overall a major headache.
sepehr09 commented 2017-09-27 21:03:18 +00:00 (Migrated from github.com)
Author
Owner

Any help I can do will not hesitate

best regards

Any help I can do will not hesitate best regards
mwweb commented 2017-09-29 18:42:51 +00:00 (Migrated from github.com)
Author
Owner

Many of the JRequest classes have been depreciated. Such as JRequest::getInt

https://api.joomla.org/cms-3/classes/JRequest.html

Many of the JRequest classes have been depreciated. Such as JRequest::getInt https://api.joomla.org/cms-3/classes/JRequest.html
mwweb commented 2017-10-10 03:04:37 +00:00 (Migrated from github.com)
Author
Owner

The use of JError in the compiler needs to be changed before Joomla! 4.

Replacing something like:

JError::raiseError(500, implode('
', $errors));

With JFactory::getApplication()->enqueueMessage();

https://api.joomla.org/cms-3/classes/JError.html

The use of JError in the compiler needs to be changed before Joomla! 4. Replacing something like: JError::raiseError(500, implode(' ', $errors)); With JFactory::getApplication()->enqueueMessage(); https://api.joomla.org/cms-3/classes/JError.html
mwweb commented 2017-11-18 07:22:12 +00:00 (Migrated from github.com)
Author
Owner

I wanted to share that Joomla! officially released Joomla 4 alpha 1 today, which has been a long time coming. Alpha, of course, is still a long ways from stable, but is a step closer.

https://www.joomla.org/announcements/release-news/5718-joomla-4-0-alpha-1-release.html

I wanted to share that Joomla! officially released Joomla 4 alpha 1 today, which has been a long time coming. Alpha, of course, is still a long ways from stable, but is a step closer. https://www.joomla.org/announcements/release-news/5718-joomla-4-0-alpha-1-release.html
stutteringp0et commented 2017-11-24 08:54:22 +00:00 (Migrated from github.com)
Author
Owner

I'm in.

I'm in.
mwweb commented 2017-11-24 09:19:49 +00:00 (Migrated from github.com)
Author
Owner

Good to hear. Llewellyn has been doing a lot of changes lately, as can be seen with the new snippet area. But i know the Joomla dev team are doing tons of changes for v4. I've never successfully gotten v4 alpha to install on my hosting server, and my localhost i haven't upgraded yet.

Any major depreciated code thet you know of would be of great help. I know that Llewellyn has a project open for changing the routing system, which will be a requirement.

Good to hear. Llewellyn has been doing a lot of changes lately, as can be seen with the new snippet area. But i know the Joomla dev team are doing tons of changes for v4. I've never successfully gotten v4 alpha to install on my hosting server, and my localhost i haven't upgraded yet. Any major depreciated code thet you know of would be of great help. I know that Llewellyn has a project open for changing the routing system, which will be a requirement.
stutteringp0et commented 2017-11-24 17:43:21 +00:00 (Migrated from github.com)
Author
Owner

I haven't played around too much with it, but I have installed the alpha release. There are some new plugin types, but I have yet to build a plugin that installs correctly - the plugin xml file is missing when the install is done. Either there's something wrong with the extension installer, or they've changed something that I'm not seeing.

I'll look over the announcements to see if there's anything that stands out.

I haven't played around too much with it, but I have installed the alpha release. There are some new plugin types, but I have yet to build a plugin that installs correctly - the plugin xml file is missing when the install is done. Either there's something wrong with the extension installer, or they've changed something that I'm not seeing. I'll look over the announcements to see if there's anything that stands out.
stutteringp0et commented 2017-11-24 18:39:27 +00:00 (Migrated from github.com)
Author
Owner

According to the J4 announcement, all J3.x deprecated functions will be removed in J4. Just a quick search through vanilla 3.8.2 I find 510 files with deprecated functions. Searching for "\s*\s@deprecated" (which should be found on each deprecated function) - I'm coming up with 1045 deprecated functions in the core.

Certainly, all of these aren't being used in JCB - but I think a good starting place would be to catalog all of these functions and find if/where they're used in JCB.

According to the J4 announcement, all J3.x deprecated functions will be removed in J4. Just a quick search through vanilla 3.8.2 I find 510 files with deprecated functions. Searching for "\s\*\s\@deprecated" (which should be found on each deprecated function) - I'm coming up with 1045 deprecated functions in the core. Certainly, all of these aren't being used in JCB - but I think a good starting place would be to catalog all of these functions and find if/where they're used in JCB.
stutteringp0et commented 2017-11-24 18:44:57 +00:00 (Migrated from github.com)
Author
Owner

This is something else on my list of things to read up on:

https://docs.joomla.org/Potential_backward_compatibility_issues_in_Joomla_4

I've got 30something extensions to prepare for J4

This is something else on my list of things to read up on: https://docs.joomla.org/Potential_backward_compatibility_issues_in_Joomla_4 I've got 30something extensions to prepare for J4
Author
Owner

I think the most major issue we will face will be the router, for the most part I can see only a few other things that may need some tweaking.

I am thinking to start a branch that just prep the compiler for the new Joomla 4.x components. Yet I have not had time to really install Joomla 4 and start tinkering with it. So if any of you can install JCB on Joomla 4 and tell us what broke, that will be a start. Also installing your JCB build components on v4 and giving some feed back will help.

I have been removing stuff as I come across them. But it seems some things are completely changing and would require more work.

I see PHP 7 only is also part of the change... that is going to push the market very hard, and leave many behind. So I think we can do this and stay ahead.

@stutteringp0et those 30+ extensions are they all in JCB or just some of them.

Well my hope is that from the time we have a stable Joomla 4.x JCB v3 should already be able to compile for it, and run on it. That will be ideal 👍

I think the most major issue we will face will be the router, for the most part I can see only a few other things that may need some tweaking. I am thinking to start a branch that just prep the compiler for the new Joomla 4.x components. Yet I have not had time to really install Joomla 4 and start tinkering with it. So if any of you can install JCB on Joomla 4 and tell us what broke, that will be a start. Also installing your JCB build components on v4 and giving some feed back will help. I have been removing stuff as I come across them. But it seems some things are completely changing and would require more work. I see PHP 7 only is also part of the change... that is going to push the market very hard, and leave many behind. So I think we can do this and stay ahead. @stutteringp0et those 30+ extensions are they all in JCB or just some of them. Well my hope is that from the time we have a stable Joomla 4.x JCB v3 should already be able to compile for it, and run on it. That will be ideal :+1:
stutteringp0et commented 2017-11-25 02:09:24 +00:00 (Migrated from github.com)
Author
Owner

None are in JCB. I have a client who requires rapid project cycles, and JCB has really helped me to keep up with their needs.

I'll be re-releasing 3 or 4 of my extensions re-written in JCB.

None are in JCB. I have a client who requires rapid project cycles, and JCB has really helped me to keep up with their needs. I'll be re-releasing 3 or 4 of my extensions re-written in JCB.
stutteringp0et commented 2017-11-25 02:17:23 +00:00 (Migrated from github.com)
Author
Owner

J4 + JCB install aborts with an SQL error - but that might be because this is an alpha release. There are a lot of things broken. I tried looking at contact fields and everything broke...I had to re-load /administrator because the error killed all of the javascript nav items on the page.

I'm looking closely at the banners component.

screenshot from 2017-11-24 20-13-48

J4 + JCB install aborts with an SQL error - but that might be because this is an alpha release. There are a lot of things broken. I tried looking at contact fields and everything broke...I had to re-load /administrator because the error killed all of the javascript nav items on the page. I'm looking closely at the banners component. ![screenshot from 2017-11-24 20-13-48](https://user-images.githubusercontent.com/310899/33226473-201baa74-d154-11e7-8d52-0477eebb7b85.png)
stutteringp0et commented 2017-11-25 02:29:38 +00:00 (Migrated from github.com)
Author
Owner

Looking it up, that error was due to my mariadb version. MariaDB 10.2.1 and up allow text column default values.

Looking it up, that error was due to my mariadb version. MariaDB 10.2.1 and up allow text column default values.
Author
Owner

Well there you go... lol still much todo, what is the planned release date for a stable Joomla4. Did they already set a date?

Anyway I am sure when the time comes we will cross this bridge. I personally think even once the stable release is out it will take a few months for every one to get the courage to move up. I also think many will not move for the first 6-8 months. Usually these major upgrades are painful and slow.

But to get JCB to work should not be that hard, lets say at most a months work in worse case. I just know that these new releases are always a nightmare, I really hope they do better this time around.

Well there you go... lol still much todo, what is the planned release date for a stable Joomla4. Did they already set a date? Anyway I am sure when the time comes we will cross this bridge. I personally think even once the stable release is out it will take a few months for every one to get the courage to move up. I also think many will not move for the first 6-8 months. Usually these major upgrades are painful and slow. But to get JCB to work should not be that hard, lets say at most a months work in worse case. I just know that these new releases are always a nightmare, I really hope they do better this time around.
stutteringp0et commented 2017-11-25 02:35:43 +00:00 (Migrated from github.com)
Author
Owner

Now on MariaDB 10.2.10 - I'm getting this error:
Warning

JInstaller: :Install: Error SQL Field 'addcontributors' doesn't have a default value
JLIB_INSTALLER_ABORT_INSTALL_ABORTED

Maria is a picky broad!

Now on MariaDB 10.2.10 - I'm getting this error: Warning JInstaller: :Install: Error SQL Field 'addcontributors' doesn't have a default value JLIB_INSTALLER_ABORT_INSTALL_ABORTED Maria is a picky broad!
stutteringp0et commented 2017-11-25 02:36:53 +00:00 (Migrated from github.com)
Author
Owner

The only thing I've seen about J4 release date is "someday" - I seem to remember the 3.x series taking about a year from alpha to release

The only thing I've seen about J4 release date is "someday" - I seem to remember the 3.x series taking about a year from alpha to release
Author
Owner

We should try MySQL... I don't think the install tables are MariaDB ready. But yes it could take long... but then again they have been taking small steps towards this.

I remember some saying they are planning to insure that components that run on 3.8 will also run on 4.0 but we will see. It clearly is not there yet.

We should try MySQL... I don't think the install tables are MariaDB ready. But yes it could take long... but then again they have been taking small steps towards this. I remember some saying they are planning to insure that components that run on 3.8 will also run on 4.0 but we will see. It clearly is not there yet.
mwweb commented 2017-11-25 04:40:23 +00:00 (Migrated from github.com)
Author
Owner

I remember seeing somewhere ghost they are pushing for a summer 2018 release. I saw that they have released alpha 2 already.

I remember seeing somewhere ghost they are pushing for a summer 2018 release. I saw that they have released alpha 2 already.
mwweb commented 2017-11-25 04:42:38 +00:00 (Migrated from github.com)
Author
Owner

Here's a page of potential backward compatibility issues with J!4: https://docs.joomla.org/Potential_backward_compatibility_issues_in_Joomla_4

Here's a page of potential backward compatibility issues with J!4: https://docs.joomla.org/Potential_backward_compatibility_issues_in_Joomla_4
stutteringp0et commented 2017-11-25 06:51:51 +00:00 (Migrated from github.com)
Author
Owner

I switched to a server still running MySQL and got the same types of errors. Turns out, in the MySQL 5.7 docs, BLOB, TEXT, GEOMETRY or JSON columns cannot have default values.

https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html

I switched to a server still running MySQL and got the same types of errors. Turns out, in the MySQL 5.7 docs, BLOB, TEXT, GEOMETRY or JSON columns cannot have default values. https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html
mwweb commented 2018-01-12 22:02:09 +00:00 (Migrated from github.com)
Author
Owner

In a test on J!4 Alpha 2 received the following error:

Warning
JInstaller: :Install: Error SQL BLOB/TEXT column 'params' can't have a default value
JLIB_INSTALLER_ABORT_INSTALL_ABORTED

In a test on J!4 Alpha 2 received the following error: Warning JInstaller: :Install: Error SQL BLOB/TEXT column 'params' can't have a default value JLIB_INSTALLER_ABORT_INSTALL_ABORTED
Author
Owner

This JAB-17 Prepare your extension for Joomla 4 seems very helpful, but also proves that we may need to make major improvements to JCB to target J4 more effectively. So I am planning a new branch for the J4 implementation.

This [JAB-17 Prepare your extension for Joomla 4](https://www.youtube.com/watch?v=4FKSrAVcDqU) seems very helpful, but also proves that we may need to make major improvements to JCB to target J4 more effectively. So I am planning a new branch for the J4 implementation.
mwweb commented 2018-04-16 01:05:27 +00:00 (Migrated from github.com)
Author
Owner

I have a Joomla 4, alpha 2 install that i can run testing on when you get to the point that you need testing.

I have a Joomla 4, alpha 2 install that i can run testing on when you get to the point that you need testing.
mwweb commented 2018-05-30 20:07:21 +00:00 (Migrated from github.com)
Author
Owner

This isn't, necessarily, related ONLY to J!4, but will be part of Joomla! 3.9, moving forward.

According to Joomla!, they have been adding a new privacy tool suite to comply with GDPR requirements. In this the tool suite will "Provide an API for extension developers so they can report the data they collect and this info can be displayed in the new com_privacy extension", "Gain the consent of the registered users (form plugin), track their consent, log their activities, and take care about the consent retention time", and more.

I'm just "throwing that out", in the event you aren't aware, and want to add anything to the JCB Core.

This isn't, necessarily, related ONLY to J!4, but will be part of Joomla! 3.9, moving forward. According to Joomla!, they have been adding a new privacy tool suite to comply with GDPR requirements. In this the tool suite will "Provide an API for extension developers so they can report the data they collect and this info can be displayed in the new com_privacy extension", "Gain the consent of the registered users (form plugin), track their consent, log their activities, and take care about the consent retention time", and more. I'm just "throwing that out", in the event you aren't aware, and want to add anything to the JCB Core.
mwweb commented 2019-04-13 22:46:53 +00:00 (Migrated from github.com)
Author
Owner

This might be helpful on what is going to be needed for Joomla 4

https://joomla.digital-peak.com/images/blog/JWC17_Prepare_you_extension_for_Joomla_4.pdf

This might be helpful on what is going to be needed for Joomla 4 [https://joomla.digital-peak.com/images/blog/JWC17_Prepare_you_extension_for_Joomla_4.pdf](https://joomla.digital-peak.com/images/blog/JWC17_Prepare_you_extension_for_Joomla_4.pdf)
Ninja-007 commented 2019-07-21 06:41:20 +00:00 (Migrated from github.com)
Author
Owner

Thanks for provding an interesting extension.
Did you make release plan for J4 support? May be you can have two separate releases like for J3 and J4.

Thanks for provding an interesting extension. Did you make release plan for J4 support? May be you can have two separate releases like for J3 and J4.
Ninja-007 commented 2019-07-21 07:18:15 +00:00 (Migrated from github.com)
Author
Owner
https://github.com/vdm-io/Joomla-Component-Builder/projects/4
Author
Owner

@Ninja-007 I am working on this, but we are not yet ready to push anything out. Soon as that happens this issue will also get bumped 👍

@Ninja-007 I am working on this, but we are not yet ready to push anything out. Soon as that happens this issue will also get bumped :+1:
ergotone commented 2020-07-16 05:19:04 +00:00 (Migrated from github.com)
Author
Owner

Now that J4 beta 2 is out, things look to be firming up, and I'm going to be plunging into J4 Development this autumn. Once I get up to speed, will be following this project and hope to be able to help out

Now that J4 beta 2 is out, things look to be firming up, and I'm going to be plunging into J4 Development this autumn. Once I get up to speed, will be following this project and hope to be able to help out

In a test on J!4 Beta 3 received the following error on installation:

An error has occurred.
500 behavior::modal not found.
Screenshot from 2020-08-18 17-37-34

In a test on **J!4 Beta 3** received the following error on installation: An error has occurred. 500 behavior::modal not found. ![Screenshot from 2020-08-18 17-37-34](https://user-images.githubusercontent.com/38046346/90534672-50700600-e17a-11ea-801f-c0e1aa94467e.png)
stutteringp0et commented 2020-09-10 15:47:40 +00:00 (Migrated from github.com)
Author
Owner

@ohrionmartin it looks like J4 uses bootstrap::renderModal for that task...

@ohrionmartin it looks like J4 uses bootstrap::renderModal for that task...

Get JCB's Demo Component to work in J4! using the legacy approach

Admin Area

Install JCB's Demo component on a J3.10! site, populate it with some demo data, 
and then migrate the J3.10! site to J4! 

Comment out the Submenu from admin area: admin/com_demo/views/looks/view.html.php (line 35-39)

           if ($this->getLayout() !== 'modal')
		{
			// Include helper submenu
			DemoHelper::addSubmenu('looks');
		}

Comment out: JHtml::_('behavior.tabstate');
from admin/demo.php
Displays the list of records on j4!
No breaking changes noticed on j3.10

Comment out: JHtml::_('behavior.tooltip'); 
from admin/views/demo/tmpl/default.php && admin/views/look/tmpl/edit.php
No breaking changes noticed on j3.10


Comment out: JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_demo.look'));
from admin/tables/look.php
Ability to view the list of records
No breaking changes noticed on j3.10!


Change JHtml::_('behavior.formvalidation'); to JHtml::_('behavior.formvalidator'); 
in admin/views/look/tmpl/edit.php
When you click on a single record, it brings up a non stop loading window/spinner
No breaking changes noticed on j3.10!

Comment out the loader/spinner
from admin/views/look/tmpl/edit.php

<script type="text/javascript">
	// waiting spinner
	var outerDiv = jQuery('body');
	jQuery('<div id="loading"></div>')
		.css("background", "rgba(255, 255, 255, .8) url('components/com_demo/assets/images/import.gif') 50% 15% no-repeat")
		.css("top", outerDiv.position().top - jQuery(window).scrollTop())
		.css("left", outerDiv.position().left - jQuery(window).scrollLeft())
		.css("width", outerDiv.width())
		.css("height", outerDiv.height())
		.css("position", "fixed")
		.css("opacity", "0.80")
		.css("-ms-filter", "progid:DXImageTransform.Microsoft.Alpha(Opacity = 80)")
		.css("filter", "alpha(opacity = 80)")
		.css("display", "none")
		.appendTo(outerDiv);
	jQuery('#loading').show();
	// when page is ready remove and show
	jQuery(window).load(function() {
		jQuery('#demo_loader').fadeIn('fast');
		jQuery('#loading').hide();
	});
</script>
<div id="demo_loader" style="display: none;">

Able to enter the edit view of a record and modify data, but unable to perform any of the Save operations

Getting the following error when trying to perform any of the Save operations on J4!:

An error has occurred.
0 Class JApplication not found

Resolution:

  • Change $this->alias = JApplication::stringURLSafe($this->alias); to $this->alias = JApplicationHelper::stringURLSafe($this->alias); in admin/tables/look.php L335 Note: (Breaks version history in J3.10! & Does not keep version history in J4!)
  • Change the params column in the demo_look table to accept null values in order to be able to create and Save
    new records

Getting the following error when trying to perform a Batch operation on J4!:

An error has occurred.
0 Call to undefined method DemoTableLook::getObserverOfClass()

Some of the observed Component folder structure changes in the admin area

  • No assets, layout, sql folders found in admin area of com_content as opposed to com_demo
  • No script.php and index.html files found in admin area com_content as opposed to com_demo
  • No index.html found in admin area of com_content/views
  • No submitbutton.js found in admin/com_content/views/single_view

Site Area

Comment out: JHtml::_('behavior.tabstate'); 
from site/demo.php
Able to displays the list of records on j4 frontend!
Unable to open / access the edit view

Comment out (from com_demo/views/look/tmpl/edit.php):

JHtml::_('behavior.tooltip');
JHtml::_('behavior.tabstate');
JHtml::_('behavior.calendar');
JHtml::_('behavior.formvalidation'); -> JHtml::_('behavior.formvalidator'); // replace

Modify JEventDispatcher from: com_demo/models/looking.php
// Load the JEvent Dispatcher
JPluginHelperimportPlugin('content');
$this->_dispatcher = JEventDispatchergetInstance();

to

// Load the JEvent Dispatcher
JPluginHelper::importPlugin('content');
$this->_dispatcher = JFactory::getApplication();

Add the following code (re-write -> J4! implementation) to com_demo/router.php:
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Component\Router\RouterView;
use Joomla\CMS\Component\Router\RouterViewConfiguration;
use Joomla\CMS\Component\Router\Rules\MenuRules;
use Joomla\CMS\Component\Router\Rules\StandardRules;
use Joomla\CMS\Component\Router\Rules\NomenuRules;
use Joomla\CMS\Factory;
use Joomla\CMS\Menu\SiteMenu;

/**
 * Routing class from com_demo
 *
 * @since  3.3
 */
class DemoRouter extends RouterView
{	
    /**
	 * The database driver
	 *
	 * @var    \JDatabaseDriver
	 * @since  1.0
	 */
	protected $db;

	/**
	 * Search Component router constructor
	 *
	 * @param   CMSApplication  $app   The application object
	 * @param   SiteMenu        $menu  The menu object to work with
	 */
	public function __construct($app = null, $menu = null)
	{
		$this->db = Factory::getDbo();

		$looks = new RouterViewConfiguration('looks');
		$this->registerView($looks);

		$look = (new RouterViewConfiguration('look'))
			->setParent($looks)
			->setKey('id');
		$this->registerView($application);

		$looking = (new RouterViewConfiguration('looking'))
			->setParent($look, 'id')
			->setKey('id');

		$this->registerView($looking);

		$export = (new RouterViewConfiguration('export'))
			->setKey('cms_version');
		$this->registerView($export);

		parent::__construct($app, $menu);

		$this->attachRule(new MenuRules($this));
		$this->attachRule(new StandardRules($this));
		$this->attachRule(new NomenuRules($this));
	}

	/**
	 * Method to get the segment(s) for looks
	 *
	 * @param   string  $id     ID of the looks to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 */
	public function getLooksSegment($id, $query)
	{
		return $this->getLookSegment($id, $query);
	}

	/**
	 * Method to get the segment(s) for  looks
	 *
	 * @param   string  $segment  Segment of the contact to retrieve the ID for
	 * @param   array   $query    The request that is parsed right now
	 *
	 * @return  mixed   The id of this item or false
	 */
	public function getLooksId($segment, $query)
	{
		return $this->getLookId($segment, $query);
	}

	/**
	 * Method to get the segment(s) for an application
	 *
	 * @param   string  $id     ID of the application to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 */
	public function getLookSegment($id, $query)
	{
		if (!strpos($id, ':'))
		{
			$dbquery = $this->db->getQuery(true);
			$dbquery->select($this->db->quoteName('alias'))
				->from($this->db->quoteName('#__demo_look'))
				->where('id = ' . $dbquery->q((int) $id));
			$this->db->setQuery($dbquery);

			$id .= ':' . $this->db->loadResult();
		}

		list($void, $segment) = explode(':', $id, 2);

		return array($void => $segment);
	}

	/**
	 * Method to get the segment(s) for an application
	 *
	 * @param   string  $segment  Segment of the application to retrieve the ID for
	 * @param   array   $query    The request that is parsed right now
	 *
	 * @return  mixed   The id of this item or false
	 */
	public function getLookId($segment, $query)
	{
		$query = $this->db->getQuery(true);
		$query->select($this->db->quoteName('id'))
			->from($this->db->quoteName('#__demo_look'))
			->where('alias = ' . $this->db->quote($segment));
		$this->db->setQuery($query);

		return (int) $this->db->loadResult();
	}
        
        	/**
	 * Method to get the segment(s) for a looking
	 *
	 * @param   string  $id     ID of the looking to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 */
	public function getLookingSegment($id, $query)
	{
		if (!strpos($id, ':'))
		{
			$dbquery = $this->db->getQuery(true);
			$dbquery->select($this->db->quoteName('alias'))
				->from($this->db->quoteName('#__demo_look'))
				->where('id = ' . $dbquery->q((int) $id));
			$this->db->setQuery($dbquery);

			$id .= ':' . $this->db->loadResult();
		}

		list($void, $segment) = explode(':', $id, 2);

		return array($void => $segment);
	}

	/**
	 * Method to get the segment(s) for a looking
	 *
	 * @param   string  $segment  Segment of the looking to retrieve the ID for
	 * @param   array   $query    The request that is parsed right now
	 *
	 * @return  mixed   The id of this item or false
	 */
	public function getLookingId($segment, $query)
	{
		$dbQuery = $this->db->getQuery(true);
		$dbQuery->select($this->db->quoteName('id'))
			->from($this->db->quoteName('#__demo_look'))
			->where(
				[
					$this->db->quoteName('alias') . ' = ' . $this->db->quote($segment),
					$this->db->quoteName('id') . ' = ' . (int) $query['id'],
				]
			);;
		$this->db->setQuery($dbQuery);

		return (int) $this->db->loadResult();
	}

    
}
### Get JCB's Demo Component to work in J4! using the legacy approach ## Admin Area ```````````````````````````````````````````` Install JCB's Demo component on a J3.10! site, populate it with some demo data, and then migrate the J3.10! site to J4! ``````````````````````````````````````````````` Comment out the Submenu from admin area: `admin/com_demo/views/looks/view.html.php (line 35-39)` ```php if ($this->getLayout() !== 'modal') { // Include helper submenu DemoHelper::addSubmenu('looks'); } ````````````````````````````````````````````````` Comment out: JHtml::_('behavior.tabstate'); from admin/demo.php Displays the list of records on j4! No breaking changes noticed on j3.10 ```````````````````````````````````````````` Comment out: JHtml::_('behavior.tooltip'); from admin/views/demo/tmpl/default.php && admin/views/look/tmpl/edit.php No breaking changes noticed on j3.10 ````````````````````````````````````````````` Comment out: JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_demo.look')); from admin/tables/look.php Ability to view the list of records No breaking changes noticed on j3.10! ```````````````````````````````````````````````` Change JHtml::_('behavior.formvalidation'); to JHtml::_('behavior.formvalidator'); in admin/views/look/tmpl/edit.php When you click on a single record, it brings up a non stop loading window/spinner No breaking changes noticed on j3.10! `````````````````````````````````````````````````````````` `````````````````````````````````````````````````````````` `````````````````````````````````````````````````````````` Comment out the loader/spinner from admin/views/look/tmpl/edit.php ```javascript <script type="text/javascript"> // waiting spinner var outerDiv = jQuery('body'); jQuery('<div id="loading"></div>') .css("background", "rgba(255, 255, 255, .8) url('components/com_demo/assets/images/import.gif') 50% 15% no-repeat") .css("top", outerDiv.position().top - jQuery(window).scrollTop()) .css("left", outerDiv.position().left - jQuery(window).scrollLeft()) .css("width", outerDiv.width()) .css("height", outerDiv.height()) .css("position", "fixed") .css("opacity", "0.80") .css("-ms-filter", "progid:DXImageTransform.Microsoft.Alpha(Opacity = 80)") .css("filter", "alpha(opacity = 80)") .css("display", "none") .appendTo(outerDiv); jQuery('#loading').show(); // when page is ready remove and show jQuery(window).load(function() { jQuery('#demo_loader').fadeIn('fast'); jQuery('#loading').hide(); }); </script> <div id="demo_loader" style="display: none;"> Able to enter the edit view of a record and modify data, but unable to perform any of the Save operations `````````````````````````````````````````````````````````` `````````````````````````````````````````````````````````` `````````````````````````````````````````````````````````` Getting the following error when trying to perform any of the `Save` operations on J4!: An error has occurred. 0 Class `JApplication` not found **Resolution:** - Change $this->alias = `JApplication`::stringURLSafe($this->alias); to $this->alias = `JApplicationHelper`::stringURLSafe($this->alias); in **admin/tables/look.php** `L335` **Note:** (_Breaks version history in J3.10! & Does not keep version history in J4!_) - Change the params column in the demo_look table to accept null values in order to be able to create and Save new records `````````````````````````````````````````````````````````` `````````````````````````````````````````````````````````` Getting the following error when trying to perform a `Batch` operation on J4!: An error has occurred. 0 Call to undefined method `DemoTableLook::getObserverOfClass()` `````````````````````````````````````````````````````````` `````````````````````````````````````````````````````````` **Some of the observed Component folder structure changes in the admin area** - No assets, layout, sql folders found in admin area of com_content as opposed to com_demo - No script.php and index.html files found in admin area com_content as opposed to com_demo - No index.html found in admin area of com_content/views - No submitbutton.js found in admin/com_content/views/single_view ````````````````````````````````````````````````````````` ````````````````````````````````````````````````````````` ## Site Area `````````````````````````````````````````````````````````` Comment out: JHtml::_('behavior.tabstate'); from site/demo.php Able to displays the list of records on j4 frontend! Unable to open / access the edit view `````````````````````````````````````````````````````````` Comment out (from `com_demo/views/look/tmpl/edit.php`): ```php JHtml::_('behavior.tooltip'); JHtml::_('behavior.tabstate'); JHtml::_('behavior.calendar'); JHtml::_('behavior.formvalidation'); -> JHtml::_('behavior.formvalidator'); // replace `````````````````````````````````````````````````````````` `````````````````````````````````````````````````````````` Modify JEventDispatcher from: com_demo/models/looking.php `````````````````````````````````````````````````````````` ```php // Load the JEvent Dispatcher JPluginHelperimportPlugin('content'); $this->_dispatcher = JEventDispatchergetInstance(); to // Load the JEvent Dispatcher JPluginHelper::importPlugin('content'); $this->_dispatcher = JFactory::getApplication(); `````````````````````````````````````````````````````````` `````````````````````````````````````````````````````````` Add the following code (re-write -> J4! implementation) to com_demo/router.php: `````````````````````````````````````````````````````````` ```php use Joomla\CMS\Application\CMSApplication; use Joomla\CMS\Component\Router\RouterView; use Joomla\CMS\Component\Router\RouterViewConfiguration; use Joomla\CMS\Component\Router\Rules\MenuRules; use Joomla\CMS\Component\Router\Rules\StandardRules; use Joomla\CMS\Component\Router\Rules\NomenuRules; use Joomla\CMS\Factory; use Joomla\CMS\Menu\SiteMenu; /** * Routing class from com_demo * * @since 3.3 */ class DemoRouter extends RouterView { /** * The database driver * * @var \JDatabaseDriver * @since 1.0 */ protected $db; /** * Search Component router constructor * * @param CMSApplication $app The application object * @param SiteMenu $menu The menu object to work with */ public function __construct($app = null, $menu = null) { $this->db = Factory::getDbo(); $looks = new RouterViewConfiguration('looks'); $this->registerView($looks); $look = (new RouterViewConfiguration('look')) ->setParent($looks) ->setKey('id'); $this->registerView($application); $looking = (new RouterViewConfiguration('looking')) ->setParent($look, 'id') ->setKey('id'); $this->registerView($looking); $export = (new RouterViewConfiguration('export')) ->setKey('cms_version'); $this->registerView($export); parent::__construct($app, $menu); $this->attachRule(new MenuRules($this)); $this->attachRule(new StandardRules($this)); $this->attachRule(new NomenuRules($this)); } /** * Method to get the segment(s) for looks * * @param string $id ID of the looks to retrieve the segments for * @param array $query The request that is built right now * * @return array|string The segments of this item */ public function getLooksSegment($id, $query) { return $this->getLookSegment($id, $query); } /** * Method to get the segment(s) for looks * * @param string $segment Segment of the contact to retrieve the ID for * @param array $query The request that is parsed right now * * @return mixed The id of this item or false */ public function getLooksId($segment, $query) { return $this->getLookId($segment, $query); } /** * Method to get the segment(s) for an application * * @param string $id ID of the application to retrieve the segments for * @param array $query The request that is built right now * * @return array|string The segments of this item */ public function getLookSegment($id, $query) { if (!strpos($id, ':')) { $dbquery = $this->db->getQuery(true); $dbquery->select($this->db->quoteName('alias')) ->from($this->db->quoteName('#__demo_look')) ->where('id = ' . $dbquery->q((int) $id)); $this->db->setQuery($dbquery); $id .= ':' . $this->db->loadResult(); } list($void, $segment) = explode(':', $id, 2); return array($void => $segment); } /** * Method to get the segment(s) for an application * * @param string $segment Segment of the application to retrieve the ID for * @param array $query The request that is parsed right now * * @return mixed The id of this item or false */ public function getLookId($segment, $query) { $query = $this->db->getQuery(true); $query->select($this->db->quoteName('id')) ->from($this->db->quoteName('#__demo_look')) ->where('alias = ' . $this->db->quote($segment)); $this->db->setQuery($query); return (int) $this->db->loadResult(); } /** * Method to get the segment(s) for a looking * * @param string $id ID of the looking to retrieve the segments for * @param array $query The request that is built right now * * @return array|string The segments of this item */ public function getLookingSegment($id, $query) { if (!strpos($id, ':')) { $dbquery = $this->db->getQuery(true); $dbquery->select($this->db->quoteName('alias')) ->from($this->db->quoteName('#__demo_look')) ->where('id = ' . $dbquery->q((int) $id)); $this->db->setQuery($dbquery); $id .= ':' . $this->db->loadResult(); } list($void, $segment) = explode(':', $id, 2); return array($void => $segment); } /** * Method to get the segment(s) for a looking * * @param string $segment Segment of the looking to retrieve the ID for * @param array $query The request that is parsed right now * * @return mixed The id of this item or false */ public function getLookingId($segment, $query) { $dbQuery = $this->db->getQuery(true); $dbQuery->select($this->db->quoteName('id')) ->from($this->db->quoteName('#__demo_look')) ->where( [ $this->db->quoteName('alias') . ' = ' . $this->db->quote($segment), $this->db->quoteName('id') . ' = ' . (int) $query['id'], ] );; $this->db->setQuery($dbQuery); return (int) $this->db->loadResult(); } }

Comment out the following lines to make the component install on both J3! & J4! from com_demo/script.php:

<?php
/*----------------------------------------------------------------------------------|  www.vdm.io  |----/
				Vast Development Method 
/-------------------------------------------------------------------------------------------------------/

	@version		2.0.3
	@build			18th October, 2021
	@created		18th October, 2016
	@package		Demo
	@subpackage		script.php
	@author			Llewellyn van der Merwe <https://www.vdm.io/>	
	@copyright		Copyright (C) 2015. All Rights Reserved
	@license		GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html
  ____  _____  _____  __  __  __      __       ___  _____  __  __  ____  _____  _  _  ____  _  _  ____ 
 (_  _)(  _  )(  _  )(  \/  )(  )    /__\     / __)(  _  )(  \/  )(  _ \(  _  )( \( )( ___)( \( )(_  _)
.-_)(   )(_)(  )(_)(  )    (  )(__  /(__)\   ( (__  )(_)(  )    (  )___/ )(_)(  )  (  )__)  )  (   )(  
\____) (_____)(_____)(_/\/\_)(____)(__)(__)   \___)(_____)(_/\/\_)(__)  (_____)(_)\_)(____)(_)\_) (__) 

/------------------------------------------------------------------------------------------------------*/

// No direct access to this file
defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Filesystem\Folder;
use Joomla\CMS\Installer\Adapter\ComponentAdapter;
JHTML::_('bootstrap.renderModal');

/**
 * Script File of Demo Component
 */
class com_demoInstallerScript
{
	/**
	 * Constructor
	 *
	 * @param   JAdapterInstance  $parent  The object responsible for running this script
	 */
	public function __construct(ComponentAdapter $parent) {}

	/**
	 * Called on installation
	 *
	 * @param   ComponentAdapter  $parent  The object responsible for running this script
	 *
	 * @return  boolean  True on success
	 */
	public function install(ComponentAdapter $parent) {}

	/**
	 * Called on uninstallation
	 *
	 * @param   ComponentAdapter  $parent  The object responsible for running this script
	 */
	public function uninstall(ComponentAdapter $parent)
	{
		// Get Application object
		$app = JFactory::getApplication();

		// Get The Database object
		$db = JFactory::getDbo();

		// Create a new query object.
		$query = $db->getQuery(true);
		// Select ids from fields
		$query->select($db->quoteName('id'));
		$query->from($db->quoteName('#__fields'));
		// Where look context is found
		$query->where( $db->quoteName('context') . ' = '. $db->quote('com_demo.look') );
		$db->setQuery($query);
		// Execute query to see if context is found
		$db->execute();
		$look_found = $db->getNumRows();
		// Now check if there were any rows
		if ($look_found)
		{
			// Since there are load the needed  look field ids
			$look_field_ids = $db->loadColumn();
			// Remove look from the field table
			$look_condition = array( $db->quoteName('context') . ' = '. $db->quote('com_demo.look') );
			// Create a new query object.
			$query = $db->getQuery(true);
			$query->delete($db->quoteName('#__fields'));
			$query->where($look_condition);
			$db->setQuery($query);
			// Execute the query to remove look items
			$look_done = $db->execute();
			if ($look_done)
			{
				// If successfully remove look add queued success message.
				$app->enqueueMessage(JText::_('The fields with type (com_demo.look) context was removed from the <b>#__fields</b> table'));
			}
			// Also Remove look field values
			$look_condition = array( $db->quoteName('field_id') . ' IN ('. implode(',', $look_field_ids) .')');
			// Create a new query object.
			$query = $db->getQuery(true);
			$query->delete($db->quoteName('#__fields_values'));
			$query->where($look_condition);
			$db->setQuery($query);
			// Execute the query to remove look field values
			$look_done = $db->execute();
			if ($look_done)
			{
				// If successfully remove look add queued success message.
				$app->enqueueMessage(JText::_('The fields values for look was removed from the <b>#__fields_values</b> table'));
			}
		}

		// Create a new query object.
		$query = $db->getQuery(true);
		// Select ids from field groups
		$query->select($db->quoteName('id'));
		$query->from($db->quoteName('#__fields_groups'));
		// Where look context is found
		$query->where( $db->quoteName('context') . ' = '. $db->quote('com_demo.look') );
		$db->setQuery($query);
		// Execute query to see if context is found
		$db->execute();
		$look_found = $db->getNumRows();
		// Now check if there were any rows
		if ($look_found)
		{
			// Remove look from the field groups table
			$look_condition = array( $db->quoteName('context') . ' = '. $db->quote('com_demo.look') );
			// Create a new query object.
			$query = $db->getQuery(true);
			$query->delete($db->quoteName('#__fields_groups'));
			$query->where($look_condition);
			$db->setQuery($query);
			// Execute the query to remove look items
			$look_done = $db->execute();
			if ($look_done)
			{
				// If successfully remove look add queued success message.
				$app->enqueueMessage(JText::_('The field groups with type (com_demo.look) context was removed from the <b>#__fields_groups</b> table'));
			}
		}

		// Create a new query object.
		$query = $db->getQuery(true);
		// Select id from content type table
		$query->select($db->quoteName('type_id'));
		$query->from($db->quoteName('#__content_types'));
		// Where look alias is found
		$query->where( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') );
		$db->setQuery($query);
		// Execute query to see if alias is found
		$db->execute();
		$look_found = $db->getNumRows();
		// Now check if there were any rows
		if ($look_found)
		{
			// Since there are load the needed  look type ids
			$look_ids = $db->loadColumn();
			// Remove look from the content type table
			$look_condition = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') );
			// Create a new query object.
			$query = $db->getQuery(true);
			$query->delete($db->quoteName('#__content_types'));
			$query->where($look_condition);
			$db->setQuery($query);
			// Execute the query to remove look items
			$look_done = $db->execute();
			if ($look_done)
			{
				// If successfully remove look add queued success message.
				$app->enqueueMessage(JText::_('The (com_demo.look) type alias was removed from the <b>#__content_type</b> table'));
			}

			// Remove look items from the contentitem tag map table
			$look_condition = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') );
			// Create a new query object.
			$query = $db->getQuery(true);
			$query->delete($db->quoteName('#__contentitem_tag_map'));
			$query->where($look_condition);
			$db->setQuery($query);
			// Execute the query to remove look items
			$look_done = $db->execute();
			if ($look_done)
			{
				// If successfully remove look add queued success message.
				$app->enqueueMessage(JText::_('The (com_demo.look) type alias was removed from the <b>#__contentitem_tag_map</b> table'));
			}

			// Remove look items from the ucm content table
			$look_condition = array( $db->quoteName('core_type_alias') . ' = ' . $db->quote('com_demo.look') );
			// Create a new query object.
			$query = $db->getQuery(true);
			$query->delete($db->quoteName('#__ucm_content'));
			$query->where($look_condition);
			$db->setQuery($query);
			// Execute the query to remove look items
			$look_done = $db->execute();
			if ($look_done)
			{
				// If successfully removed look add queued success message.
				$app->enqueueMessage(JText::_('The (com_demo.look) type alias was removed from the <b>#__ucm_content</b> table'));
			}

			// Make sure that all the look items are cleared from DB
			foreach ($look_ids as $look_id)
			{
				// Remove look items from the ucm base table
				$look_condition = array( $db->quoteName('ucm_type_id') . ' = ' . $look_id);
				// Create a new query object.
				$query = $db->getQuery(true);
				$query->delete($db->quoteName('#__ucm_base'));
				$query->where($look_condition);
				$db->setQuery($query);
				// Execute the query to remove look items
				$db->execute();

				// Remove look items from the ucm history table
				$look_condition = array( $db->quoteName('ucm_type_id') . ' = ' . $look_id);
				// Create a new query object.
				$query = $db->getQuery(true);
				$query->delete($db->quoteName('#__ucm_history'));
				$query->where($look_condition);
				$db->setQuery($query);
				// Execute the query to remove look items
				$db->execute();
			}
		}

		// Create a new query object.
		$query = $db->getQuery(true);
		// Select id from content type table
		$query->select($db->quoteName('type_id'));
		$query->from($db->quoteName('#__content_types'));
		// Where Look alias is found
		$query->where( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') );
		$db->setQuery($query);
		// Execute query to see if alias is found
		$db->execute();
		$look_found = $db->getNumRows();
		// Now check if there were any rows
		if ($look_found)
		{
			// Since there are load the needed  look type ids
			$look_ids = $db->loadColumn();
			// Remove Look from the content type table
			$look_condition = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') );
			// Create a new query object.
			$query = $db->getQuery(true);
			$query->delete($db->quoteName('#__content_types'));
			$query->where($look_condition);
			$db->setQuery($query);
			// Execute the query to remove Look items
			$look_done = $db->execute();
			if ($look_done)
			{
				// If successfully remove Look add queued success message.
				$app->enqueueMessage(JText::_('The (com_demo.look) type alias was removed from the <b>#__content_type</b> table'));
			}

			// Remove Look items from the contentitem tag map table
			$look_condition = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') );
			// Create a new query object.
			$query = $db->getQuery(true);
			$query->delete($db->quoteName('#__contentitem_tag_map'));
			$query->where($look_condition);
			$db->setQuery($query);
			// Execute the query to remove Look items
			$look_done = $db->execute();
			if ($look_done)
			{
				// If successfully remove Look add queued success message.
				$app->enqueueMessage(JText::_('The (com_demo.look) type alias was removed from the <b>#__contentitem_tag_map</b> table'));
			}

			// Remove Look items from the ucm content table
			$look_condition = array( $db->quoteName('core_type_alias') . ' = ' . $db->quote('com_demo.look') );
			// Create a new query object.
			$query = $db->getQuery(true);
			$query->delete($db->quoteName('#__ucm_content'));
			$query->where($look_condition);
			$db->setQuery($query);
			// Execute the query to remove Look items
			$look_done = $db->execute();
			if ($look_done)
			{
				// If successfully removed Look add queued success message.
				$app->enqueueMessage(JText::_('The (com_demo.look) type alias was removed from the <b>#__ucm_content</b> table'));
			}

			// Make sure that all the Look items are cleared from DB
			foreach ($look_ids as $look_id)
			{
				// Remove Look items from the ucm base table
				$look_condition = array( $db->quoteName('ucm_type_id') . ' = ' . $look_id);
				// Create a new query object.
				$query = $db->getQuery(true);
				$query->delete($db->quoteName('#__ucm_base'));
				$query->where($look_condition);
				$db->setQuery($query);
				// Execute the query to remove Look items
				$db->execute();

				// Remove Look items from the ucm history table
				$look_condition = array( $db->quoteName('ucm_type_id') . ' = ' . $look_id);
				// Create a new query object.
				$query = $db->getQuery(true);
				$query->delete($db->quoteName('#__ucm_history'));
				$query->where($look_condition);
				$db->setQuery($query);
				// Execute the query to remove Look items
				$db->execute();
			}
		}

		// If All related items was removed queued success message.
		$app->enqueueMessage(JText::_('All related items was removed from the <b>#__ucm_base</b> table'));
		$app->enqueueMessage(JText::_('All related items was removed from the <b>#__ucm_history</b> table'));

		// Remove demo assets from the assets table
		$demo_condition = array( $db->quoteName('name') . ' LIKE ' . $db->quote('com_demo%') );

		// Create a new query object.
		$query = $db->getQuery(true);
		$query->delete($db->quoteName('#__assets'));
		$query->where($demo_condition);
		$db->setQuery($query);
		$look_done = $db->execute();
		if ($look_done)
		{
			// If successfully removed demo add queued success message.
			$app->enqueueMessage(JText::_('All related items was removed from the <b>#__assets</b> table'));
		}

		// Get the biggest rule column in the assets table at this point.
		// $get_rule_length = "SELECT CHAR_LENGTH(`rules`) as rule_size FROM #__assets ORDER BY rule_size DESC LIMIT 1";
		// $db->setQuery($get_rule_length);
		// if ($db->execute())
		// {
		// 	$rule_length = $db->loadResult();
		// 	// Check the size of the rules column
		// 	if ($rule_length < 5120)
		// 	{
		// 		// Revert the assets table rules column back to the default
		// 		$revert_rule = "ALTER TABLE `#__assets` CHANGE `rules` `rules` varchar(5120) NOT NULL COMMENT 'JSON encoded access control.';";
		// 		$db->setQuery($revert_rule);
		// 		$db->execute();
		// 		$app->enqueueMessage(JText::_('Reverted the <b>#__assets</b> table rules column back to its default size of varchar(5120)'));
		// 	}
		// 	else
		// 	{

		// 		$app->enqueueMessage(JText::_('Could not revert the <b>#__assets</b> table rules column back to its default size of varchar(5120), since there is still one or more components that still requires the column to be larger.'));
		// 	}
		// }

		// Set db if not set already.
		if (!isset($db))
		{
			$db = JFactory::getDbo();
		}
		// Set app if not set already.
		if (!isset($app))
		{
			$app = JFactory::getApplication();
		}
		// Remove Demo from the action_logs_extensions table
		$demo_action_logs_extensions = array( $db->quoteName('extension') . ' = ' . $db->quote('com_demo') );
		// Create a new query object.
		$query = $db->getQuery(true);
		$query->delete($db->quoteName('#__action_logs_extensions'));
		$query->where($demo_action_logs_extensions);
		$db->setQuery($query);
		// Execute the query to remove Demo
		$demo_removed_done = $db->execute();
		if ($demo_removed_done)
		{
			// If successfully remove Demo add queued success message.
			$app->enqueueMessage(JText::_('The com_demo extension was removed from the <b>#__action_logs_extensions</b> table'));
		}

		// Set db if not set already.
		if (!isset($db))
		{
			$db = JFactory::getDbo();
		}
		// Set app if not set already.
		if (!isset($app))
		{
			$app = JFactory::getApplication();
		}
		// Remove Demo Look from the action_log_config table
		$look_action_log_config = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') );
		// Create a new query object.
		$query = $db->getQuery(true);
		$query->delete($db->quoteName('#__action_log_config'));
		$query->where($look_action_log_config);
		$db->setQuery($query);
		// Execute the query to remove com_demo.look
		$look_action_log_config_done = $db->execute();
		if ($look_action_log_config_done)
		{
			// If successfully removed Demo Look add queued success message.
			$app->enqueueMessage(JText::_('The com_demo.look type alias was removed from the <b>#__action_log_config</b> table'));
		}
		// little notice as after service, in case of bad experience with component.
		echo '<h2>Did something go wrong? Are you disappointed?</h2>
		<p>Please let me know at <a href="mailto:joomla@vdm.io">joomla@vdm.io</a>.
		<br />We at Vast Development Method are committed to building extensions that performs proficiently! You can help us, really!
		<br />Send me your thoughts on improvements that is needed, trust me, I will be very grateful!
		<br />Visit us at <a href="https://www.vdm.io/" target="_blank">https://www.vdm.io/</a> today!</p>';
	}

	/**
	 * Called on update
	 *
	 * @param   ComponentAdapter  $parent  The object responsible for running this script
	 *
	 * @return  boolean  True on success
	 */
	public function update(ComponentAdapter $parent){}

	/**
	 * Called before any type of action
	 *
	 * @param   string  $type  Which action is happening (install|uninstall|discover_install|update)
	 * @param   ComponentAdapter  $parent  The object responsible for running this script
	 *
	 * @return  boolean  True on success
	 */
	public function preflight($type, ComponentAdapter $parent)
	{
		// get application
		$app = JFactory::getApplication();
		// is redundant or so it seems ...hmmm let me know if it works again
		if ($type === 'uninstall')
		{
			return true;
		}
		// the default for both install and update
		$jversion = new JVersion();
		if (!$jversion->isCompatible('3.8.0'))
		{
			$app->enqueueMessage('Please upgrade to at least Joomla! 3.8.0 before continuing!', 'error');
			return false;
		}
		// do any updates needed
		if ($type === 'update')
		{
		}
		// do any install needed
		if ($type === 'install')
		{
		}
		// check if the PHPExcel stuff is still around
		if (File::exists(JPATH_ADMINISTRATOR . '/components/com_demo/helpers/PHPExcel.php'))
		{
			// We need to remove this old PHPExcel folder
			$this->removeFolder(JPATH_ADMINISTRATOR . '/components/com_demo/helpers/PHPExcel');
			// We need to remove this old PHPExcel file
			File::delete(JPATH_ADMINISTRATOR . '/components/com_demo/helpers/PHPExcel.php');
		}
		return true;
	}

	/**
	 * Called after any type of action
	 *
	 * @param   string  $type  Which action is happening (install|uninstall|discover_install|update)
	 * @param   ComponentAdapter  $parent  The object responsible for running this script
	 *
	 * @return  boolean  True on success
	 */
	public function postflight($type, ComponentAdapter $parent)
	{
		// get application
		$app = JFactory::getApplication();
		// We check if we have dynamic folders to copy
		$this->setDynamicF0ld3rs($app, $parent);
		// set the default component settings
		if ($type === 'install')
		{

			// Get The Database object
			$db = JFactory::getDbo();

			// Create the look content type object.
			// $look = new stdClass();
			// $look->type_title = 'Demo Look';
			// $look->type_alias = 'com_demo.look';
			// $look->table = '{"special": {"dbtable": "#__demo_look","key": "id","type": "Look","prefix": "demoTable","config": "array()"},"common": {"dbtable": "#__ucm_content","key": "ucm_id","type": "Corecontent","prefix": "JTable","config": "array()"}}';
			// $look->field_mappings = '{"common": {"core_content_item_id": "id","core_title": "name","core_state": "published","core_alias": "alias","core_created_time": "created","core_modified_time": "modified","core_body": "null","core_hits": "hits","core_publish_up": "null","core_publish_down": "null","core_access": "access","core_params": "params","core_featured": "null","core_metadata": "metadata","core_language": "null","core_images": "null","core_urls": "null","core_version": "version","core_ordering": "ordering","core_metakey": "metakey","core_metadesc": "metadesc","core_catid": "null","core_xreference": "null","asset_id": "asset_id"},"special": {"name":"name","description":"description","website":"website","image":"image","dateofbirth":"dateofbirth","mobile_phone":"mobile_phone","email":"email","add":"add","alias":"alias"}}';
			// $look->router = 'DemoHelperRoute::getLookRoute';
			// $look->content_history_options = '{"formFile": "administrator/components/com_demo/models/forms/look.xml","hideFields": ["asset_id","checked_out","checked_out_time","version"],"ignoreChanges": ["modified_by","modified","checked_out","checked_out_time","version","hits"],"convertToInt": ["published","ordering","add"],"displayLookup": [{"sourceColumn": "created_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "access","targetTable": "#__viewlevels","targetColumn": "id","displayColumn": "title"},{"sourceColumn": "modified_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"}]}';

			// // Set the object into the content types table.
			// $look_Inserted = $db->insertObject('#__content_types', $look);


			// // Install the global extenstion assets permission.
			// $query = $db->getQuery(true);
			// // Field to update.
			// $fields = array(
			// 	$db->quoteName('rules') . ' = ' . $db->quote('{"site.looks.access":{"1":1}}'),
			// );
			// // Condition.
			// $conditions = array(
			// 	$db->quoteName('name') . ' = ' . $db->quote('com_demo')
			// );
			// $query->update($db->quoteName('#__assets'))->set($fields)->where($conditions);
			// $db->setQuery($query);
			// $allDone = $db->execute();

			// Install the global extension params.
			$query = $db->getQuery(true);
			// Field to update.
			$fields = array(
				$db->quoteName('params') . ' = ' . $db->quote('{"autorName":"Llewellyn van der Merwe","autorEmail":"joomla@vdm.io","check_in":"-1 day","save_history":"1","history_limit":"10","uikit_load":"1","uikit_min":"","uikit_style":""}'),
			);
			// Condition.
			$conditions = array(
				$db->quoteName('element') . ' = ' . $db->quote('com_demo')
			);
			$query->update($db->quoteName('#__extensions'))->set($fields)->where($conditions);
			$db->setQuery($query);
			$allDone = $db->execute();


		// Get Application object
		$app = JFactory::getApplication();
		$app->enqueueMessage('This is a demo component developed in <a href="http://vdm.bz/component-builder" taget="_balnk" title="Joomla Component Builder">JCB</a>! You can build more components like this with JCB, checkout our page on <a href="https://github.com/vdm-io/Joomla-Component-Builder" taget="_balnk" title="Joomla Component Builder">github</a> for more info. The future of <a href="http://vdm.bz/component-builder" taget="_balnk" title="Joomla Component Builder">Joomla Component Development</a> is Here!', 'Info');
			// Get the biggest rule column in the assets table at this point.
			// $get_rule_length = "SELECT CHAR_LENGTH(`rules`) as rule_size FROM #__assets ORDER BY rule_size DESC LIMIT 1";
			// $db->setQuery($get_rule_length);
			// if ($db->execute())
			// {
			// 	$rule_length = $db->loadResult();
			// 	// Check the size of the rules column
			// 	if ($rule_length <= 5600)
			// 	{
			// 		// Fix the assets table rules column size
			// 		$fix_rules_size = "ALTER TABLE `#__assets` CHANGE `rules` `rules` TEXT NOT NULL COMMENT 'JSON encoded access control. Enlarged to TEXT by JCB';";
			// 		$db->setQuery($fix_rules_size);
			// 		$db->execute();
			// 		$app->enqueueMessage(JText::_('The <b>#__assets</b> table rules column was resized to the TEXT datatype for the components possible large permission rules.'));
			// 	}
			// }
			// echo '<a target="_blank" href="https://www.vdm.io/" title="Demo">
			// 	<img src="components/com_demo/assets/images/vdm-component.jpg"/>
			// 	</a>';

			// // Set db if not set already.
			// if (!isset($db))
			// {
			// 	$db = JFactory::getDbo();
			// }
			// // Create the demo action logs extensions object.
			// $demo_action_logs_extensions = new stdClass();
			// $demo_action_logs_extensions->extension = 'com_demo';

			// Set the object into the action logs extensions table.
			// $demo_action_logs_extensions_Inserted = $db->insertObject('#__action_logs_extensions', $demo_action_logs_extensions);

			// // Set db if not set already.
			// if (!isset($db))
			// {
			// 	$db = JFactory::getDbo();
			// }
			// // Create the look action log config object.
			// $look_action_log_config = new stdClass();
			// $look_action_log_config->type_title = 'LOOK';
			// $look_action_log_config->type_alias = 'com_demo.look';
			// $look_action_log_config->id_holder = 'id';
			// $look_action_log_config->title_holder = 'name';
			// $look_action_log_config->table_name = '#__demo_look';
			// $look_action_log_config->text_prefix = 'COM_DEMO';

			// // Set the object into the action log config table.
			// $look_Inserted = $db->insertObject('#__action_log_config', $look_action_log_config);
		}
		// do any updates needed
		if ($type === 'update')
		{

			// Get The Database object
			// $db = JFactory::getDbo();

			// // Create the look content type object.
			// $look = new stdClass();
			// $look->type_title = 'Demo Look';
			// $look->type_alias = 'com_demo.look';
			// $look->table = '{"special": {"dbtable": "#__demo_look","key": "id","type": "Look","prefix": "demoTable","config": "array()"},"common": {"dbtable": "#__ucm_content","key": "ucm_id","type": "Corecontent","prefix": "JTable","config": "array()"}}';
			// $look->field_mappings = '{"common": {"core_content_item_id": "id","core_title": "name","core_state": "published","core_alias": "alias","core_created_time": "created","core_modified_time": "modified","core_body": "null","core_hits": "hits","core_publish_up": "null","core_publish_down": "null","core_access": "access","core_params": "params","core_featured": "null","core_metadata": "metadata","core_language": "null","core_images": "null","core_urls": "null","core_version": "version","core_ordering": "ordering","core_metakey": "metakey","core_metadesc": "metadesc","core_catid": "null","core_xreference": "null","asset_id": "asset_id"},"special": {"name":"name","description":"description","website":"website","image":"image","dateofbirth":"dateofbirth","mobile_phone":"mobile_phone","email":"email","add":"add","alias":"alias"}}';
			// $look->router = 'DemoHelperRoute::getLookRoute';
			// $look->content_history_options = '{"formFile": "administrator/components/com_demo/models/forms/look.xml","hideFields": ["asset_id","checked_out","checked_out_time","version"],"ignoreChanges": ["modified_by","modified","checked_out","checked_out_time","version","hits"],"convertToInt": ["published","ordering","add"],"displayLookup": [{"sourceColumn": "created_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "access","targetTable": "#__viewlevels","targetColumn": "id","displayColumn": "title"},{"sourceColumn": "modified_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"}]}';

			// // Check if look type is already in content_type DB.
			// $look_id = null;
			// $query = $db->getQuery(true);
			// $query->select($db->quoteName(array('type_id')));
			// $query->from($db->quoteName('#__content_types'));
			// $query->where($db->quoteName('type_alias') . ' LIKE '. $db->quote($look->type_alias));
			// $db->setQuery($query);
			// $db->execute();

			// // Set the object into the content types table.
			// if ($db->getNumRows())
			// {
			// 	$look->type_id = $db->loadResult();
			// 	$look_Updated = $db->updateObject('#__content_types', $look, 'type_id');
			// }
			// else
			// {
			// 	$look_Inserted = $db->insertObject('#__content_types', $look);
			// }


			echo '<a target="_blank" href="https://www.vdm.io/" title="Demo">
				<img src="components/com_demo/assets/images/vdm-component.jpg"/>
				</a>
				<h3>Upgrade to Version 2.0.3 Was Successful! Let us know if anything is not working as expected.</h3>';

			// Set db if not set already.
			// if (!isset($db))
			// {
			// 	$db = JFactory::getDbo();
			// }
			// // Create the demo action logs extensions object.
			// $demo_action_logs_extensions = new stdClass();
			// $demo_action_logs_extensions->extension = 'com_demo';

			// // Check if demo action log extension is already in action logs extensions DB.
			// $query = $db->getQuery(true);
			// $query->select($db->quoteName(array('id')));
			// $query->from($db->quoteName('#__action_logs_extensions'));
			// $query->where($db->quoteName('extension') . ' LIKE '. $db->quote($demo_action_logs_extensions->extension));
			// $db->setQuery($query);
			// $db->execute();

			// // Set the object into the action logs extensions table if not found.
			// if (!$db->getNumRows())
			// {
			// 	$demo_action_logs_extensions_Inserted = $db->insertObject('#__action_logs_extensions', $demo_action_logs_extensions);
			// }

			// // Set db if not set already.
			// if (!isset($db))
			// {
			// 	$db = JFactory::getDbo();
			// }
			// // Create the look action log config object.
			// $look_action_log_config = new stdClass();
			// $look_action_log_config->id = null;
			// $look_action_log_config->type_title = 'LOOK';
			// $look_action_log_config->type_alias = 'com_demo.look';
			// $look_action_log_config->id_holder = 'id';
			// $look_action_log_config->title_holder = 'name';
			// $look_action_log_config->table_name = '#__demo_look';
			// $look_action_log_config->text_prefix = 'COM_DEMO';

			// // Check if look action log config is already in action_log_config DB.
			// $query = $db->getQuery(true);
			// $query->select($db->quoteName(array('id')));
			// $query->from($db->quoteName('#__action_log_config'));
			// $query->where($db->quoteName('type_alias') . ' LIKE '. $db->quote($look_action_log_config->type_alias));
			// $db->setQuery($query);
			// $db->execute();

			// // Set the object into the content types table.
			// if ($db->getNumRows())
			// {
			// 	$look_action_log_config->id = $db->loadResult();
			// 	$look_action_log_config_Updated = $db->updateObject('#__action_log_config', $look_action_log_config, 'id');
			// }
			// else
			// {
			// 	$look_action_log_config_Inserted = $db->insertObject('#__action_log_config', $look_action_log_config);
			// }
		}
		return true;
	}

	/**
	 * Remove folders with files
	 * 
	 * @param   string   $dir     The path to folder to remove
	 * @param   boolean  $ignore  The folders and files to ignore and not remove
	 *
	 * @return  boolean   True in all is removed
	 * 
	 */
	protected function removeFolder($dir, $ignore = false)
	{
		if (Folder::exists($dir))
		{
			$it = new RecursiveDirectoryIterator($dir);
			$it = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
			// remove ending /
			$dir = rtrim($dir, '/');
			// now loop the files & folders
			foreach ($it as $file)
			{
				if ('.' === $file->getBasename() || '..' ===  $file->getBasename()) continue;
				// set file dir
				$file_dir = $file->getPathname();
				// check if this is a dir or a file
				if ($file->isDir())
				{
					$keeper = false;
					if ($this->checkArray($ignore))
					{
						foreach ($ignore as $keep)
						{
							if (strpos($file_dir, $dir.'/'.$keep) !== false)
							{
								$keeper = true;
							}
						}
					}
					if ($keeper)
					{
						continue;
					}
					Folder::delete($file_dir);
				}
				else
				{
					$keeper = false;
					if ($this->checkArray($ignore))
					{
						foreach ($ignore as $keep)
						{
							if (strpos($file_dir, $dir.'/'.$keep) !== false)
							{
								$keeper = true;
							}
						}
					}
					if ($keeper)
					{
						continue;
					}
					File::delete($file_dir);
				}
			}
			// delete the root folder if not ignore found
			if (!$this->checkArray($ignore))
			{
				return Folder::delete($dir);
			}
			return true;
		}
		return false;
	}

	/**
	 * Check if have an array with a length
	 *
	 * @input	array   The array to check
	 *
	 * @returns bool/int  number of items in array on success
	 */
	protected function checkArray($array, $removeEmptyString = false)
	{
		if (isset($array) && is_array($array) && ($nr = count((array)$array)) > 0)
		{
			// also make sure the empty strings are removed
			if ($removeEmptyString)
			{
				foreach ($array as $key => $string)
				{
					if (empty($string))
					{
						unset($array[$key]);
					}
				}
				return $this->checkArray($array, false);
			}
			return $nr;
		}
		return false;
	}

	/**
	 * Method to set/copy dynamic folders into place (use with caution)
	 *
	 * @return void
	 */
	protected function setDynamicF0ld3rs($app, $parent)
	{
		// get the instalation path
		$installer = $parent->getParent();
		$installPath = $installer->getPath('source');
		// get all the folders
		$folders = Folder::folders($installPath);
		// check if we have folders we may want to copy
		$doNotCopy = array('media','admin','site'); // Joomla already deals with these
		if (count((array) $folders) > 1)
		{
			foreach ($folders as $folder)
			{
				// Only copy if not a standard folders
				if (!in_array($folder, $doNotCopy))
				{
					// set the source path
					$src = $installPath.'/'.$folder;
					// set the destination path
					$dest = JPATH_ROOT.'/'.$folder;
					// now try to copy the folder
					if (!Folder::copy($src, $dest, '', true))
					{
						$app->enqueueMessage('Could not copy '.$folder.' folder into place, please make sure destination is writable!', 'error');
					}
				}
			}
		}
	}
}
Comment out the following lines to make the component install on both J3! & J4! from `com_demo/script.php`: `````````````````````````````````````````````````````````` `````````````````````````````````````````````````````````` ```php <?php /*----------------------------------------------------------------------------------| www.vdm.io |----/ Vast Development Method /-------------------------------------------------------------------------------------------------------/ @version 2.0.3 @build 18th October, 2021 @created 18th October, 2016 @package Demo @subpackage script.php @author Llewellyn van der Merwe <https://www.vdm.io/> @copyright Copyright (C) 2015. All Rights Reserved @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html ____ _____ _____ __ __ __ __ ___ _____ __ __ ____ _____ _ _ ____ _ _ ____ (_ _)( _ )( _ )( \/ )( ) /__\ / __)( _ )( \/ )( _ \( _ )( \( )( ___)( \( )(_ _) .-_)( )(_)( )(_)( ) ( )(__ /(__)\ ( (__ )(_)( ) ( )___/ )(_)( ) ( )__) ) ( )( \____) (_____)(_____)(_/\/\_)(____)(__)(__) \___)(_____)(_/\/\_)(__) (_____)(_)\_)(____)(_)\_) (__) /------------------------------------------------------------------------------------------------------*/ // No direct access to this file defined('_JEXEC') or die('Restricted access'); use Joomla\CMS\Filesystem\File; use Joomla\CMS\Filesystem\Folder; use Joomla\CMS\Installer\Adapter\ComponentAdapter; JHTML::_('bootstrap.renderModal'); /** * Script File of Demo Component */ class com_demoInstallerScript { /** * Constructor * * @param JAdapterInstance $parent The object responsible for running this script */ public function __construct(ComponentAdapter $parent) {} /** * Called on installation * * @param ComponentAdapter $parent The object responsible for running this script * * @return boolean True on success */ public function install(ComponentAdapter $parent) {} /** * Called on uninstallation * * @param ComponentAdapter $parent The object responsible for running this script */ public function uninstall(ComponentAdapter $parent) { // Get Application object $app = JFactory::getApplication(); // Get The Database object $db = JFactory::getDbo(); // Create a new query object. $query = $db->getQuery(true); // Select ids from fields $query->select($db->quoteName('id')); $query->from($db->quoteName('#__fields')); // Where look context is found $query->where( $db->quoteName('context') . ' = '. $db->quote('com_demo.look') ); $db->setQuery($query); // Execute query to see if context is found $db->execute(); $look_found = $db->getNumRows(); // Now check if there were any rows if ($look_found) { // Since there are load the needed look field ids $look_field_ids = $db->loadColumn(); // Remove look from the field table $look_condition = array( $db->quoteName('context') . ' = '. $db->quote('com_demo.look') ); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__fields')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove look items $look_done = $db->execute(); if ($look_done) { // If successfully remove look add queued success message. $app->enqueueMessage(JText::_('The fields with type (com_demo.look) context was removed from the <b>#__fields</b> table')); } // Also Remove look field values $look_condition = array( $db->quoteName('field_id') . ' IN ('. implode(',', $look_field_ids) .')'); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__fields_values')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove look field values $look_done = $db->execute(); if ($look_done) { // If successfully remove look add queued success message. $app->enqueueMessage(JText::_('The fields values for look was removed from the <b>#__fields_values</b> table')); } } // Create a new query object. $query = $db->getQuery(true); // Select ids from field groups $query->select($db->quoteName('id')); $query->from($db->quoteName('#__fields_groups')); // Where look context is found $query->where( $db->quoteName('context') . ' = '. $db->quote('com_demo.look') ); $db->setQuery($query); // Execute query to see if context is found $db->execute(); $look_found = $db->getNumRows(); // Now check if there were any rows if ($look_found) { // Remove look from the field groups table $look_condition = array( $db->quoteName('context') . ' = '. $db->quote('com_demo.look') ); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__fields_groups')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove look items $look_done = $db->execute(); if ($look_done) { // If successfully remove look add queued success message. $app->enqueueMessage(JText::_('The field groups with type (com_demo.look) context was removed from the <b>#__fields_groups</b> table')); } } // Create a new query object. $query = $db->getQuery(true); // Select id from content type table $query->select($db->quoteName('type_id')); $query->from($db->quoteName('#__content_types')); // Where look alias is found $query->where( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') ); $db->setQuery($query); // Execute query to see if alias is found $db->execute(); $look_found = $db->getNumRows(); // Now check if there were any rows if ($look_found) { // Since there are load the needed look type ids $look_ids = $db->loadColumn(); // Remove look from the content type table $look_condition = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') ); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__content_types')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove look items $look_done = $db->execute(); if ($look_done) { // If successfully remove look add queued success message. $app->enqueueMessage(JText::_('The (com_demo.look) type alias was removed from the <b>#__content_type</b> table')); } // Remove look items from the contentitem tag map table $look_condition = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') ); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__contentitem_tag_map')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove look items $look_done = $db->execute(); if ($look_done) { // If successfully remove look add queued success message. $app->enqueueMessage(JText::_('The (com_demo.look) type alias was removed from the <b>#__contentitem_tag_map</b> table')); } // Remove look items from the ucm content table $look_condition = array( $db->quoteName('core_type_alias') . ' = ' . $db->quote('com_demo.look') ); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__ucm_content')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove look items $look_done = $db->execute(); if ($look_done) { // If successfully removed look add queued success message. $app->enqueueMessage(JText::_('The (com_demo.look) type alias was removed from the <b>#__ucm_content</b> table')); } // Make sure that all the look items are cleared from DB foreach ($look_ids as $look_id) { // Remove look items from the ucm base table $look_condition = array( $db->quoteName('ucm_type_id') . ' = ' . $look_id); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__ucm_base')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove look items $db->execute(); // Remove look items from the ucm history table $look_condition = array( $db->quoteName('ucm_type_id') . ' = ' . $look_id); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__ucm_history')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove look items $db->execute(); } } // Create a new query object. $query = $db->getQuery(true); // Select id from content type table $query->select($db->quoteName('type_id')); $query->from($db->quoteName('#__content_types')); // Where Look alias is found $query->where( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') ); $db->setQuery($query); // Execute query to see if alias is found $db->execute(); $look_found = $db->getNumRows(); // Now check if there were any rows if ($look_found) { // Since there are load the needed look type ids $look_ids = $db->loadColumn(); // Remove Look from the content type table $look_condition = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') ); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__content_types')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove Look items $look_done = $db->execute(); if ($look_done) { // If successfully remove Look add queued success message. $app->enqueueMessage(JText::_('The (com_demo.look) type alias was removed from the <b>#__content_type</b> table')); } // Remove Look items from the contentitem tag map table $look_condition = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') ); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__contentitem_tag_map')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove Look items $look_done = $db->execute(); if ($look_done) { // If successfully remove Look add queued success message. $app->enqueueMessage(JText::_('The (com_demo.look) type alias was removed from the <b>#__contentitem_tag_map</b> table')); } // Remove Look items from the ucm content table $look_condition = array( $db->quoteName('core_type_alias') . ' = ' . $db->quote('com_demo.look') ); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__ucm_content')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove Look items $look_done = $db->execute(); if ($look_done) { // If successfully removed Look add queued success message. $app->enqueueMessage(JText::_('The (com_demo.look) type alias was removed from the <b>#__ucm_content</b> table')); } // Make sure that all the Look items are cleared from DB foreach ($look_ids as $look_id) { // Remove Look items from the ucm base table $look_condition = array( $db->quoteName('ucm_type_id') . ' = ' . $look_id); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__ucm_base')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove Look items $db->execute(); // Remove Look items from the ucm history table $look_condition = array( $db->quoteName('ucm_type_id') . ' = ' . $look_id); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__ucm_history')); $query->where($look_condition); $db->setQuery($query); // Execute the query to remove Look items $db->execute(); } } // If All related items was removed queued success message. $app->enqueueMessage(JText::_('All related items was removed from the <b>#__ucm_base</b> table')); $app->enqueueMessage(JText::_('All related items was removed from the <b>#__ucm_history</b> table')); // Remove demo assets from the assets table $demo_condition = array( $db->quoteName('name') . ' LIKE ' . $db->quote('com_demo%') ); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__assets')); $query->where($demo_condition); $db->setQuery($query); $look_done = $db->execute(); if ($look_done) { // If successfully removed demo add queued success message. $app->enqueueMessage(JText::_('All related items was removed from the <b>#__assets</b> table')); } // Get the biggest rule column in the assets table at this point. // $get_rule_length = "SELECT CHAR_LENGTH(`rules`) as rule_size FROM #__assets ORDER BY rule_size DESC LIMIT 1"; // $db->setQuery($get_rule_length); // if ($db->execute()) // { // $rule_length = $db->loadResult(); // // Check the size of the rules column // if ($rule_length < 5120) // { // // Revert the assets table rules column back to the default // $revert_rule = "ALTER TABLE `#__assets` CHANGE `rules` `rules` varchar(5120) NOT NULL COMMENT 'JSON encoded access control.';"; // $db->setQuery($revert_rule); // $db->execute(); // $app->enqueueMessage(JText::_('Reverted the <b>#__assets</b> table rules column back to its default size of varchar(5120)')); // } // else // { // $app->enqueueMessage(JText::_('Could not revert the <b>#__assets</b> table rules column back to its default size of varchar(5120), since there is still one or more components that still requires the column to be larger.')); // } // } // Set db if not set already. if (!isset($db)) { $db = JFactory::getDbo(); } // Set app if not set already. if (!isset($app)) { $app = JFactory::getApplication(); } // Remove Demo from the action_logs_extensions table $demo_action_logs_extensions = array( $db->quoteName('extension') . ' = ' . $db->quote('com_demo') ); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__action_logs_extensions')); $query->where($demo_action_logs_extensions); $db->setQuery($query); // Execute the query to remove Demo $demo_removed_done = $db->execute(); if ($demo_removed_done) { // If successfully remove Demo add queued success message. $app->enqueueMessage(JText::_('The com_demo extension was removed from the <b>#__action_logs_extensions</b> table')); } // Set db if not set already. if (!isset($db)) { $db = JFactory::getDbo(); } // Set app if not set already. if (!isset($app)) { $app = JFactory::getApplication(); } // Remove Demo Look from the action_log_config table $look_action_log_config = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_demo.look') ); // Create a new query object. $query = $db->getQuery(true); $query->delete($db->quoteName('#__action_log_config')); $query->where($look_action_log_config); $db->setQuery($query); // Execute the query to remove com_demo.look $look_action_log_config_done = $db->execute(); if ($look_action_log_config_done) { // If successfully removed Demo Look add queued success message. $app->enqueueMessage(JText::_('The com_demo.look type alias was removed from the <b>#__action_log_config</b> table')); } // little notice as after service, in case of bad experience with component. echo '<h2>Did something go wrong? Are you disappointed?</h2> <p>Please let me know at <a href="mailto:joomla@vdm.io">joomla@vdm.io</a>. <br />We at Vast Development Method are committed to building extensions that performs proficiently! You can help us, really! <br />Send me your thoughts on improvements that is needed, trust me, I will be very grateful! <br />Visit us at <a href="https://www.vdm.io/" target="_blank">https://www.vdm.io/</a> today!</p>'; } /** * Called on update * * @param ComponentAdapter $parent The object responsible for running this script * * @return boolean True on success */ public function update(ComponentAdapter $parent){} /** * Called before any type of action * * @param string $type Which action is happening (install|uninstall|discover_install|update) * @param ComponentAdapter $parent The object responsible for running this script * * @return boolean True on success */ public function preflight($type, ComponentAdapter $parent) { // get application $app = JFactory::getApplication(); // is redundant or so it seems ...hmmm let me know if it works again if ($type === 'uninstall') { return true; } // the default for both install and update $jversion = new JVersion(); if (!$jversion->isCompatible('3.8.0')) { $app->enqueueMessage('Please upgrade to at least Joomla! 3.8.0 before continuing!', 'error'); return false; } // do any updates needed if ($type === 'update') { } // do any install needed if ($type === 'install') { } // check if the PHPExcel stuff is still around if (File::exists(JPATH_ADMINISTRATOR . '/components/com_demo/helpers/PHPExcel.php')) { // We need to remove this old PHPExcel folder $this->removeFolder(JPATH_ADMINISTRATOR . '/components/com_demo/helpers/PHPExcel'); // We need to remove this old PHPExcel file File::delete(JPATH_ADMINISTRATOR . '/components/com_demo/helpers/PHPExcel.php'); } return true; } /** * Called after any type of action * * @param string $type Which action is happening (install|uninstall|discover_install|update) * @param ComponentAdapter $parent The object responsible for running this script * * @return boolean True on success */ public function postflight($type, ComponentAdapter $parent) { // get application $app = JFactory::getApplication(); // We check if we have dynamic folders to copy $this->setDynamicF0ld3rs($app, $parent); // set the default component settings if ($type === 'install') { // Get The Database object $db = JFactory::getDbo(); // Create the look content type object. // $look = new stdClass(); // $look->type_title = 'Demo Look'; // $look->type_alias = 'com_demo.look'; // $look->table = '{"special": {"dbtable": "#__demo_look","key": "id","type": "Look","prefix": "demoTable","config": "array()"},"common": {"dbtable": "#__ucm_content","key": "ucm_id","type": "Corecontent","prefix": "JTable","config": "array()"}}'; // $look->field_mappings = '{"common": {"core_content_item_id": "id","core_title": "name","core_state": "published","core_alias": "alias","core_created_time": "created","core_modified_time": "modified","core_body": "null","core_hits": "hits","core_publish_up": "null","core_publish_down": "null","core_access": "access","core_params": "params","core_featured": "null","core_metadata": "metadata","core_language": "null","core_images": "null","core_urls": "null","core_version": "version","core_ordering": "ordering","core_metakey": "metakey","core_metadesc": "metadesc","core_catid": "null","core_xreference": "null","asset_id": "asset_id"},"special": {"name":"name","description":"description","website":"website","image":"image","dateofbirth":"dateofbirth","mobile_phone":"mobile_phone","email":"email","add":"add","alias":"alias"}}'; // $look->router = 'DemoHelperRoute::getLookRoute'; // $look->content_history_options = '{"formFile": "administrator/components/com_demo/models/forms/look.xml","hideFields": ["asset_id","checked_out","checked_out_time","version"],"ignoreChanges": ["modified_by","modified","checked_out","checked_out_time","version","hits"],"convertToInt": ["published","ordering","add"],"displayLookup": [{"sourceColumn": "created_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "access","targetTable": "#__viewlevels","targetColumn": "id","displayColumn": "title"},{"sourceColumn": "modified_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"}]}'; // // Set the object into the content types table. // $look_Inserted = $db->insertObject('#__content_types', $look); // // Install the global extenstion assets permission. // $query = $db->getQuery(true); // // Field to update. // $fields = array( // $db->quoteName('rules') . ' = ' . $db->quote('{"site.looks.access":{"1":1}}'), // ); // // Condition. // $conditions = array( // $db->quoteName('name') . ' = ' . $db->quote('com_demo') // ); // $query->update($db->quoteName('#__assets'))->set($fields)->where($conditions); // $db->setQuery($query); // $allDone = $db->execute(); // Install the global extension params. $query = $db->getQuery(true); // Field to update. $fields = array( $db->quoteName('params') . ' = ' . $db->quote('{"autorName":"Llewellyn van der Merwe","autorEmail":"joomla@vdm.io","check_in":"-1 day","save_history":"1","history_limit":"10","uikit_load":"1","uikit_min":"","uikit_style":""}'), ); // Condition. $conditions = array( $db->quoteName('element') . ' = ' . $db->quote('com_demo') ); $query->update($db->quoteName('#__extensions'))->set($fields)->where($conditions); $db->setQuery($query); $allDone = $db->execute(); // Get Application object $app = JFactory::getApplication(); $app->enqueueMessage('This is a demo component developed in <a href="http://vdm.bz/component-builder" taget="_balnk" title="Joomla Component Builder">JCB</a>! You can build more components like this with JCB, checkout our page on <a href="https://github.com/vdm-io/Joomla-Component-Builder" taget="_balnk" title="Joomla Component Builder">github</a> for more info. The future of <a href="http://vdm.bz/component-builder" taget="_balnk" title="Joomla Component Builder">Joomla Component Development</a> is Here!', 'Info'); // Get the biggest rule column in the assets table at this point. // $get_rule_length = "SELECT CHAR_LENGTH(`rules`) as rule_size FROM #__assets ORDER BY rule_size DESC LIMIT 1"; // $db->setQuery($get_rule_length); // if ($db->execute()) // { // $rule_length = $db->loadResult(); // // Check the size of the rules column // if ($rule_length <= 5600) // { // // Fix the assets table rules column size // $fix_rules_size = "ALTER TABLE `#__assets` CHANGE `rules` `rules` TEXT NOT NULL COMMENT 'JSON encoded access control. Enlarged to TEXT by JCB';"; // $db->setQuery($fix_rules_size); // $db->execute(); // $app->enqueueMessage(JText::_('The <b>#__assets</b> table rules column was resized to the TEXT datatype for the components possible large permission rules.')); // } // } // echo '<a target="_blank" href="https://www.vdm.io/" title="Demo"> // <img src="components/com_demo/assets/images/vdm-component.jpg"/> // </a>'; // // Set db if not set already. // if (!isset($db)) // { // $db = JFactory::getDbo(); // } // // Create the demo action logs extensions object. // $demo_action_logs_extensions = new stdClass(); // $demo_action_logs_extensions->extension = 'com_demo'; // Set the object into the action logs extensions table. // $demo_action_logs_extensions_Inserted = $db->insertObject('#__action_logs_extensions', $demo_action_logs_extensions); // // Set db if not set already. // if (!isset($db)) // { // $db = JFactory::getDbo(); // } // // Create the look action log config object. // $look_action_log_config = new stdClass(); // $look_action_log_config->type_title = 'LOOK'; // $look_action_log_config->type_alias = 'com_demo.look'; // $look_action_log_config->id_holder = 'id'; // $look_action_log_config->title_holder = 'name'; // $look_action_log_config->table_name = '#__demo_look'; // $look_action_log_config->text_prefix = 'COM_DEMO'; // // Set the object into the action log config table. // $look_Inserted = $db->insertObject('#__action_log_config', $look_action_log_config); } // do any updates needed if ($type === 'update') { // Get The Database object // $db = JFactory::getDbo(); // // Create the look content type object. // $look = new stdClass(); // $look->type_title = 'Demo Look'; // $look->type_alias = 'com_demo.look'; // $look->table = '{"special": {"dbtable": "#__demo_look","key": "id","type": "Look","prefix": "demoTable","config": "array()"},"common": {"dbtable": "#__ucm_content","key": "ucm_id","type": "Corecontent","prefix": "JTable","config": "array()"}}'; // $look->field_mappings = '{"common": {"core_content_item_id": "id","core_title": "name","core_state": "published","core_alias": "alias","core_created_time": "created","core_modified_time": "modified","core_body": "null","core_hits": "hits","core_publish_up": "null","core_publish_down": "null","core_access": "access","core_params": "params","core_featured": "null","core_metadata": "metadata","core_language": "null","core_images": "null","core_urls": "null","core_version": "version","core_ordering": "ordering","core_metakey": "metakey","core_metadesc": "metadesc","core_catid": "null","core_xreference": "null","asset_id": "asset_id"},"special": {"name":"name","description":"description","website":"website","image":"image","dateofbirth":"dateofbirth","mobile_phone":"mobile_phone","email":"email","add":"add","alias":"alias"}}'; // $look->router = 'DemoHelperRoute::getLookRoute'; // $look->content_history_options = '{"formFile": "administrator/components/com_demo/models/forms/look.xml","hideFields": ["asset_id","checked_out","checked_out_time","version"],"ignoreChanges": ["modified_by","modified","checked_out","checked_out_time","version","hits"],"convertToInt": ["published","ordering","add"],"displayLookup": [{"sourceColumn": "created_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "access","targetTable": "#__viewlevels","targetColumn": "id","displayColumn": "title"},{"sourceColumn": "modified_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"}]}'; // // Check if look type is already in content_type DB. // $look_id = null; // $query = $db->getQuery(true); // $query->select($db->quoteName(array('type_id'))); // $query->from($db->quoteName('#__content_types')); // $query->where($db->quoteName('type_alias') . ' LIKE '. $db->quote($look->type_alias)); // $db->setQuery($query); // $db->execute(); // // Set the object into the content types table. // if ($db->getNumRows()) // { // $look->type_id = $db->loadResult(); // $look_Updated = $db->updateObject('#__content_types', $look, 'type_id'); // } // else // { // $look_Inserted = $db->insertObject('#__content_types', $look); // } echo '<a target="_blank" href="https://www.vdm.io/" title="Demo"> <img src="components/com_demo/assets/images/vdm-component.jpg"/> </a> <h3>Upgrade to Version 2.0.3 Was Successful! Let us know if anything is not working as expected.</h3>'; // Set db if not set already. // if (!isset($db)) // { // $db = JFactory::getDbo(); // } // // Create the demo action logs extensions object. // $demo_action_logs_extensions = new stdClass(); // $demo_action_logs_extensions->extension = 'com_demo'; // // Check if demo action log extension is already in action logs extensions DB. // $query = $db->getQuery(true); // $query->select($db->quoteName(array('id'))); // $query->from($db->quoteName('#__action_logs_extensions')); // $query->where($db->quoteName('extension') . ' LIKE '. $db->quote($demo_action_logs_extensions->extension)); // $db->setQuery($query); // $db->execute(); // // Set the object into the action logs extensions table if not found. // if (!$db->getNumRows()) // { // $demo_action_logs_extensions_Inserted = $db->insertObject('#__action_logs_extensions', $demo_action_logs_extensions); // } // // Set db if not set already. // if (!isset($db)) // { // $db = JFactory::getDbo(); // } // // Create the look action log config object. // $look_action_log_config = new stdClass(); // $look_action_log_config->id = null; // $look_action_log_config->type_title = 'LOOK'; // $look_action_log_config->type_alias = 'com_demo.look'; // $look_action_log_config->id_holder = 'id'; // $look_action_log_config->title_holder = 'name'; // $look_action_log_config->table_name = '#__demo_look'; // $look_action_log_config->text_prefix = 'COM_DEMO'; // // Check if look action log config is already in action_log_config DB. // $query = $db->getQuery(true); // $query->select($db->quoteName(array('id'))); // $query->from($db->quoteName('#__action_log_config')); // $query->where($db->quoteName('type_alias') . ' LIKE '. $db->quote($look_action_log_config->type_alias)); // $db->setQuery($query); // $db->execute(); // // Set the object into the content types table. // if ($db->getNumRows()) // { // $look_action_log_config->id = $db->loadResult(); // $look_action_log_config_Updated = $db->updateObject('#__action_log_config', $look_action_log_config, 'id'); // } // else // { // $look_action_log_config_Inserted = $db->insertObject('#__action_log_config', $look_action_log_config); // } } return true; } /** * Remove folders with files * * @param string $dir The path to folder to remove * @param boolean $ignore The folders and files to ignore and not remove * * @return boolean True in all is removed * */ protected function removeFolder($dir, $ignore = false) { if (Folder::exists($dir)) { $it = new RecursiveDirectoryIterator($dir); $it = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST); // remove ending / $dir = rtrim($dir, '/'); // now loop the files & folders foreach ($it as $file) { if ('.' === $file->getBasename() || '..' === $file->getBasename()) continue; // set file dir $file_dir = $file->getPathname(); // check if this is a dir or a file if ($file->isDir()) { $keeper = false; if ($this->checkArray($ignore)) { foreach ($ignore as $keep) { if (strpos($file_dir, $dir.'/'.$keep) !== false) { $keeper = true; } } } if ($keeper) { continue; } Folder::delete($file_dir); } else { $keeper = false; if ($this->checkArray($ignore)) { foreach ($ignore as $keep) { if (strpos($file_dir, $dir.'/'.$keep) !== false) { $keeper = true; } } } if ($keeper) { continue; } File::delete($file_dir); } } // delete the root folder if not ignore found if (!$this->checkArray($ignore)) { return Folder::delete($dir); } return true; } return false; } /** * Check if have an array with a length * * @input array The array to check * * @returns bool/int number of items in array on success */ protected function checkArray($array, $removeEmptyString = false) { if (isset($array) && is_array($array) && ($nr = count((array)$array)) > 0) { // also make sure the empty strings are removed if ($removeEmptyString) { foreach ($array as $key => $string) { if (empty($string)) { unset($array[$key]); } } return $this->checkArray($array, false); } return $nr; } return false; } /** * Method to set/copy dynamic folders into place (use with caution) * * @return void */ protected function setDynamicF0ld3rs($app, $parent) { // get the instalation path $installer = $parent->getParent(); $installPath = $installer->getPath('source'); // get all the folders $folders = Folder::folders($installPath); // check if we have folders we may want to copy $doNotCopy = array('media','admin','site'); // Joomla already deals with these if (count((array) $folders) > 1) { foreach ($folders as $folder) { // Only copy if not a standard folders if (!in_array($folder, $doNotCopy)) { // set the source path $src = $installPath.'/'.$folder; // set the destination path $dest = JPATH_ROOT.'/'.$folder; // now try to copy the folder if (!Folder::copy($src, $dest, '', true)) { $app->enqueueMessage('Could not copy '.$folder.' folder into place, please make sure destination is writable!', 'error'); } } } } } }
micker commented 2022-02-16 15:03:54 +00:00 (Migrated from github.com)
Author
Owner

hello did you have some news about j4 compatibility ?

hello did you have some news about j4 compatibility ?
Author
Owner

Honestly there is not that much to do to get JCB to build legacy components for Joomla 4

We need the new router implementation and a few GUI tweaks.

There are also some integration issues with tags, history and categories to resolve.

I was very sure to have it finished before the end of last year, but one of my larges clients was not willing to wait any longer for JCB (in Joomla 4), and so I had to prioritize my time. I therefore build their new very large application in J3... this was a loss for JCB, since I to this day work on JCB as my own priorities dictates the need.

Yet we have suggested a working group to help take the small needed steps to slowly move JCB to Joomla 4.

There is also this serious reality that moving to native Joomla 4 is much more attractive to me, to skip the legacy step all together. This because of the new Powers area in JCB-pro as it allows for much better PHP conventions and best practices way beyond what we have now. Yet this path is a far larger task, and yet another reason for me to not wast time going legacy... lets just go native strait away.

The new native way of building components in Joomla 4 has much less work in terms of code needed to achieve the same in Joomla 3. But it is a complete different architecture and many of the smart advance features we have in JCB today will probably be lost initially... But I can tell you I am very exited about JCB as I firmly believe the best is yet to come... all things of real value takes time, so I am not willing to do some quick fix just to result in more regret.... JCB has always aimed at native Joomla implementation.

Honestly there is not that much to do to get JCB to build legacy components for Joomla 4 We need the new router implementation and a few GUI tweaks. There are also some integration issues with tags, history and categories to resolve. I was very sure to have it finished before the end of last year, but one of my larges clients was not willing to wait any longer for JCB (in Joomla 4), and so I had to prioritize my time. I therefore build their new very large application in J3... this was a loss for JCB, since I to this day work on JCB as my own priorities dictates the need. Yet we have suggested a working group to help take the small needed steps to slowly move JCB to Joomla 4. There is also this serious reality that moving to native Joomla 4 is much more attractive to me, to skip the legacy step all together. This because of the new Powers area in JCB-pro as it allows for much better PHP conventions and best practices way beyond what we have now. Yet this path is a far larger task, and yet another reason for me to not wast time going legacy... lets just go native strait away. The new native way of building components in Joomla 4 has much less work in terms of code needed to achieve the same in Joomla 3. But it is a complete different architecture and many of the smart advance features we have in JCB today will probably be lost initially... But I can tell you I am very exited about JCB as I firmly believe the best is yet to come... all things of real value takes time, so I am not willing to do some quick fix just to result in more regret.... JCB has always aimed at native Joomla implementation.
stutteringp0et commented 2022-05-27 20:56:24 +00:00 (Migrated from github.com)
Author
Owner

Wondering what the current state of J4 compatibility is. This last update from @Llewellynvdm was over 3 months ago, and if there has been progress - I'd hate to duplicate or undermine it with my meddling.

I have 2 projects that I would dearly love to implement in J4 instead of planning for migration - so I wonder what might be done to assist. I have contributed before, and I think I'm listed as a contributor (the pretty print PHP module requirement for XML generation is my fault :P ).

I see where @Llewellynvdm wants to skip legacy, but that seems far away...I don't see that progress anywhere in the issues. I do see that I was nominated for testing - which I accept....but I don't see anything to test.

Basically, I'm asking - if I were to offer an immediate and significant amount of time toward J4 compatibility (legacy or pure j4) - where would that time best be spent. In the long run, a J4 compatible JCB is going to benefit me more in time than building the components outside of JCB.

Put me in the game coach!

Wondering what the current state of J4 compatibility is. This last update from @Llewellynvdm was over 3 months ago, and if there has been progress - I'd hate to duplicate or undermine it with my meddling. I have 2 projects that I would dearly love to implement in J4 instead of planning for migration - so I wonder what might be done to assist. I have contributed before, and I think I'm listed as a contributor (the pretty print PHP module requirement for XML generation is my fault :P ). I see where @Llewellynvdm wants to skip legacy, but that seems far away...I don't see that progress anywhere in the issues. I do see that I was nominated for testing - which I accept....but I don't see anything to test. Basically, I'm asking - if I were to offer an immediate and significant amount of time toward J4 compatibility (legacy or pure j4) - where would that time best be spent. In the long run, a J4 compatible JCB is going to benefit me more in time than building the components outside of JCB. Put me in the game coach!
Author
Owner

@stutteringp0et best way to get involved is to join the Telegram channel, and start attending the weekly (that is Mondays) meetings in the Telegram channel.

Reality is I am finding it very hard to explain what I am doing, as the compiler is not your average script. But to put it simple, I am refactoring the compiler into the new Powers area, and so decoupling the Joomla 3 approach to component development. The reality as I am doing this I see thing is the overall JCB architecture that needs change. Like the last release we move the whole MVC classes to extend the new native MVC classes in Joomla. The next I am looking at adding a switch to add namespacing to these classes. But as you know to do this will break most extensions build with JCB that has custom code. So to make this change I am thinking of adding a screening engin that will look at all your custom code going into your extension and making errors or warrnings where you are still using Joomla API without adding use of its namespacing. Yet at the same time I am working on an abstraction layer of the compiler. Yet each time I touch that... is see small issues that must globally change to accommodate these changes. The meanwhile trying to get the implementation path simple for newcomers.

So yes lots of work going into to JCB transition to Joomla 4. Most if which is related to the new power area, this means I need to release the new powers are to the public version if we want to take them along to Joomla 4 ;) to do this we need funding so we opened a donation initiative... which has not really achieved the amount needed. This means that moving the public version of JCB to Joomla 4 may take much longer then the pro version. Which is not what I actually wanted... so any donations toward Joomla 4 development will hasten it going public.

@stutteringp0et since you know the compiler better than most, you are probably able to help me in conversation over the abstraction steps I am taking... so even if you can't make it to the Monday meetings... any time you can give towards some conversation with me on Telegram could proof helpful and even help me identify what your able to do towards this work.

How well do you know the new powers area? have you used it in any way? I have added a new JCB package to the VDM packages called Power Updater this holds the core set of classes already moved to the powers area. This package will grow as we continue. We will also add a package called the compiler... which will hold all the compile classes in a JCB package. Anyway hope this is helpful as an introduction to joining me on this journey.

@stutteringp0et best way to get involved is to join the [Telegram channel](https://t.me/Joomla_component_builder), and start attending the weekly (that is Mondays) meetings in the Telegram channel. Reality is I am finding it very hard to explain what I am doing, as the compiler is not your average script. But to put it simple, I am refactoring the compiler into the new Powers area, and so decoupling the Joomla 3 approach to component development. The reality as I am doing this I see thing is the overall JCB architecture that needs change. Like the last release we move the whole MVC classes to extend the new native MVC classes in Joomla. The next I am looking at adding a switch to add namespacing to these classes. But as you know to do this will break most extensions build with JCB that has custom code. So to make this change I am thinking of adding a screening engin that will look at all your custom code going into your extension and making errors or warrnings where you are still using Joomla API without adding **use** of its namespacing. Yet at the same time I am working on an abstraction layer of the compiler. Yet each time I touch that... is see small issues that must globally change to accommodate these changes. The meanwhile trying to get the implementation path simple for newcomers. So yes lots of work going into to JCB transition to Joomla 4. Most if which is related to the new power area, this means I need to release the new powers are to the public version if we want to take them along to Joomla 4 ;) to do this we need funding so we opened a donation initiative... which has not really achieved the amount needed. This means that moving the public version of JCB to Joomla 4 may take much longer then the pro version. Which is not what I actually wanted... so any donations toward Joomla 4 development will hasten it going public. @stutteringp0et since you know the compiler better than most, you are probably able to help me in conversation over the abstraction steps I am taking... so even if you can't make it to the Monday meetings... any time you can give towards some conversation with me on Telegram could proof helpful and even help me identify what your able to do towards this work. How well do you know the new powers area? have you used it in any way? I have added a new JCB package to the VDM packages called **Power Updater** this holds the core set of classes already moved to the powers area. This package will grow as we continue. We will also add a package called the compiler... which will hold all the compile classes in a JCB package. Anyway hope this is helpful as an introduction to joining me on this journey.
stutteringp0et commented 2022-06-10 02:56:14 +00:00 (Migrated from github.com)
Author
Owner

I'll jump into telegram. I haven't seen the powers area at all. I've only ever seen the public release.

I'll jump into telegram. I haven't seen the powers area at all. I've only ever seen the public release.
stutteringp0et commented 2022-06-10 03:04:31 +00:00 (Migrated from github.com)
Author
Owner

and I threw $100 at the donation initiative

and I threw $100 at the donation initiative
Member

Hi ho -

I have a project I'd really like to build in J4...so I thought I'd spend some time and map out what's holding back JCB install in J4.

First, there's the "doesn't have a default value" error I detailed previously. The fix for that is easy enough. Everywhere in the installation SQL files, where you find "TEXT NOT NULL," replace it with "TEXT NOT NULL DEFAULT '',"

Then there are a lot of insert errors. What I'm seeing is that if an int or tinyint value is default, it's being inserted as an empty string instead of the default value (usually 0, which causes an error on any recent mysql or mariadb server).

Because it's always default values, the easiest thing to do would be to omit the values from the insert statement, but as it's generated programmatically - the solution is probably to insert the default value instead of an empty string.

Once I get past those issues, I hit a 500 error, which reports:
PHP Fatal error: Trait "VDM\Joomla\Utilities" not found in path/administrator/components/com_componentbuilder/helpers/componentbuilder.php on line 75

I'm out of time today, must attend the family (Christmas approaches). I'll return to this, probably tomorrow.

Hi ho - I have a project I'd really like to build in J4...so I thought I'd spend some time and map out what's holding back JCB install in J4. First, there's the "doesn't have a default value" error I detailed previously. The fix for that is easy enough. Everywhere in the installation SQL files, where you find "TEXT NOT NULL," replace it with "TEXT NOT NULL DEFAULT ''," Then there are a lot of insert errors. What I'm seeing is that if an int or tinyint value is default, it's being inserted as an empty string instead of the default value (usually 0, which causes an error on any recent mysql or mariadb server). Because it's always default values, the easiest thing to do would be to omit the values from the insert statement, but as it's generated programmatically - the solution is probably to insert the default value instead of an empty string. Once I get past those issues, I hit a 500 error, which reports: PHP Fatal error: Trait "VDM\Joomla\Utilities" not found in *path*/administrator/components/com_componentbuilder/helpers/componentbuilder.php on line 75 I'm out of time today, must attend the family (Christmas approaches). I'll return to this, probably tomorrow.
Member

Festivities canceled for weather...

So, something happens between the first install and the 2nd, because I don't get the 500 error. I'm assuming that the files are being copied after they're called.

So, it's installed now. Many errors are displayed.

() JROOT/libraries/src/Dispatcher/LegacyComponentDispatcher.php:61

Joomla\CMS\Dispatcher\LegacyComponentDispatcher->dispatch()
JROOT/libraries/src/Component/ComponentHelper.php:355

Joomla\CMS\Component\ComponentHelper::renderComponent() JROOT/libraries/src/Application/AdministratorApplication.php:143

Joomla\CMS\Application\AdministratorApplication->dispatch() JROOT/libraries/src/Application/AdministratorApplication.php:186

Joomla\CMS\Application\AdministratorApplication->doExecute() JROOT/libraries/src/Application/CMSApplication.php:294

Joomla\CMS\Application\CMSApplication->execute() JROOT/administrator/includes/app.php:61

require_once() JROOT/administrator/index.php:32

Festivities canceled for weather... So, something happens between the first install and the 2nd, because I don't get the 500 error. I'm assuming that the files are being copied after they're called. So, it's installed now. Many errors are displayed. () JROOT/libraries/src/Dispatcher/LegacyComponentDispatcher.php:61 Joomla\CMS\Dispatcher\LegacyComponentDispatcher->dispatch() JROOT/libraries/src/Component/ComponentHelper.php:355 Joomla\CMS\Component\ComponentHelper::renderComponent() JROOT/libraries/src/Application/AdministratorApplication.php:143 Joomla\CMS\Application\AdministratorApplication->dispatch() JROOT/libraries/src/Application/AdministratorApplication.php:186 Joomla\CMS\Application\AdministratorApplication->doExecute() JROOT/libraries/src/Application/CMSApplication.php:294 Joomla\CMS\Application\CMSApplication->execute() JROOT/administrator/includes/app.php:61 require_once() JROOT/administrator/index.php:32
Author
Owner

At the moment I am refactoring the compiler, and the result will be that we will be able to build native Joomla 4 extensions.

Not that I mind making little changes to target a legacy kind of approach, I just don't have time.I am going directly for the right solution, and yes it take more work and yet, once I am done we will have the whole compiler in the new POWERS area, you can see some of the work that was already done here:

https://git.vdm.dev/joomla/Component-Builder/src/branch/staging/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler

At the moment I am refactoring the compiler, and the result will be that we will be able to build native Joomla 4 extensions. Not that I mind making little changes to target a legacy kind of approach, I just don't have time.I am going directly for the right solution, and yes it take more work and yet, once I am done we will have the whole compiler in the new POWERS area, you can see some of the work that was already done here: https://git.vdm.dev/joomla/Component-Builder/src/branch/staging/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler
Member

@Llewellyn that's how you're doing it - very impressed!

@Llewellyn that's how you're doing it - very impressed!
Member

@Llewellyn
that is very good news. i am very happy. would you please say when we can see JCB for joomla4? (even beta version)

@Llewellyn that is very good news. i am very happy. would you please say when we can see JCB for joomla4? (even beta version)
Author
Owner

This is the only answer we have at this time:
#964 (comment)

This is the only answer we have at this time: https://git.vdm.dev/joomla/Component-Builder/issues/964#issuecomment-18788
Sign in to join this conversation.
No project
No Assignees
4 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: joomla/Component-Builder#126
No description provided.