Question about "Custom/Espo/Custom/" folder

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Firyo
    Senior Member
    • Jun 2022
    • 134

    Question about "Custom/Espo/Custom/" folder

    Hi there,

    I would like to know where are we (developpers working with Espo) supposed to put the "overrides" we do on the already existant entities / features of EspoCRM or extensions ?
    Until now I put these ones in the "Custom/Espo/Custom" folder.

    But now I'm not sure if it's really the good way to do this.
    I checked the Real estate extension and the "overrides" (like on the "Email") are located in the extension folder.


    Regards,
    Firyo.
  • rabii
    Active Community Member
    • Jun 2016
    • 1250

    #2
    hey,

    if you are developing an extension then you could add your overrides in the extension folder but if you are just customizing the crm then custom folder, moving forward even extensions will be installed under Custom Espo Modules, so custom folder is the correct place by design.

    Cheers
    Rabii
    Web Dev

    Comment

    • Firyo
      Senior Member
      • Jun 2022
      • 134

      #3
      Hi,

      I am currenty developping and maintaining 10 extensions (that are working more or less together).
      Recently I had to create 2 new extensions that are overriding the same entites (same files) like "SalesOrder" or "SalesOrderItem" or "Product"...

      So if I understand well I should put my overrides in the respectives modules folder (either application/espo/modules or custom/espo/module) and not anymore in the "Global" Custom/Espo/Custom folder ?

      Regards,
      Firyo.

      Comment

      • rabii
        Active Community Member
        • Jun 2016
        • 1250

        #4
        I personally would not develop an extension that changes behavior of other extensions as it will be difficult to manage, instead i would consider to add custom functionalities into espo/custom to avoid any conflict or breaking changes issues, however if i am developing an extension that is isolated and only interact with core (crm) then i would use custom/espo/modules (previously i would consider application/espo/modules).

        At the end it will all work just depends on what is best for your to keep things organised and easy to maintain.

        Thanks
        Last edited by rabii; 09-06-2023, 10:28 AM.
        Rabii
        Web Dev

        Comment

        • Firyo
          Senior Member
          • Jun 2022
          • 134

          #5
          Well, currently it isn't working very well with the current "workflow / setup" I have.

          Due to my 2 last extensions I have the following problem (with using the "Custom/Espo/Custom" folder to add / edit already existant features from either EspoCRM or like the Sales Pack).

          In my extensions I have like the "main" one, I'll call it "MainExt" here.
          Previously I needed to add new fields and links to existant entities like "SalesOrder" or "Product".
          The overrides (like in "entityDefs" or "layouts") were placed in the "Custom/Espo/Custom" folder.

          Until now it was okay.

          Recently, I've had to create 2 new extensions that are not mandatories unlike MainExt. I'll call them "OptExt1" and "OptExt2" here.
          Each one also needs to add custom fields / links to already existant entities like "SalesOrder" or "Product".
          Naturally, I've placed the overrides in my already overrided files (like "Custom/Espo/Custom/...entityDefs/SalesOrder.json").

          The problem with that is when I deploy the extension "MainExt" without the "OptExt1" and "OptExt2" I have links in "SalesOrder" (for example) to unknown SQL tables and/or missing ACL or lang.

          If I move each override (from each extension) in their respectives "application/espo/modules/..." or "custom/espo/modules/..." fix this issue ?


          Tell me if something isn't clear.

          Regards,
          Firyo.

          Comment


          • rabii
            rabii commented
            Editing a comment
            in such situation i would think about merging all extensions into one hence all 3 extensions target similar entities it would be better if i could get all 3 extensions merged into one which would solve the issue i guess.

          • rabii
            rabii commented
            Editing a comment
            One thing to note if you have links then i would definitely define those in the extension folder because that would make sense as they are part of the logic of the extension. Just be careful of overriding links that have similar name between extensions that target similar entities.
        • bandtank
          Active Community Member
          • Mar 2017
          • 379

          #6
          I have been trying to do the same thing by modifying the User entity. Placing the files in custom/Modules/<Module>/Resources/... works for some of the changes, but not all.

          For example, adding a new entityDef file for the User entity in custom/Modules/<Module>/Resources/metadata/entityDefs/User.json works as expected. However, adding a layout file to custom/Modules/<Module>/Resources/layouts/User/detail.json does not completely work. The custom layout is visible in the layout manager, but the detail view of a record reflects the default layout. The only way I have found to fix this is to save the layout from the GUI in the layout manager for the User entity, which creates custom/Espo/Custom/Resources/layouts/User/detail.json file.

          I release my module in a controlled environment, which allows me to work around this issue by writing the files directly into custom/Espo/Custom, but you may not be able to do it that way. Regardless, I am still interested in a better solution if one exists.

          This is what I am currently using, which works well:

          PHP Code:
          class AfterInstall
          {
            private \Espo\Core\Container $container;
            private \Espo\ORM\EntityManager $em;
            ...
          
            public function __construct(
              private bool $developerMode = False) {
              ...
            }
          
            public function run(\Espo\Core\Container $container): void {
              $this->container = $container;
              $this->em = $this->container->get('entityManager');
          
              $this->moveFiles();
              ...
            }
          
            #######################
            ## EXISTING ENTITIES ##
            #######################
            private function moveFiles(): void {
              # Copy files for existing entities to custom/Espo/Custom because Espo
              # will not properly handle the changes in custom/Modules. Only
              # fully custom entities can be completely contained within a module.
          
              $basePathSrc = dirname(__FILE__);
              $basePathDst = dirname(__FILE__);
              if($this->developerMode) {
                $basePathSrc .= "/../../site/custom/Espo/Modules/Paragon/";
                $basePathDst .= "/../../site/custom/Espo/Custom/";
              } else {
                $basePathSrc .= "/../../../../../custom/Espo/Modules/Paragon/";
                $basePathDst .= "/../../../../../custom/Espo/Custom/";
              }
          
              foreach($this->getFilesToMove() as $file) {
                mkdir(dirname("{$basePathDst}/{$file}"), 0755, true);
                rename("{$basePathSrc}/{$file}","{$basePathDst}/{$file}");
              }
            }
          
            private function getFilesToMove(): array {
              # User files
              return array(
                "Resources/i18n/en_US/User.json",
                "Resources/metadata/entityDefs/User.json",
                "Resources/metadata/clientDefs/User.json",
                "Resources/layouts/User/listSmall.json",
                "Resources/layouts/User/list.json",
                "Resources/layouts/User/massUpdate.json",
                "Resources/layouts/User/detailSmall.json",
                "Resources/layouts/User/detail.json",
                "Resources/layouts/User/bottomPanelsDetail.json",
              );
            }...
          } 
          
          Last edited by bandtank; 09-11-2023, 09:50 PM.

          Comment

          • Firyo
            Senior Member
            • Jun 2022
            • 134

            #7
            Originally posted by bandtank
            I have been trying to do the same thing by modifying the User entity. Placing the files in custom/Modules/<Module>/Resources/... works for some of the changes, but not all.

            For example, adding a new entityDef file for the User entity in custom/Modules/<Module>/Resources/metadata/entityDefs/User.json works as expected. However, adding a layout file to custom/Modules/<Module>/Resources/layouts/User/detail.json does not completely work. The custom layout is visible in the layout manager, but the detail view of a record reflects the default layout. The only way I have found to fix this is to save the layout from the GUI in the layout manager for the User entity, which creates custom/Espo/Custom/Resources/layouts/User/detail.json file.

            I release my module in a controlled environment, which allows me to work around this issue by writing the files directly into custom/Espo/Custom, but you may not be able to do it that way. Regardless, I am still interested in a better solution if one exists.

            This is what I am currently using, which works well:

            PHP Code:
            class AfterInstall
            {
            private \Espo\Core\Container $container;
            private \Espo\ORM\EntityManager $em;
            ...
            
            public function __construct(
            private bool $developerMode = False) {
            ...
            }
            
            public function run(\Espo\Core\Container $container): void {
            $this->container = $container;
            $this->em = $this->container->get('entityManager');
            
            $this->moveFiles();
            ...
            }
            
            #######################
            ## EXISTING ENTITIES ##
            #######################
            private function moveFiles(): void {
            # Copy files for existing entities to custom/Espo/Custom because Espo
            # will not properly handle the changes in custom/Modules. Only
            # fully custom entities can be completely contained within a module.
            
            $basePathSrc = dirname(__FILE__);
            $basePathDst = dirname(__FILE__);
            if($this->developerMode) {
            $basePathSrc .= "/../../site/custom/Espo/Modules/Paragon/";
            $basePathDst .= "/../../site/custom/Espo/Custom/";
            } else {
            $basePathSrc .= "/../../../../../custom/Espo/Modules/Paragon/";
            $basePathDst .= "/../../../../../custom/Espo/Custom/";
            }
            
            foreach($this->getFilesToMove() as $file) {
            mkdir(dirname("{$basePathDst}/{$file}"), 0755, true);
            rename("{$basePathSrc}/{$file}","{$basePathDst}/{$file}");
            }
            }
            
            private function getFilesToMove(): array {
            # User files
            return array(
            "Resources/i18n/en_US/User.json",
            "Resources/metadata/entityDefs/User.json",
            "Resources/metadata/clientDefs/User.json",
            "Resources/layouts/User/listSmall.json",
            "Resources/layouts/User/list.json",
            "Resources/layouts/User/massUpdate.json",
            "Resources/layouts/User/detailSmall.json",
            "Resources/layouts/User/detail.json",
            "Resources/layouts/User/bottomPanelsDetail.json",
            );
            }...
            } 
            
            Yeah I've discovered that on my end too.

            Why are you doing this in the AfterInstall ? Couldn't you just place the layout files in the custom/Espo/Custom folder directly ?

            Comment

            • bandtank
              Active Community Member
              • Mar 2017
              • 379

              #8
              I think the development and installation processes are simpler if the files are contained in the module, but I can’t remember exactly what my reasons were. Maybe it would work at this point if the files were installed directly in the right place. I’ll try it.

              Comment

              • bandtank
                Active Community Member
                • Mar 2017
                • 379

                #9
                The installation worked with the files in src/custom/Espo/Custom. I am still moving a few files using the code I posted in a previous comment, but many of the files don't need to be moved anymore. Thanks for the suggestion.

                Regarding the original question, I think this is still the best way to do it.

                Comment

                Working...